Commit 6edad161 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (258 commits)
  [libata] conversion to new debug scheme, part 1 of $N
  [PATCH] libata: Add ata_scsi_dev_disabled
  [libata] Add host lock to struct ata_port
  [PATCH] libata: implement per-dev EH action mask eh_info->dev_action[]
  [PATCH] libata-dev: move the CDB-intr DMA blacklisting
  [PATCH] ahci: disable NCQ support on vt8251
  [libata] ahci: add JMicron PCI IDs
  [libata] sata_nv: add PCI IDs
  [libata] ahci: Add NVIDIA PCI IDs.
  [PATCH] libata: convert several bmdma-style controllers to new EH, take #3
  [PATCH] sata_via: convert to new EH, take #3
  [libata] sata_nv: s/spin_lock_irqsave/spin_lock/ in irq handler
  [PATCH] sata_nv: add hotplug support
  [PATCH] sata_nv: convert to new EH
  [PATCH] sata_nv: better irq handlers
  [PATCH] sata_nv: simplify constants
  [PATCH] sata_nv: kill struct nv_host_desc and nv_host
  [PATCH] sata_nv: kill not-working hotplug code
  [libata] Update docs to reflect current driver API
  [PATCH] libata: add host_set->next for legacy two host_sets case, take #3
  ...
parents 236ee8c3 0dd4b21f
...@@ -169,6 +169,22 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); ...@@ -169,6 +169,22 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
</sect2> </sect2>
<sect2><title>PIO data read/write</title>
<programlisting>
void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
</programlisting>
<para>
All bmdma-style drivers must implement this hook. This is the low-level
operation that actually copies the data bytes during a PIO data
transfer.
Typically the driver
will choose one of ata_pio_data_xfer_noirq(), ata_pio_data_xfer(), or
ata_mmio_data_xfer().
</para>
</sect2>
<sect2><title>ATA command execute</title> <sect2><title>ATA command execute</title>
<programlisting> <programlisting>
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
...@@ -204,11 +220,10 @@ command. ...@@ -204,11 +220,10 @@ command.
<programlisting> <programlisting>
u8 (*check_status)(struct ata_port *ap); u8 (*check_status)(struct ata_port *ap);
u8 (*check_altstatus)(struct ata_port *ap); u8 (*check_altstatus)(struct ata_port *ap);
u8 (*check_err)(struct ata_port *ap);
</programlisting> </programlisting>
<para> <para>
Reads the Status/AltStatus/Error ATA shadow register from Reads the Status/AltStatus ATA shadow register from
hardware. On some hardware, reading the Status register has hardware. On some hardware, reading the Status register has
the side effect of clearing the interrupt condition. the side effect of clearing the interrupt condition.
Most drivers for taskfile-based hardware use Most drivers for taskfile-based hardware use
...@@ -269,23 +284,6 @@ void (*set_mode) (struct ata_port *ap); ...@@ -269,23 +284,6 @@ void (*set_mode) (struct ata_port *ap);
</sect2> </sect2>
<sect2><title>Reset ATA bus</title>
<programlisting>
void (*phy_reset) (struct ata_port *ap);
</programlisting>
<para>
The very first step in the probe phase. Actions vary depending
on the bus type, typically. After waking up the device and probing
for device presence (PATA and SATA), typically a soft reset
(SRST) will be performed. Drivers typically use the helper
functions ata_bus_reset() or sata_phy_reset() for this hook.
Many SATA drivers use sata_phy_reset() or call it from within
their own phy_reset() functions.
</para>
</sect2>
<sect2><title>Control PCI IDE BMDMA engine</title> <sect2><title>Control PCI IDE BMDMA engine</title>
<programlisting> <programlisting>
void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_setup) (struct ata_queued_cmd *qc);
...@@ -354,16 +352,74 @@ int (*qc_issue) (struct ata_queued_cmd *qc); ...@@ -354,16 +352,74 @@ int (*qc_issue) (struct ata_queued_cmd *qc);
</sect2> </sect2>
<sect2><title>Timeout (error) handling</title> <sect2><title>Exception and probe handling (EH)</title>
<programlisting> <programlisting>
void (*eng_timeout) (struct ata_port *ap); void (*eng_timeout) (struct ata_port *ap);
void (*phy_reset) (struct ata_port *ap);
</programlisting>
<para>
Deprecated. Use ->error_handler() instead.
</para>
<programlisting>
void (*freeze) (struct ata_port *ap);
void (*thaw) (struct ata_port *ap);
</programlisting>
<para>
ata_port_freeze() is called when HSM violations or some other
condition disrupts normal operation of the port. A frozen port
is not allowed to perform any operation until the port is
thawed, which usually follows a successful reset.
</para>
<para>
The optional ->freeze() callback can be used for freezing the port
hardware-wise (e.g. mask interrupt and stop DMA engine). If a
port cannot be frozen hardware-wise, the interrupt handler
must ack and clear interrupts unconditionally while the port
is frozen.
</para>
<para>
The optional ->thaw() callback is called to perform the opposite of ->freeze():
prepare the port for normal operation once again. Unmask interrupts,
start DMA engine, etc.
</para>
<programlisting>
void (*error_handler) (struct ata_port *ap);
</programlisting>
<para>
->error_handler() is a driver's hook into probe, hotplug, and recovery
and other exceptional conditions. The primary responsibility of an
implementation is to call ata_do_eh() or ata_bmdma_drive_eh() with a set
of EH hooks as arguments:
</para>
<para>
'prereset' hook (may be NULL) is called during an EH reset, before any other actions
are taken.
</para>
<para>
'postreset' hook (may be NULL) is called after the EH reset is performed. Based on
existing conditions, severity of the problem, and hardware capabilities,
</para>
<para>
Either 'softreset' (may be NULL) or 'hardreset' (may be NULL) will be
called to perform the low-level EH reset.
</para>
<programlisting>
void (*post_internal_cmd) (struct ata_queued_cmd *qc);
</programlisting> </programlisting>
<para> <para>
This is a high level error handling function, called from the Perform any hardware-specific actions necessary to finish processing
error handling thread, when a command times out. Most newer after executing a probe-time or EH-time command via ata_exec_internal().
hardware will implement its own error handling code here. IDE BMDMA
drivers may use the helper function ata_eng_timeout().
</para> </para>
</sect2> </sect2>
......
...@@ -74,6 +74,7 @@ static struct amd_ide_chip { ...@@ -74,6 +74,7 @@ static struct amd_ide_chip {
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 }, { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 },
{ 0 } { 0 }
}; };
...@@ -488,7 +489,8 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { ...@@ -488,7 +489,8 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"), /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"), /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"), /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"),
/* 17 */ DECLARE_AMD_DEV("AMD5536"), /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
/* 18 */ DECLARE_AMD_DEV("AMD5536"),
}; };
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
...@@ -525,7 +527,8 @@ static struct pci_device_id amd74xx_pci_tbl[] = { ...@@ -525,7 +527,8 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
{ 0, }, { 0, },
}; };
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
......
...@@ -165,7 +165,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ ...@@ -165,7 +165,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
zalon7xx-objs := zalon.o ncr53c8xx.o zalon7xx-objs := zalon.o ncr53c8xx.o
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o
oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o
# Files generated that shall be removed upon make clean # Files generated that shall be removed upon make clean
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "ahci" #define DRV_NAME "ahci"
#define DRV_VERSION "1.2" #define DRV_VERSION "1.3"
enum { enum {
...@@ -56,12 +56,15 @@ enum { ...@@ -56,12 +56,15 @@ enum {
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 = 0, AHCI_USE_CLUSTERING = 0,
AHCI_CMD_SLOT_SZ = 32 * 32, AHCI_MAX_CMDS = 32,
AHCI_CMD_SZ = 32,
AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
AHCI_RX_FIS_SZ = 256, AHCI_RX_FIS_SZ = 256,
AHCI_CMD_TBL_HDR = 0x80,
AHCI_CMD_TBL_CDB = 0x40, AHCI_CMD_TBL_CDB = 0x40,
AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16), AHCI_CMD_TBL_HDR_SZ = 0x80,
AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ + AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
AHCI_RX_FIS_SZ, AHCI_RX_FIS_SZ,
AHCI_IRQ_ON_SG = (1 << 31), AHCI_IRQ_ON_SG = (1 << 31),
AHCI_CMD_ATAPI = (1 << 5), AHCI_CMD_ATAPI = (1 << 5),
...@@ -71,8 +74,10 @@ enum { ...@@ -71,8 +74,10 @@ enum {
AHCI_CMD_CLR_BUSY = (1 << 10), AHCI_CMD_CLR_BUSY = (1 << 10),
RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
board_ahci = 0, board_ahci = 0,
board_ahci_vt8251 = 1,
/* global controller registers */ /* global controller registers */
HOST_CAP = 0x00, /* host capabilities */ HOST_CAP = 0x00, /* host capabilities */
...@@ -87,8 +92,9 @@ enum { ...@@ -87,8 +92,9 @@ enum {
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
/* HOST_CAP bits */ /* HOST_CAP bits */
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
HOST_CAP_CLO = (1 << 24), /* Command List Override support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */
HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
/* registers for each SATA port */ /* registers for each SATA port */
PORT_LST_ADDR = 0x00, /* command list DMA addr */ PORT_LST_ADDR = 0x00, /* command list DMA addr */
...@@ -127,15 +133,17 @@ enum { ...@@ -127,15 +133,17 @@ enum {
PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */ PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */ PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
PORT_IRQ_FATAL = PORT_IRQ_TF_ERR | PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR |
PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_CONNECT |
PORT_IRQ_IF_ERR, PORT_IRQ_PHYRDY |
DEF_PORT_IRQ = PORT_IRQ_FATAL | PORT_IRQ_PHYRDY | PORT_IRQ_UNK_FIS,
PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE | PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS | PORT_IRQ_TF_ERR |
PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS | PORT_IRQ_HBUS_DATA_ERR,
PORT_IRQ_D2H_REG_FIS, DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
/* PORT_CMD bits */ /* PORT_CMD bits */
PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
...@@ -153,6 +161,10 @@ enum { ...@@ -153,6 +161,10 @@ enum {
/* hpriv->flags bits */ /* hpriv->flags bits */
AHCI_FLAG_MSI = (1 << 0), AHCI_FLAG_MSI = (1 << 0),
/* ap->flags bits */
AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24),
AHCI_FLAG_NO_NCQ = (1 << 25),
}; };
struct ahci_cmd_hdr { struct ahci_cmd_hdr {
...@@ -181,7 +193,6 @@ struct ahci_port_priv { ...@@ -181,7 +193,6 @@ struct ahci_port_priv {
dma_addr_t cmd_slot_dma; dma_addr_t cmd_slot_dma;
void *cmd_tbl; void *cmd_tbl;
dma_addr_t cmd_tbl_dma; dma_addr_t cmd_tbl_dma;
struct ahci_sg *cmd_tbl_sg;
void *rx_fis; void *rx_fis;
dma_addr_t rx_fis_dma; dma_addr_t rx_fis_dma;
}; };
...@@ -191,15 +202,16 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); ...@@ -191,15 +202,16 @@ static void 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 irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
static void ahci_irq_clear(struct ata_port *ap); static void ahci_irq_clear(struct ata_port *ap);
static void ahci_eng_timeout(struct ata_port *ap);
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_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 u8 ahci_check_status(struct ata_port *ap);
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static void ahci_freeze(struct ata_port *ap);
static void ahci_thaw(struct ata_port *ap);
static void ahci_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
static void ahci_remove_one (struct pci_dev *pdev); static void ahci_remove_one (struct pci_dev *pdev);
static struct scsi_host_template ahci_sht = { static struct scsi_host_template ahci_sht = {
...@@ -207,7 +219,8 @@ static struct scsi_host_template ahci_sht = { ...@@ -207,7 +219,8 @@ static struct scsi_host_template ahci_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE, .change_queue_depth = ata_scsi_change_queue_depth,
.can_queue = AHCI_MAX_CMDS - 1,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = AHCI_MAX_SG, .sg_tablesize = AHCI_MAX_SG,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
...@@ -216,6 +229,7 @@ static struct scsi_host_template ahci_sht = { ...@@ -216,6 +229,7 @@ static struct scsi_host_template ahci_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = AHCI_DMA_BOUNDARY, .dma_boundary = AHCI_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -228,19 +242,21 @@ static const struct ata_port_operations ahci_ops = { ...@@ -228,19 +242,21 @@ static const struct ata_port_operations ahci_ops = {
.tf_read = ahci_tf_read, .tf_read = ahci_tf_read,
.probe_reset = ahci_probe_reset,
.qc_prep = ahci_qc_prep, .qc_prep = ahci_qc_prep,
.qc_issue = ahci_qc_issue, .qc_issue = ahci_qc_issue,
.eng_timeout = ahci_eng_timeout,
.irq_handler = ahci_interrupt, .irq_handler = ahci_interrupt,
.irq_clear = ahci_irq_clear, .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_error_handler,
.post_internal_cmd = ahci_post_internal_cmd,
.port_start = ahci_port_start, .port_start = ahci_port_start,
.port_stop = ahci_port_stop, .port_stop = ahci_port_stop,
}; };
...@@ -250,7 +266,19 @@ static const struct ata_port_info ahci_port_info[] = { ...@@ -250,7 +266,19 @@ static const struct ata_port_info ahci_port_info[] = {
{ {
.sht = &ahci_sht, .sht = &ahci_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_SKIP_D2H_BSY,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops,
},
/* board_ahci_vt8251 */
{
.sht = &ahci_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_SKIP_D2H_BSY |
AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops, .port_ops = &ahci_ops,
...@@ -258,6 +286,7 @@ static const struct ata_port_info ahci_port_info[] = { ...@@ -258,6 +286,7 @@ static const struct ata_port_info ahci_port_info[] = {
}; };
static const struct pci_device_id ahci_pci_tbl[] = { static const struct pci_device_id ahci_pci_tbl[] = {
/* Intel */
{ PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH6 */ board_ahci }, /* ICH6 */
{ PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
...@@ -288,14 +317,39 @@ static const struct pci_device_id ahci_pci_tbl[] = { ...@@ -288,14 +317,39 @@ static const struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* ICH8M */ board_ahci }, /* ICH8M */
{ PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH8M */ board_ahci }, /* ICH8M */
/* JMicron */
{ 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* JMicron JMB360 */ board_ahci }, /* JMicron JMB360 */
{ 0x197b, 0x2361, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* JMicron JMB361 */
{ 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* JMicron JMB363 */ board_ahci }, /* JMicron JMB363 */
{ 0x197b, 0x2365, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* JMicron JMB365 */
{ 0x197b, 0x2366, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* JMicron JMB366 */
/* ATI */
{ PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ATI SB600 non-raid */ board_ahci }, /* ATI SB600 non-raid */
{ PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ATI SB600 raid */ board_ahci }, /* ATI SB600 raid */
/* VIA */
{ PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci_vt8251 }, /* VIA VT8251 */
/* NVIDIA */
{ PCI_VENDOR_ID_NVIDIA, 0x044c, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* MCP65 */
{ PCI_VENDOR_ID_NVIDIA, 0x044d, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* MCP65 */
{ PCI_VENDOR_ID_NVIDIA, 0x044e, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* MCP65 */
{ PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* MCP65 */
{ } /* terminate list */ { } /* terminate list */
}; };
...@@ -374,8 +428,6 @@ static int ahci_port_start(struct ata_port *ap) ...@@ -374,8 +428,6 @@ static int ahci_port_start(struct ata_port *ap)
pp->cmd_tbl = mem; pp->cmd_tbl = mem;
pp->cmd_tbl_dma = mem_dma; pp->cmd_tbl_dma = mem_dma;
pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR;
ap->private_data = pp; ap->private_data = pp;
if (hpriv->cap & HOST_CAP_64) if (hpriv->cap & HOST_CAP_64)
...@@ -508,46 +560,71 @@ static unsigned int ahci_dev_classify(struct ata_port *ap) ...@@ -508,46 +560,71 @@ static unsigned int ahci_dev_classify(struct ata_port *ap)
return ata_dev_classify(&tf); return ata_dev_classify(&tf);
} }
static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
u32 opts)
{ {
pp->cmd_slot[0].opts = cpu_to_le32(opts); dma_addr_t cmd_tbl_dma;
pp->cmd_slot[0].status = 0;
pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff); cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
pp->cmd_slot[tag].opts = cpu_to_le32(opts);
pp->cmd_slot[tag].status = 0;
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);
} }
static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, static int ahci_clo(struct ata_port *ap)
unsigned long interval_msec,
unsigned long timeout_msec)
{ {
unsigned long timeout; void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
struct ahci_host_priv *hpriv = ap->host_set->private_data;
u32 tmp; u32 tmp;
timeout = jiffies + (timeout_msec * HZ) / 1000; if (!(hpriv->cap & HOST_CAP_CLO))
do { return -EOPNOTSUPP;
tmp = readl(reg);
if ((tmp & mask) == val) tmp = readl(port_mmio + PORT_CMD);
tmp |= PORT_CMD_CLO;
writel(tmp, port_mmio + PORT_CMD);
tmp = ata_wait_register(port_mmio + PORT_CMD,
PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
if (tmp & PORT_CMD_CLO)
return -EIO;
return 0; return 0;
msleep(interval_msec); }
} while (time_before(jiffies, timeout));
return -1; static int ahci_prereset(struct ata_port *ap)
{
if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) &&
(ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) {
/* ATA_BUSY hasn't cleared, so send a CLO */
ahci_clo(ap);
}
return ata_std_prereset(ap);
} }
static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) static int ahci_softreset(struct ata_port *ap, unsigned int *class)
{ {
struct ahci_host_priv *hpriv = ap->host_set->private_data;
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
void __iomem *mmio = ap->host_set->mmio_base; void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
const u32 cmd_fis_len = 5; /* five dwords */ const u32 cmd_fis_len = 5; /* five dwords */
const char *reason = NULL; const char *reason = NULL;
struct ata_taskfile tf; struct ata_taskfile tf;
u32 tmp;
u8 *fis; u8 *fis;
int rc; int rc;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
if (ata_port_offline(ap)) {
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_stop_engine(ap); rc = ahci_stop_engine(ap);
if (rc) { if (rc) {
...@@ -558,23 +635,13 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) ...@@ -558,23 +635,13 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
/* check BUSY/DRQ, perform Command List Override if necessary */ /* check BUSY/DRQ, perform Command List Override if necessary */
ahci_tf_read(ap, &tf); ahci_tf_read(ap, &tf);
if (tf.command & (ATA_BUSY | ATA_DRQ)) { if (tf.command & (ATA_BUSY | ATA_DRQ)) {
u32 tmp; rc = ahci_clo(ap);
if (!(hpriv->cap & HOST_CAP_CLO)) { if (rc == -EOPNOTSUPP) {
rc = -EIO; reason = "port busy but CLO unavailable";
reason = "port busy but no CLO";
goto fail_restart; goto fail_restart;
} } else if (rc) {
reason = "port busy but CLO failed";
tmp = readl(port_mmio + PORT_CMD);
tmp |= PORT_CMD_CLO;
writel(tmp, port_mmio + PORT_CMD);
readl(port_mmio + PORT_CMD); /* flush */
if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0,
1, 500)) {
rc = -EIO;
reason = "CLO failed";
goto fail_restart; goto fail_restart;
} }
} }
...@@ -582,20 +649,21 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) ...@@ -582,20 +649,21 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
/* restart engine */ /* restart engine */
ahci_start_engine(ap); ahci_start_engine(ap);
ata_tf_init(ap, &tf, 0); ata_tf_init(ap->device, &tf);
fis = pp->cmd_tbl; fis = pp->cmd_tbl;
/* issue the first D2H Register FIS */ /* issue the first D2H Register FIS */
ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); ahci_fill_cmd_slot(pp, 0,
cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
tf.ctl |= ATA_SRST; tf.ctl |= ATA_SRST;
ata_tf_to_fis(&tf, fis, 0); ata_tf_to_fis(&tf, fis, 0);
fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ fis[1] &= ~(1 << 7); /* turn off Command FIS bit */
writel(1, port_mmio + PORT_CMD_ISSUE); writel(1, port_mmio + PORT_CMD_ISSUE);
readl(port_mmio + PORT_CMD_ISSUE); /* flush */
if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500);
if (tmp & 0x1) {
rc = -EIO; rc = -EIO;
reason = "1st FIS failed"; reason = "1st FIS failed";
goto fail; goto fail;
...@@ -605,7 +673,7 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) ...@@ -605,7 +673,7 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
msleep(1); msleep(1);
/* issue the second D2H Register FIS */ /* issue the second D2H Register FIS */
ahci_fill_cmd_slot(pp, cmd_fis_len); ahci_fill_cmd_slot(pp, 0, cmd_fis_len);
tf.ctl &= ~ATA_SRST; tf.ctl &= ~ATA_SRST;
ata_tf_to_fis(&tf, fis, 0); ata_tf_to_fis(&tf, fis, 0);
...@@ -625,7 +693,7 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) ...@@ -625,7 +693,7 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
msleep(150); msleep(150);
*class = ATA_DEV_NONE; *class = ATA_DEV_NONE;
if (sata_dev_present(ap)) { if (ata_port_online(ap)) {
if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
rc = -EIO; rc = -EIO;
reason = "device not ready"; reason = "device not ready";
...@@ -640,25 +708,31 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) ...@@ -640,25 +708,31 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
fail_restart: fail_restart:
ahci_start_engine(ap); ahci_start_engine(ap);
fail: fail:
if (verbose) ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
printk(KERN_ERR "ata%u: softreset failed (%s)\n",
ap->id, reason);
else
DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason);
return rc; return rc;
} }
static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
{ {
struct ahci_port_priv *pp = ap->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf;
int rc; int rc;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
ahci_stop_engine(ap); ahci_stop_engine(ap);
rc = sata_std_hardreset(ap, verbose, class);
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(ap->device, &tf);
tf.command = 0xff;
ata_tf_to_fis(&tf, d2h_fis, 0);
rc = sata_std_hardreset(ap, class);
ahci_start_engine(ap); ahci_start_engine(ap);
if (rc == 0) if (rc == 0 && ata_port_online(ap))
*class = ahci_dev_classify(ap); *class = ahci_dev_classify(ap);
if (*class == ATA_DEV_UNKNOWN) if (*class == ATA_DEV_UNKNOWN)
*class = ATA_DEV_NONE; *class = ATA_DEV_NONE;
...@@ -686,13 +760,6 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class) ...@@ -686,13 +760,6 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class)
} }
} }
static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes)
{
return ata_drive_probe_reset(ap, ata_std_probeinit,
ahci_softreset, ahci_hardreset,
ahci_postreset, classes);
}
static u8 ahci_check_status(struct ata_port *ap) static u8 ahci_check_status(struct ata_port *ap)
{ {
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
...@@ -708,9 +775,8 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) ...@@ -708,9 +775,8 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
ata_tf_from_fis(d2h_fis, tf); ata_tf_from_fis(d2h_fis, tf);
} }
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
{ {
struct ahci_port_priv *pp = qc->ap->private_data;
struct scatterlist *sg; struct scatterlist *sg;
struct ahci_sg *ahci_sg; struct ahci_sg *ahci_sg;
unsigned int n_sg = 0; unsigned int n_sg = 0;
...@@ -720,7 +786,7 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) ...@@ -720,7 +786,7 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc)
/* /*
* Next, the S/G list. * Next, the S/G list.
*/ */
ahci_sg = pp->cmd_tbl_sg; ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
ata_for_each_sg(sg, qc) { ata_for_each_sg(sg, qc) {
dma_addr_t addr = sg_dma_address(sg); dma_addr_t addr = sg_dma_address(sg);
u32 sg_len = sg_dma_len(sg); u32 sg_len = sg_dma_len(sg);
...@@ -741,6 +807,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ...@@ -741,6 +807,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
int is_atapi = is_atapi_taskfile(&qc->tf); int is_atapi = is_atapi_taskfile(&qc->tf);
void *cmd_tbl;
u32 opts; u32 opts;
const u32 cmd_fis_len = 5; /* five dwords */ const u32 cmd_fis_len = 5; /* five dwords */
unsigned int n_elem; unsigned int n_elem;
...@@ -749,16 +816,17 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ...@@ -749,16 +816,17 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
* Fill in command table information. First, the header, * Fill in command table information. First, the header,
* a SATA Register - Host to Device command FIS. * a SATA Register - Host to Device command FIS.
*/ */
ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0); cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
ata_tf_to_fis(&qc->tf, cmd_tbl, 0);
if (is_atapi) { if (is_atapi) {
memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
qc->dev->cdb_len);
} }
n_elem = 0; n_elem = 0;
if (qc->flags & ATA_QCFLAG_DMAMAP) if (qc->flags & ATA_QCFLAG_DMAMAP)
n_elem = ahci_fill_sg(qc); n_elem = ahci_fill_sg(qc, cmd_tbl);
/* /*
* Fill in command slot information. * Fill in command slot information.
...@@ -769,112 +837,122 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ...@@ -769,112 +837,122 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
if (is_atapi) if (is_atapi)
opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
ahci_fill_cmd_slot(pp, opts); ahci_fill_cmd_slot(pp, qc->tag, opts);
} }
static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
{ {
void __iomem *mmio = ap->host_set->mmio_base; struct ahci_port_priv *pp = ap->private_data;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); struct ata_eh_info *ehi = &ap->eh_info;
u32 tmp; unsigned int err_mask = 0, action = 0;
struct ata_queued_cmd *qc;
u32 serror;
if ((ap->device[0].class != ATA_DEV_ATAPI) || ata_ehi_clear_desc(ehi);
((irq_stat & PORT_IRQ_TF_ERR) == 0))
printk(KERN_WARNING "ata%u: port reset, "
"p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n",
ap->id,
irq_stat,
readl(mmio + HOST_IRQ_STAT),
readl(port_mmio + PORT_IRQ_STAT),
readl(port_mmio + PORT_CMD),
readl(port_mmio + PORT_TFDATA),
readl(port_mmio + PORT_SCR_STAT),
readl(port_mmio + PORT_SCR_ERR));
/* stop DMA */
ahci_stop_engine(ap);
/* clear SATA phy error, if any */ /* AHCI needs SError cleared; otherwise, it might lock up */
tmp = readl(port_mmio + PORT_SCR_ERR); serror = ahci_scr_read(ap, SCR_ERROR);
writel(tmp, port_mmio + PORT_SCR_ERR); ahci_scr_write(ap, SCR_ERROR, serror);
/* if DRQ/BSY is set, device needs to be reset. /* analyze @irq_stat */
* if so, issue COMRESET ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
*/
tmp = readl(port_mmio + PORT_TFDATA); if (irq_stat & PORT_IRQ_TF_ERR)
if (tmp & (ATA_BUSY | ATA_DRQ)) { err_mask |= AC_ERR_DEV;
writel(0x301, port_mmio + PORT_SCR_CTL);
readl(port_mmio + PORT_SCR_CTL); /* flush */ if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
udelay(10); err_mask |= AC_ERR_HOST_BUS;
writel(0x300, port_mmio + PORT_SCR_CTL); action |= ATA_EH_SOFTRESET;
readl(port_mmio + PORT_SCR_CTL); /* flush */
} }
/* re-start DMA */ if (irq_stat & PORT_IRQ_IF_ERR) {
ahci_start_engine(ap); err_mask |= AC_ERR_ATA_BUS;
} action |= ATA_EH_SOFTRESET;
ata_ehi_push_desc(ehi, ", interface fatal error");
}
static void ahci_eng_timeout(struct ata_port *ap) if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
{ ata_ehi_hotplugged(ehi);
struct ata_host_set *host_set = ap->host_set; ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ?
void __iomem *mmio = host_set->mmio_base; "connection status changed" : "PHY RDY changed");
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); }
struct ata_queued_cmd *qc;
unsigned long flags;
printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id); if (irq_stat & PORT_IRQ_UNK_FIS) {
u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
spin_lock_irqsave(&host_set->lock, flags); err_mask |= AC_ERR_HSM;
action |= ATA_EH_SOFTRESET;
ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x",
unk[0], unk[1], unk[2], unk[3]);
}
ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); /* okay, let's hand over to EH */
qc = ata_qc_from_tag(ap, ap->active_tag); ehi->serror |= serror;
qc->err_mask |= AC_ERR_TIMEOUT; ehi->action |= action;
spin_unlock_irqrestore(&host_set->lock, flags); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc)
qc->err_mask |= err_mask;
else
ehi->err_mask |= err_mask;
ata_eh_qc_complete(qc); if (irq_stat & PORT_IRQ_FREEZE)
ata_port_freeze(ap);
else
ata_port_abort(ap);
} }
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) static void ahci_host_intr(struct ata_port *ap)
{ {
void __iomem *mmio = ap->host_set->mmio_base; void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 status, serr, ci; struct ata_eh_info *ehi = &ap->eh_info;
u32 status, qc_active;
serr = readl(port_mmio + PORT_SCR_ERR); int rc;
writel(serr, port_mmio + PORT_SCR_ERR);
status = readl(port_mmio + PORT_IRQ_STAT); status = readl(port_mmio + PORT_IRQ_STAT);
writel(status, port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT);
ci = readl(port_mmio + PORT_CMD_ISSUE); if (unlikely(status & PORT_IRQ_ERROR)) {
if (likely((ci & 0x1) == 0)) { ahci_error_intr(ap, status);
if (qc) { return;
WARN_ON(qc->err_mask);
ata_qc_complete(qc);
qc = NULL;
}
} }
if (status & PORT_IRQ_FATAL) { if (ap->sactive)
unsigned int err_mask; qc_active = readl(port_mmio + PORT_SCR_ACT);
if (status & PORT_IRQ_TF_ERR)
err_mask = AC_ERR_DEV;
else if (status & PORT_IRQ_IF_ERR)
err_mask = AC_ERR_ATA_BUS;
else else
err_mask = AC_ERR_HOST_BUS; qc_active = readl(port_mmio + PORT_CMD_ISSUE);
/* command processing has stopped due to error; restart */
ahci_restart_port(ap, status);
if (qc) { rc = ata_qc_complete_multiple(ap, qc_active, NULL);
qc->err_mask |= err_mask; if (rc > 0)
ata_qc_complete(qc); return;
if (rc < 0) {
ehi->err_mask |= AC_ERR_HSM;
ehi->action |= ATA_EH_SOFTRESET;
ata_port_freeze(ap);
return;
} }
/* hmmm... a spurious interupt */
/* some devices send D2H reg with I bit set during NCQ command phase */
if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS)
return;
/* ignore interim PIO setup fis interrupts */
if (ata_tag_valid(ap->active_tag)) {
struct ata_queued_cmd *qc =
ata_qc_from_tag(ap, ap->active_tag);
if (qc && qc->tf.protocol == ATA_PROT_PIO &&
(status & PORT_IRQ_PIOS_FIS))
return;
} }
return 1; if (ata_ratelimit())
ata_port_printk(ap, KERN_INFO, "spurious interrupt "
"(irq_stat 0x%x active_tag %d sactive 0x%x)\n",
status, ap->active_tag, ap->sactive);
} }
static void ahci_irq_clear(struct ata_port *ap) static void ahci_irq_clear(struct ata_port *ap)
...@@ -882,7 +960,7 @@ static void ahci_irq_clear(struct ata_port *ap) ...@@ -882,7 +960,7 @@ static void ahci_irq_clear(struct ata_port *ap)
/* TODO */ /* TODO */
} }
static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs) static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{ {
struct ata_host_set *host_set = dev_instance; struct ata_host_set *host_set = dev_instance;
struct ahci_host_priv *hpriv; struct ahci_host_priv *hpriv;
...@@ -911,14 +989,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * ...@@ -911,14 +989,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
ap = host_set->ports[i]; ap = host_set->ports[i];
if (ap) { if (ap) {
struct ata_queued_cmd *qc; ahci_host_intr(ap);
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!ahci_host_intr(ap, qc))
if (ata_ratelimit())
dev_printk(KERN_WARNING, host_set->dev,
"unhandled interrupt on port %u\n",
i);
VPRINTK("port %u\n", i); VPRINTK("port %u\n", i);
} else { } else {
VPRINTK("port %u (no irq)\n", i); VPRINTK("port %u (no irq)\n", i);
...@@ -947,12 +1018,65 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) ...@@ -947,12 +1018,65 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
writel(1, port_mmio + PORT_CMD_ISSUE); if (qc->tf.protocol == ATA_PROT_NCQ)
writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
readl(port_mmio + PORT_CMD_ISSUE); /* flush */ readl(port_mmio + PORT_CMD_ISSUE); /* flush */
return 0; return 0;
} }
static void ahci_freeze(struct ata_port *ap)
{
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
/* turn IRQ off */
writel(0, port_mmio + PORT_IRQ_MASK);
}
static void ahci_thaw(struct ata_port *ap)
{
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
/* clear IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT);
writel(tmp, port_mmio + PORT_IRQ_STAT);
writel(1 << ap->id, mmio + HOST_IRQ_STAT);
/* turn IRQ back on */
writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
}
static void ahci_error_handler(struct ata_port *ap)
{
if (!(ap->flags & ATA_FLAG_FROZEN)) {
/* restart engine */
ahci_stop_engine(ap);
ahci_start_engine(ap);
}
/* perform recovery */
ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset,
ahci_postreset);
}
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
if (qc->flags & ATA_QCFLAG_FAILED)
qc->err_mask |= AC_ERR_OTHER;
if (qc->err_mask) {
/* make DMA engine forget about the failed command */
ahci_stop_engine(ap);
ahci_start_engine(ap);
}
}
static void ahci_setup_port(struct ata_ioports *port, unsigned long base, static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
unsigned int port_idx) unsigned int port_idx)
{ {
...@@ -1097,9 +1221,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) ...@@ -1097,9 +1221,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
writel(tmp, port_mmio + PORT_IRQ_STAT); writel(tmp, port_mmio + PORT_IRQ_STAT);
writel(1 << i, mmio + HOST_IRQ_STAT); writel(1 << i, mmio + HOST_IRQ_STAT);
/* set irq mask (enables interrupts) */
writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
} }
tmp = readl(mmio + HOST_CTL); tmp = readl(mmio + HOST_CTL);
...@@ -1197,6 +1318,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1197,6 +1318,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
...@@ -1264,6 +1387,10 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1264,6 +1387,10 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) if (rc)
goto err_out_hpriv; goto err_out_hpriv;
if (!(probe_ent->host_flags & AHCI_FLAG_NO_NCQ) &&
(hpriv->cap & HOST_CAP_NCQ))
probe_ent->host_flags |= ATA_FLAG_NCQ;
ahci_print_info(probe_ent); ahci_print_info(probe_ent);
/* FIXME: check ata_device_add return value */ /* FIXME: check ata_device_add return value */
...@@ -1295,21 +1422,17 @@ static void ahci_remove_one (struct pci_dev *pdev) ...@@ -1295,21 +1422,17 @@ static void ahci_remove_one (struct pci_dev *pdev)
struct device *dev = pci_dev_to_dev(pdev); struct device *dev = pci_dev_to_dev(pdev);
struct ata_host_set *host_set = dev_get_drvdata(dev); struct ata_host_set *host_set = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host_set->private_data; struct ahci_host_priv *hpriv = host_set->private_data;
struct ata_port *ap;
unsigned int i; unsigned int i;
int have_msi; int have_msi;
for (i = 0; i < host_set->n_ports; i++) { for (i = 0; i < host_set->n_ports; i++)
ap = host_set->ports[i]; ata_port_detach(host_set->ports[i]);
scsi_remove_host(ap->host);
}
have_msi = hpriv->flags & AHCI_FLAG_MSI; have_msi = hpriv->flags & AHCI_FLAG_MSI;
free_irq(host_set->irq, host_set); free_irq(host_set->irq, host_set);
for (i = 0; i < host_set->n_ports; i++) { for (i = 0; i < host_set->n_ports; i++) {
ap = host_set->ports[i]; struct ata_port *ap = host_set->ports[i];
ata_scsi_release(ap->host); ata_scsi_release(ap->host);
scsi_host_put(ap->host); scsi_host_put(ap->host);
......
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "ata_piix" #define DRV_NAME "ata_piix"
#define DRV_VERSION "1.05" #define DRV_VERSION "1.10"
enum { enum {
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
...@@ -146,11 +146,10 @@ struct piix_map_db { ...@@ -146,11 +146,10 @@ struct piix_map_db {
static int piix_init_one (struct pci_dev *pdev, static int piix_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent); const struct pci_device_id *ent);
static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes);
static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes);
static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); 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 piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
static void piix_pata_error_handler(struct ata_port *ap);
static void piix_sata_error_handler(struct ata_port *ap);
static unsigned int in_module_init = 1; static unsigned int in_module_init = 1;
...@@ -159,6 +158,7 @@ static const struct pci_device_id piix_pci_tbl[] = { ...@@ -159,6 +158,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata },
{ 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
{ 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
{ 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
#endif #endif
/* NOTE: The following PCI ids must be kept in sync with the /* NOTE: The following PCI ids must be kept in sync with the
...@@ -218,6 +218,7 @@ static struct scsi_host_template piix_sht = { ...@@ -218,6 +218,7 @@ static struct scsi_host_template piix_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
.resume = ata_scsi_device_resume, .resume = ata_scsi_device_resume,
.suspend = ata_scsi_device_suspend, .suspend = ata_scsi_device_suspend,
...@@ -227,6 +228,7 @@ static const struct ata_port_operations piix_pata_ops = { ...@@ -227,6 +228,7 @@ static const struct ata_port_operations piix_pata_ops = {
.port_disable = ata_port_disable, .port_disable = ata_port_disable,
.set_piomode = piix_set_piomode, .set_piomode = piix_set_piomode,
.set_dmamode = piix_set_dmamode, .set_dmamode = piix_set_dmamode,
.mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
...@@ -234,16 +236,18 @@ static const struct ata_port_operations piix_pata_ops = { ...@@ -234,16 +236,18 @@ static const struct ata_port_operations piix_pata_ops = {
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.probe_reset = piix_pata_probe_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.data_xfer = ata_pio_data_xfer,
.eng_timeout = ata_eng_timeout, .freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = piix_pata_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
...@@ -262,16 +266,18 @@ static const struct ata_port_operations piix_sata_ops = { ...@@ -262,16 +266,18 @@ static const struct ata_port_operations piix_sata_ops = {
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.probe_reset = piix_sata_probe_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.data_xfer = ata_pio_data_xfer,
.eng_timeout = ata_eng_timeout, .freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = piix_sata_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
...@@ -455,59 +461,51 @@ static void piix_pata_cbl_detect(struct ata_port *ap) ...@@ -455,59 +461,51 @@ static void piix_pata_cbl_detect(struct ata_port *ap)
} }
/** /**
* piix_pata_probeinit - probeinit for PATA host controller * piix_pata_prereset - prereset for PATA host controller
* @ap: Target port * @ap: Target port
* *
* Probeinit including cable detection. * Prereset including cable detection.
*
* LOCKING:
* None (inherited from caller).
*/
static void piix_pata_probeinit(struct ata_port *ap)
{
piix_pata_cbl_detect(ap);
ata_std_probeinit(ap);
}
/**
* piix_pata_probe_reset - Perform reset on PATA port and classify
* @ap: Port to reset
* @classes: Resulting classes of attached devices
*
* Reset PATA phy and classify attached devices.
* *
* LOCKING: * LOCKING:
* None (inherited from caller). * None (inherited from caller).
*/ */
static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes) static int piix_pata_prereset(struct ata_port *ap)
{ {
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
return 0; return 0;
} }
return ata_drive_probe_reset(ap, piix_pata_probeinit, piix_pata_cbl_detect(ap);
ata_std_softreset, NULL,
ata_std_postreset, classes); return ata_std_prereset(ap);
}
static void piix_pata_error_handler(struct ata_port *ap)
{
ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL,
ata_std_postreset);
} }
/** /**
* piix_sata_probe - Probe PCI device for present SATA devices * piix_sata_prereset - prereset for SATA host controller
* @ap: Port associated with the PCI device we wish to probe * @ap: Target port
* *
* Reads and configures SATA PCI device's PCI config register * Reads and configures SATA PCI device's PCI config register
* Port Configuration and Status (PCS) to determine port and * Port Configuration and Status (PCS) to determine port and
* device availability. * device availability. Return -ENODEV to skip reset if no
* device is present.
* *
* LOCKING: * LOCKING:
* None (inherited from caller). * None (inherited from caller).
* *
* RETURNS: * RETURNS:
* Mask of avaliable devices on the port. * 0 if device is present, -ENODEV otherwise.
*/ */
static unsigned int piix_sata_probe (struct ata_port *ap) static int piix_sata_prereset(struct ata_port *ap)
{ {
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
const unsigned int *map = ap->host_set->private_data; const unsigned int *map = ap->host_set->private_data;
...@@ -549,29 +547,19 @@ static unsigned int piix_sata_probe (struct ata_port *ap) ...@@ -549,29 +547,19 @@ static unsigned int piix_sata_probe (struct ata_port *ap)
DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
ap->id, pcs, present_mask); ap->id, pcs, present_mask);
return present_mask; if (!present_mask) {
} ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n");
ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
/**
* piix_sata_probe_reset - Perform reset on SATA port and classify
* @ap: Port to reset
* @classes: Resulting classes of attached devices
*
* Reset SATA phy and classify attached devices.
*
* LOCKING:
* None (inherited from caller).
*/
static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes)
{
if (!piix_sata_probe(ap)) {
printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
return 0; return 0;
} }
return ata_drive_probe_reset(ap, ata_std_probeinit, return ata_std_prereset(ap);
ata_std_softreset, NULL, }
ata_std_postreset, classes);
static void piix_sata_error_handler(struct ata_port *ap)
{
ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL,
ata_std_postreset);
} }
/** /**
...@@ -760,15 +748,15 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) ...@@ -760,15 +748,15 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
pci_read_config_word(pdev, 0x41, &cfg); pci_read_config_word(pdev, 0x41, &cfg);
/* Only on the original revision: IDE DMA can hang */ /* Only on the original revision: IDE DMA can hang */
if(rev == 0x00) if (rev == 0x00)
no_piix_dma = 1; no_piix_dma = 1;
/* On all revisions below 5 PXB bus lock must be disabled for IDE */ /* On all revisions below 5 PXB bus lock must be disabled for IDE */
else if(cfg & (1<<14) && rev < 5) else if (cfg & (1<<14) && rev < 5)
no_piix_dma = 2; no_piix_dma = 2;
} }
if(no_piix_dma) if (no_piix_dma)
dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n"); dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
if(no_piix_dma == 2) if (no_piix_dma == 2)
dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
return no_piix_dma; return no_piix_dma;
} }
......
...@@ -652,6 +652,151 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc) ...@@ -652,6 +652,151 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc)
ata_altstatus(ap); /* dummy read */ ata_altstatus(ap); /* dummy read */
} }
/**
* ata_bmdma_freeze - Freeze BMDMA controller port
* @ap: port to freeze
*
* Freeze BMDMA controller port.
*
* LOCKING:
* Inherited from caller.
*/
void ata_bmdma_freeze(struct ata_port *ap)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
ap->ctl |= ATA_NIEN;
ap->last_ctl = ap->ctl;
if (ap->flags & ATA_FLAG_MMIO)
writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
else
outb(ap->ctl, ioaddr->ctl_addr);
}
/**
* ata_bmdma_thaw - Thaw BMDMA controller port
* @ap: port to thaw
*
* Thaw BMDMA controller port.
*
* LOCKING:
* Inherited from caller.
*/
void ata_bmdma_thaw(struct ata_port *ap)
{
/* clear & re-enable interrupts */
ata_chk_status(ap);
ap->ops->irq_clear(ap);
if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
ata_irq_on(ap);
}
/**
* ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
* @ap: port to handle error for
* @prereset: prereset method (can be NULL)
* @softreset: softreset method (can be NULL)
* @hardreset: hardreset method (can be NULL)
* @postreset: postreset method (can be NULL)
*
* Handle error for ATA BMDMA controller. It can handle both
* PATA and SATA controllers. Many controllers should be able to
* use this EH as-is or with some added handling before and
* after.
*
* This function is intended to be used for constructing
* ->error_handler callback by low level drivers.
*
* LOCKING:
* Kernel thread context (may sleep)
*/
void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset)
{
struct ata_eh_context *ehc = &ap->eh_context;
struct ata_queued_cmd *qc;
unsigned long flags;
int thaw = 0;
qc = __ata_qc_from_tag(ap, ap->active_tag);
if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
qc = NULL;
/* reset PIO HSM and stop DMA engine */
spin_lock_irqsave(ap->lock, flags);
ap->hsm_task_state = HSM_ST_IDLE;
if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
u8 host_stat;
host_stat = ata_bmdma_status(ap);
ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat);
/* BMDMA controllers indicate host bus error by
* setting DMA_ERR bit and timing out. As it wasn't
* really a timeout event, adjust error mask and
* cancel frozen state.
*/
if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) {
qc->err_mask = AC_ERR_HOST_BUS;
thaw = 1;
}
ap->ops->bmdma_stop(qc);
}
ata_altstatus(ap);
ata_chk_status(ap);
ap->ops->irq_clear(ap);
spin_unlock_irqrestore(ap->lock, flags);
if (thaw)
ata_eh_thaw_port(ap);
/* PIO and DMA engines have been stopped, perform recovery */
ata_do_eh(ap, prereset, softreset, hardreset, postreset);
}
/**
* ata_bmdma_error_handler - Stock error handler for BMDMA controller
* @ap: port to handle error for
*
* Stock error handler for BMDMA controller.
*
* LOCKING:
* Kernel thread context (may sleep)
*/
void ata_bmdma_error_handler(struct ata_port *ap)
{
ata_reset_fn_t hardreset;
hardreset = NULL;
if (sata_scr_valid(ap))
hardreset = sata_std_hardreset;
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
ata_std_postreset);
}
/**
* ata_bmdma_post_internal_cmd - Stock post_internal_cmd for
* BMDMA controller
* @qc: internal command to clean up
*
* LOCKING:
* Kernel thread context (may sleep)
*/
void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
{
ata_bmdma_stop(qc);
}
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static struct ata_probe_ent * static struct ata_probe_ent *
ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
...@@ -930,10 +1075,21 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, ...@@ -930,10 +1075,21 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
/* FIXME: check ata_device_add return */ /* FIXME: check ata_device_add return */
if (legacy_mode) { if (legacy_mode) {
if (legacy_mode & (1 << 0)) struct device *dev = &pdev->dev;
struct ata_host_set *host_set = NULL;
if (legacy_mode & (1 << 0)) {
ata_device_add(probe_ent); ata_device_add(probe_ent);
if (legacy_mode & (1 << 1)) host_set = dev_get_drvdata(dev);
}
if (legacy_mode & (1 << 1)) {
ata_device_add(probe_ent2); ata_device_add(probe_ent2);
if (host_set) {
host_set->next = dev_get_drvdata(dev);
dev_set_drvdata(dev, host_set);
}
}
} else } else
ata_device_add(probe_ent); ata_device_add(probe_ent);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* libata-eh.c - libata error handling
*
* Maintained by: Jeff Garzik <jgarzik@pobox.com>
* Please ALWAYS copy linux-ide@vger.kernel.org
* on emails.
*
* Copyright 2006 Tejun Heo <htejun@gmail.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.
*
* 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.*
*
* Hardware documentation available from http://www.t13.org/ and
* http://www.sata-io.org/
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include "scsi_transport_api.h"
#include <linux/libata.h>
#include "libata.h"
static void __ata_port_freeze(struct ata_port *ap);
static void ata_eh_finish(struct ata_port *ap);
static void ata_ering_record(struct ata_ering *ering, int is_io,
unsigned int err_mask)
{
struct ata_ering_entry *ent;
WARN_ON(!err_mask);
ering->cursor++;
ering->cursor %= ATA_ERING_SIZE;
ent = &ering->ring[ering->cursor];
ent->is_io = is_io;
ent->err_mask = err_mask;
ent->timestamp = get_jiffies_64();
}
static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering)
{
struct ata_ering_entry *ent = &ering->ring[ering->cursor];
if (!ent->err_mask)
return NULL;
return ent;
}
static int ata_ering_map(struct ata_ering *ering,
int (*map_fn)(struct ata_ering_entry *, void *),
void *arg)
{
int idx, rc = 0;
struct ata_ering_entry *ent;
idx = ering->cursor;
do {
ent = &ering->ring[idx];
if (!ent->err_mask)
break;
rc = map_fn(ent, arg);
if (rc)
break;
idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE;
} while (idx != ering->cursor);
return rc;
}
/**
* ata_scsi_timed_out - SCSI layer time out callback
* @cmd: timed out SCSI command
*
* Handles SCSI layer timeout. We race with normal completion of
* the qc for @cmd. If the qc is already gone, we lose and let
* the scsi command finish (EH_HANDLED). Otherwise, the qc has
* timed out and EH should be invoked. Prevent ata_qc_complete()
* from finishing it by setting EH_SCHEDULED and return
* EH_NOT_HANDLED.
*
* TODO: kill this function once old EH is gone.
*
* LOCKING:
* Called from timer context
*
* RETURNS:
* EH_HANDLED or EH_NOT_HANDLED
*/
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
struct ata_port *ap = ata_shost_to_port(host);
unsigned long flags;
struct ata_queued_cmd *qc;
enum scsi_eh_timer_return ret;
DPRINTK("ENTER\n");
if (ap->ops->error_handler) {
ret = EH_NOT_HANDLED;
goto out;
}
ret = EH_HANDLED;
spin_lock_irqsave(ap->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc) {
WARN_ON(qc->scsicmd != cmd);
qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
qc->err_mask |= AC_ERR_TIMEOUT;
ret = EH_NOT_HANDLED;
}
spin_unlock_irqrestore(ap->lock, flags);
out:
DPRINTK("EXIT, ret=%d\n", ret);
return ret;
}
/**
* ata_scsi_error - SCSI layer error handler callback
* @host: SCSI host on which error occurred
*
* Handles SCSI-layer-thrown error events.
*
* LOCKING:
* Inherited from SCSI layer (none, can sleep)
*
* RETURNS:
* Zero.
*/
void ata_scsi_error(struct Scsi_Host *host)
{
struct ata_port *ap = ata_shost_to_port(host);
spinlock_t *ap_lock = ap->lock;
int i, repeat_cnt = ATA_EH_MAX_REPEAT;
unsigned long flags;
DPRINTK("ENTER\n");
/* synchronize with port task */
ata_port_flush_task(ap);
/* synchronize with host_set lock and sort out timeouts */
/* For new EH, all qcs are finished in one of three ways -
* normal completion, error completion, and SCSI timeout.
* Both cmpletions can race against SCSI timeout. When normal
* completion wins, the qc never reaches EH. When error
* completion wins, the qc has ATA_QCFLAG_FAILED set.
*
* When SCSI timeout wins, things are a bit more complex.
* Normal or error completion can occur after the timeout but
* before this point. In such cases, both types of
* completions are honored. A scmd is determined to have
* timed out iff its associated qc is active and not failed.
*/
if (ap->ops->error_handler) {
struct scsi_cmnd *scmd, *tmp;
int nr_timedout = 0;
spin_lock_irqsave(ap_lock, flags);
list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
struct ata_queued_cmd *qc;
for (i = 0; i < ATA_MAX_QUEUE; i++) {
qc = __ata_qc_from_tag(ap, i);
if (qc->flags & ATA_QCFLAG_ACTIVE &&
qc->scsicmd == scmd)
break;
}
if (i < ATA_MAX_QUEUE) {
/* the scmd has an associated qc */
if (!(qc->flags & ATA_QCFLAG_FAILED)) {
/* which hasn't failed yet, timeout */
qc->err_mask |= AC_ERR_TIMEOUT;
qc->flags |= ATA_QCFLAG_FAILED;
nr_timedout++;
}
} else {
/* Normal completion occurred after
* SCSI timeout but before this point.
* Successfully complete it.
*/
scmd->retries = scmd->allowed;
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
}
}
/* If we have timed out qcs. They belong to EH from
* this point but the state of the controller is
* unknown. Freeze the port to make sure the IRQ
* handler doesn't diddle with those qcs. This must
* be done atomically w.r.t. setting QCFLAG_FAILED.
*/
if (nr_timedout)
__ata_port_freeze(ap);
spin_unlock_irqrestore(ap_lock, flags);
} else
spin_unlock_wait(ap_lock);
repeat:
/* invoke error handler */
if (ap->ops->error_handler) {
/* fetch & clear EH info */
spin_lock_irqsave(ap_lock, flags);
memset(&ap->eh_context, 0, sizeof(ap->eh_context));
ap->eh_context.i = ap->eh_info;
memset(&ap->eh_info, 0, sizeof(ap->eh_info));
ap->flags |= ATA_FLAG_EH_IN_PROGRESS;
ap->flags &= ~ATA_FLAG_EH_PENDING;
spin_unlock_irqrestore(ap_lock, flags);
/* invoke EH. if unloading, just finish failed qcs */
if (!(ap->flags & ATA_FLAG_UNLOADING))
ap->ops->error_handler(ap);
else
ata_eh_finish(ap);
/* Exception might have happend after ->error_handler
* recovered the port but before this point. Repeat
* EH in such case.
*/
spin_lock_irqsave(ap_lock, flags);
if (ap->flags & ATA_FLAG_EH_PENDING) {
if (--repeat_cnt) {
ata_port_printk(ap, KERN_INFO,
"EH pending after completion, "
"repeating EH (cnt=%d)\n", repeat_cnt);
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_REPEAT);
}
/* this run is complete, make sure EH info is clear */
memset(&ap->eh_info, 0, sizeof(ap->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
* re-initiate EH.
*/
host->host_eh_scheduled = 0;
spin_unlock_irqrestore(ap_lock, flags);
} else {
WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
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 */
spin_lock_irqsave(ap_lock, flags);
if (ap->flags & ATA_FLAG_LOADING) {
ap->flags &= ~ATA_FLAG_LOADING;
} else {
if (ap->flags & ATA_FLAG_SCSI_HOTPLUG)
queue_work(ata_aux_wq, &ap->hotplug_task);
if (ap->flags & ATA_FLAG_RECOVERED)
ata_port_printk(ap, KERN_INFO, "EH complete\n");
}
ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED);
/* tell wait_eh that we're done */
ap->flags &= ~ATA_FLAG_EH_IN_PROGRESS;
wake_up_all(&ap->eh_wait_q);
spin_unlock_irqrestore(ap_lock, flags);
DPRINTK("EXIT\n");
}
/**
* ata_port_wait_eh - Wait for the currently pending EH to complete
* @ap: Port to wait EH for
*
* Wait until the currently pending EH is complete.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
void ata_port_wait_eh(struct ata_port *ap)
{
unsigned long flags;
DEFINE_WAIT(wait);
retry:
spin_lock_irqsave(ap->lock, flags);
while (ap->flags & (ATA_FLAG_EH_PENDING | ATA_FLAG_EH_IN_PROGRESS)) {
prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE);
spin_unlock_irqrestore(ap->lock, flags);
schedule();
spin_lock_irqsave(ap->lock, flags);
}
finish_wait(&ap->eh_wait_q, &wait);
spin_unlock_irqrestore(ap->lock, flags);
/* make sure SCSI EH is complete */
if (scsi_host_in_recovery(ap->host)) {
msleep(10);
goto retry;
}
}
/**
* ata_qc_timeout - Handle timeout of queued command
* @qc: Command that timed out
*
* Some part of the kernel (currently, only the SCSI layer)
* has noticed that the active command on port @ap has not
* completed after a specified length of time. Handle this
* condition by disabling DMA (if necessary) and completing
* transactions, with error if necessary.
*
* This also handles the case of the "lost interrupt", where
* for some reason (possibly hardware bug, possibly driver bug)
* an interrupt was not delivered to the driver, even though the
* transaction completed successfully.
*
* TODO: kill this function once old EH is gone.
*
* LOCKING:
* Inherited from SCSI layer (none, can sleep)
*/
static void ata_qc_timeout(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
u8 host_stat = 0, drv_stat;
unsigned long flags;
DPRINTK("ENTER\n");
ap->hsm_task_state = HSM_ST_IDLE;
spin_lock_irqsave(ap->lock, flags);
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA:
host_stat = ap->ops->bmdma_status(ap);
/* before we do anything else, clear DMA-Start bit */
ap->ops->bmdma_stop(qc);
/* fall through */
default:
ata_altstatus(ap);
drv_stat = ata_chk_status(ap);
/* ack bmdma irq events */
ap->ops->irq_clear(ap);
ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, "
"stat 0x%x host_stat 0x%x\n",
qc->tf.command, drv_stat, host_stat);
/* complete taskfile transaction */
qc->err_mask |= AC_ERR_TIMEOUT;
break;
}
spin_unlock_irqrestore(ap->lock, flags);
ata_eh_qc_complete(qc);
DPRINTK("EXIT\n");
}
/**
* ata_eng_timeout - Handle timeout of queued command
* @ap: Port on which timed-out command is active
*
* Some part of the kernel (currently, only the SCSI layer)
* has noticed that the active command on port @ap has not
* completed after a specified length of time. Handle this
* condition by disabling DMA (if necessary) and completing
* transactions, with error if necessary.
*
* This also handles the case of the "lost interrupt", where
* for some reason (possibly hardware bug, possibly driver bug)
* an interrupt was not delivered to the driver, even though the
* transaction completed successfully.
*
* TODO: kill this function once old EH is gone.
*
* LOCKING:
* Inherited from SCSI layer (none, can sleep)
*/
void ata_eng_timeout(struct ata_port *ap)
{
DPRINTK("ENTER\n");
ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
DPRINTK("EXIT\n");
}
/**
* ata_qc_schedule_eh - schedule qc for error handling
* @qc: command to schedule error handling for
*
* Schedule error handling for @qc. EH will kick in as soon as
* other commands are drained.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
WARN_ON(!ap->ops->error_handler);
qc->flags |= ATA_QCFLAG_FAILED;
qc->ap->flags |= ATA_FLAG_EH_PENDING;
/* The following will fail if timeout has already expired.
* ata_scsi_error() takes care of such scmds on EH entry.
* Note that ATA_QCFLAG_FAILED is unconditionally set after
* this function completes.
*/
scsi_req_abort_cmd(qc->scsicmd);
}
/**
* 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_set lock)
*/
void ata_port_schedule_eh(struct ata_port *ap)
{
WARN_ON(!ap->ops->error_handler);
ap->flags |= ATA_FLAG_EH_PENDING;
scsi_schedule_eh(ap->host);
DPRINTK("port EH scheduled\n");
}
/**
* ata_port_abort - abort all qc's on the port
* @ap: ATA port to abort qc's for
*
* Abort all active qc's of @ap and schedule EH.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS:
* Number of aborted qc's.
*/
int ata_port_abort(struct ata_port *ap)
{
int tag, nr_aborted = 0;
WARN_ON(!ap->ops->error_handler);
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
if (qc) {
qc->flags |= ATA_QCFLAG_FAILED;
ata_qc_complete(qc);
nr_aborted++;
}
}
if (!nr_aborted)
ata_port_schedule_eh(ap);
return nr_aborted;
}
/**
* __ata_port_freeze - freeze port
* @ap: ATA port to freeze
*
* This function is called when HSM violation or some other
* condition disrupts normal operation of the port. Frozen port
* is not allowed to perform any operation until the port is
* thawed, which usually follows a successful reset.
*
* ap->ops->freeze() callback can be used for freezing the port
* hardware-wise (e.g. mask interrupt and stop DMA engine). If a
* port cannot be frozen hardware-wise, the interrupt handler
* must ack and clear interrupts unconditionally while the port
* is frozen.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static void __ata_port_freeze(struct ata_port *ap)
{
WARN_ON(!ap->ops->error_handler);
if (ap->ops->freeze)
ap->ops->freeze(ap);
ap->flags |= ATA_FLAG_FROZEN;
DPRINTK("ata%u port frozen\n", ap->id);
}
/**
* ata_port_freeze - abort & freeze port
* @ap: ATA port to freeze
*
* Abort and freeze @ap.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS:
* Number of aborted commands.
*/
int ata_port_freeze(struct ata_port *ap)
{
int nr_aborted;
WARN_ON(!ap->ops->error_handler);
nr_aborted = ata_port_abort(ap);
__ata_port_freeze(ap);
return nr_aborted;
}
/**
* ata_eh_freeze_port - EH helper to freeze port
* @ap: ATA port to freeze
*
* Freeze @ap.
*
* LOCKING:
* None.
*/
void ata_eh_freeze_port(struct ata_port *ap)
{
unsigned long flags;
if (!ap->ops->error_handler)
return;
spin_lock_irqsave(ap->lock, flags);
__ata_port_freeze(ap);
spin_unlock_irqrestore(ap->lock, flags);
}
/**
* ata_port_thaw_port - EH helper to thaw port
* @ap: ATA port to thaw
*
* Thaw frozen port @ap.
*
* LOCKING:
* None.
*/
void ata_eh_thaw_port(struct ata_port *ap)
{
unsigned long flags;
if (!ap->ops->error_handler)
return;
spin_lock_irqsave(ap->lock, flags);
ap->flags &= ~ATA_FLAG_FROZEN;
if (ap->ops->thaw)
ap->ops->thaw(ap);
spin_unlock_irqrestore(ap->lock, flags);
DPRINTK("ata%u port thawed\n", ap->id);
}
static void ata_eh_scsidone(struct scsi_cmnd *scmd)
{
/* nada */
}
static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scsi_cmnd *scmd = qc->scsicmd;
unsigned long flags;
spin_lock_irqsave(ap->lock, flags);
qc->scsidone = ata_eh_scsidone;
__ata_qc_complete(qc);
WARN_ON(ata_tag_valid(qc->tag));
spin_unlock_irqrestore(ap->lock, flags);
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
}
/**
* ata_eh_qc_complete - Complete an active ATA command from EH
* @qc: Command to complete
*
* Indicate to the mid and upper layers that an ATA command has
* completed. To be used from EH.
*/
void ata_eh_qc_complete(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
scmd->retries = scmd->allowed;
__ata_eh_qc_complete(qc);
}
/**
* ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
* @qc: Command to retry
*
* Indicate to the mid and upper layers that an ATA command
* 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
* 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--;
__ata_eh_qc_complete(qc);
}
/**
* ata_eh_detach_dev - detach ATA device
* @dev: ATA device to detach
*
* Detach @dev.
*
* LOCKING:
* None.
*/
static void ata_eh_detach_dev(struct ata_device *dev)
{
struct ata_port *ap = dev->ap;
unsigned long flags;
ata_dev_disable(dev);
spin_lock_irqsave(ap->lock, flags);
dev->flags &= ~ATA_DFLAG_DETACH;
if (ata_scsi_offline_dev(dev)) {
dev->flags |= ATA_DFLAG_DETACHED;
ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
}
spin_unlock_irqrestore(ap->lock, flags);
}
static void ata_eh_clear_action(struct ata_device *dev,
struct ata_eh_info *ehi, unsigned int action)
{
int i;
if (!dev) {
ehi->action &= ~action;
for (i = 0; i < ATA_MAX_DEVICES; i++)
ehi->dev_action[i] &= ~action;
} else {
/* doesn't make sense for port-wide EH actions */
WARN_ON(!(action & ATA_EH_PERDEV_MASK));
/* break ehi->action into ehi->dev_action */
if (ehi->action & action) {
for (i = 0; i < ATA_MAX_DEVICES; i++)
ehi->dev_action[i] |= ehi->action & action;
ehi->action &= ~action;
}
/* turn off the specified per-dev action */
ehi->dev_action[dev->devno] &= ~action;
}
}
/**
* ata_eh_about_to_do - about to perform eh_action
* @ap: target ATA port
* @dev: target ATA dev for per-dev action (can be NULL)
* @action: action about to be performed
*
* Called just before performing EH actions to clear related bits
* in @ap->eh_info such that eh actions are not unnecessarily
* repeated.
*
* LOCKING:
* None.
*/
static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
unsigned int action)
{
unsigned long flags;
spin_lock_irqsave(ap->lock, flags);
ata_eh_clear_action(dev, &ap->eh_info, action);
ap->flags |= ATA_FLAG_RECOVERED;
spin_unlock_irqrestore(ap->lock, flags);
}
/**
* ata_eh_done - EH action complete
* @ap: target ATA port
* @dev: target ATA dev for per-dev action (can be NULL)
* @action: action just completed
*
* Called right after performing EH actions to clear related bits
* in @ap->eh_context.
*
* LOCKING:
* None.
*/
static void ata_eh_done(struct ata_port *ap, struct ata_device *dev,
unsigned int action)
{
ata_eh_clear_action(dev, &ap->eh_context.i, action);
}
/**
* ata_err_string - convert err_mask to descriptive string
* @err_mask: error mask to convert to string
*
* Convert @err_mask to descriptive string. Errors are
* prioritized according to severity and only the most severe
* error is reported.
*
* LOCKING:
* None.
*
* RETURNS:
* Descriptive string for @err_mask
*/
static const char * ata_err_string(unsigned int err_mask)
{
if (err_mask & AC_ERR_HOST_BUS)
return "host bus error";
if (err_mask & AC_ERR_ATA_BUS)
return "ATA bus error";
if (err_mask & AC_ERR_TIMEOUT)
return "timeout";
if (err_mask & AC_ERR_HSM)
return "HSM violation";
if (err_mask & AC_ERR_SYSTEM)
return "internal error";
if (err_mask & AC_ERR_MEDIA)
return "media error";
if (err_mask & AC_ERR_INVALID)
return "invalid argument";
if (err_mask & AC_ERR_DEV)
return "device error";
return "unknown error";
}
/**
* ata_read_log_page - read a specific log page
* @dev: target device
* @page: page to read
* @buf: buffer to store read page
* @sectors: number of sectors to read
*
* Read log page using READ_LOG_EXT command.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, AC_ERR_* mask otherwise.
*/
static unsigned int ata_read_log_page(struct ata_device *dev,
u8 page, void *buf, unsigned int sectors)
{
struct ata_taskfile tf;
unsigned int err_mask;
DPRINTK("read log page - page %d\n", page);
ata_tf_init(dev, &tf);
tf.command = ATA_CMD_READ_LOG_EXT;
tf.lbal = page;
tf.nsect = sectors;
tf.hob_nsect = sectors >> 8;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
tf.protocol = ATA_PROT_PIO;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
buf, sectors * ATA_SECT_SIZE);
DPRINTK("EXIT, err_mask=%x\n", err_mask);
return err_mask;
}
/**
* ata_eh_read_log_10h - Read log page 10h for NCQ error details
* @dev: Device to read log page 10h from
* @tag: Resulting tag of the failed command
* @tf: Resulting taskfile registers of the failed command
*
* Read log page 10h to obtain NCQ error details and clear error
* condition.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, -errno otherwise.
*/
static int ata_eh_read_log_10h(struct ata_device *dev,
int *tag, struct ata_taskfile *tf)
{
u8 *buf = dev->ap->sector_buf;
unsigned int err_mask;
u8 csum;
int i;
err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1);
if (err_mask)
return -EIO;
csum = 0;
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);
if (buf[0] & 0x80)
return -ENOENT;
*tag = buf[0] & 0x1f;
tf->command = buf[2];
tf->feature = buf[3];
tf->lbal = buf[4];
tf->lbam = buf[5];
tf->lbah = buf[6];
tf->device = buf[7];
tf->hob_lbal = buf[8];
tf->hob_lbam = buf[9];
tf->hob_lbah = buf[10];
tf->nsect = buf[12];
tf->hob_nsect = buf[13];
return 0;
}
/**
* atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
* @dev: device to perform REQUEST_SENSE to
* @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
*
* Perform ATAPI REQUEST_SENSE after the device reported CHECK
* SENSE. This function is EH helper.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, AC_ERR_* mask on failure
*/
static unsigned int atapi_eh_request_sense(struct ata_device *dev,
unsigned char *sense_buf)
{
struct ata_port *ap = dev->ap;
struct ata_taskfile tf;
u8 cdb[ATAPI_CDB_LEN];
DPRINTK("ATAPI request sense\n");
ata_tf_init(dev, &tf);
/* FIXME: is this needed? */
memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
/* XXX: why tf_read here? */
ap->ops->tf_read(ap, &tf);
/* fill these in, for the case where they are -not- overwritten */
sense_buf[0] = 0x70;
sense_buf[2] = tf.feature >> 4;
memset(cdb, 0, ATAPI_CDB_LEN);
cdb[0] = REQUEST_SENSE;
cdb[4] = SCSI_SENSE_BUFFERSIZE;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf.command = ATA_CMD_PACKET;
/* is it pointless to prefer PIO for "safety reasons"? */
if (ap->flags & ATA_FLAG_PIO_DMA) {
tf.protocol = ATA_PROT_ATAPI_DMA;
tf.feature |= ATAPI_PKT_DMA;
} else {
tf.protocol = ATA_PROT_ATAPI;
tf.lbam = (8 * 1024) & 0xff;
tf.lbah = (8 * 1024) >> 8;
}
return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
sense_buf, SCSI_SENSE_BUFFERSIZE);
}
/**
* ata_eh_analyze_serror - analyze SError for a failed port
* @ap: ATA port to analyze SError for
*
* Analyze SError if available and further determine cause of
* failure.
*
* LOCKING:
* None.
*/
static void ata_eh_analyze_serror(struct ata_port *ap)
{
struct ata_eh_context *ehc = &ap->eh_context;
u32 serror = ehc->i.serror;
unsigned int err_mask = 0, action = 0;
if (serror & SERR_PERSISTENT) {
err_mask |= AC_ERR_ATA_BUS;
action |= ATA_EH_HARDRESET;
}
if (serror &
(SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
err_mask |= AC_ERR_ATA_BUS;
action |= ATA_EH_SOFTRESET;
}
if (serror & SERR_PROTOCOL) {
err_mask |= AC_ERR_HSM;
action |= ATA_EH_SOFTRESET;
}
if (serror & SERR_INTERNAL) {
err_mask |= AC_ERR_SYSTEM;
action |= ATA_EH_SOFTRESET;
}
if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG))
ata_ehi_hotplugged(&ehc->i);
ehc->i.err_mask |= err_mask;
ehc->i.action |= action;
}
/**
* ata_eh_analyze_ncq_error - analyze NCQ error
* @ap: ATA port to analyze NCQ error for
*
* Read log page 10h, determine the offending qc and acquire
* error status TF. For NCQ device errors, all LLDDs have to do
* is setting AC_ERR_DEV in ehi->err_mask. This function takes
* care of the rest.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
static void ata_eh_analyze_ncq_error(struct ata_port *ap)
{
struct ata_eh_context *ehc = &ap->eh_context;
struct ata_device *dev = ap->device;
struct ata_queued_cmd *qc;
struct ata_taskfile tf;
int tag, rc;
/* if frozen, we can't do much */
if (ap->flags & ATA_FLAG_FROZEN)
return;
/* is it NCQ device error? */
if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV))
return;
/* has LLDD analyzed already? */
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED))
continue;
if (qc->err_mask)
return;
}
/* okay, this error is ours */
rc = ata_eh_read_log_10h(dev, &tag, &tf);
if (rc) {
ata_port_printk(ap, KERN_ERR, "failed to read log page 10h "
"(errno=%d)\n", rc);
return;
}
if (!(ap->sactive & (1 << tag))) {
ata_port_printk(ap, KERN_ERR, "log page 10h reported "
"inactive tag %d\n", tag);
return;
}
/* we've got the perpetrator, condemn it */
qc = __ata_qc_from_tag(ap, tag);
memcpy(&qc->result_tf, &tf, sizeof(tf));
qc->err_mask |= AC_ERR_DEV;
ehc->i.err_mask &= ~AC_ERR_DEV;
}
/**
* ata_eh_analyze_tf - analyze taskfile of a failed qc
* @qc: qc to analyze
* @tf: Taskfile registers to analyze
*
* Analyze taskfile of @qc and further determine cause of
* failure. This function also requests ATAPI sense data if
* avaliable.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* Determined recovery action
*/
static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
const struct ata_taskfile *tf)
{
unsigned int tmp, action = 0;
u8 stat = tf->command, err = tf->feature;
if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
qc->err_mask |= AC_ERR_HSM;
return ATA_EH_SOFTRESET;
}
if (!(qc->err_mask & AC_ERR_DEV))
return 0;
switch (qc->dev->class) {
case ATA_DEV_ATA:
if (err & ATA_ICRC)
qc->err_mask |= AC_ERR_ATA_BUS;
if (err & ATA_UNC)
qc->err_mask |= AC_ERR_MEDIA;
if (err & ATA_IDNF)
qc->err_mask |= AC_ERR_INVALID;
break;
case ATA_DEV_ATAPI:
tmp = atapi_eh_request_sense(qc->dev,
qc->scsicmd->sense_buffer);
if (!tmp) {
/* ATA_QCFLAG_SENSE_VALID is used to tell
* atapi_qc_complete() that sense data is
* already valid.
*
* TODO: interpret sense data and set
* appropriate err_mask.
*/
qc->flags |= ATA_QCFLAG_SENSE_VALID;
} else
qc->err_mask |= tmp;
}
if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
action |= ATA_EH_SOFTRESET;
return action;
}
static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent)
{
if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT))
return 1;
if (ent->is_io) {
if (ent->err_mask & AC_ERR_HSM)
return 1;
if ((ent->err_mask &
(AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
return 2;
}
return 0;
}
struct speed_down_needed_arg {
u64 since;
int nr_errors[3];
};
static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg)
{
struct speed_down_needed_arg *arg = void_arg;
if (ent->timestamp < arg->since)
return -1;
arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++;
return 0;
}
/**
* ata_eh_speed_down_needed - Determine wheter speed down is necessary
* @dev: Device of interest
*
* This function examines error ring of @dev and determines
* whether speed down is necessary. Speed down is necessary if
* there have been more than 3 of Cat-1 errors or 10 of Cat-2
* errors during last 15 minutes.
*
* Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM
* violation for known supported commands.
*
* Cat-2 errors are unclassified DEV error for known supported
* command.
*
* LOCKING:
* Inherited from caller.
*
* RETURNS:
* 1 if speed down is necessary, 0 otherwise
*/
static int ata_eh_speed_down_needed(struct ata_device *dev)
{
const u64 interval = 15LLU * 60 * HZ;
static const int err_limits[3] = { -1, 3, 10 };
struct speed_down_needed_arg arg;
struct ata_ering_entry *ent;
int err_cat;
u64 j64;
ent = ata_ering_top(&dev->ering);
if (!ent)
return 0;
err_cat = ata_eh_categorize_ering_entry(ent);
if (err_cat == 0)
return 0;
memset(&arg, 0, sizeof(arg));
j64 = get_jiffies_64();
if (j64 >= interval)
arg.since = j64 - interval;
else
arg.since = 0;
ata_ering_map(&dev->ering, speed_down_needed_cb, &arg);
return arg.nr_errors[err_cat] > err_limits[err_cat];
}
/**
* ata_eh_speed_down - record error and speed down if necessary
* @dev: Failed device
* @is_io: Did the device fail during normal IO?
* @err_mask: err_mask of the error
*
* Record error and examine error history to determine whether
* adjusting transmission speed is necessary. It also sets
* transmission limits appropriately if such adjustment is
* necessary.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, -errno otherwise
*/
static int ata_eh_speed_down(struct ata_device *dev, int is_io,
unsigned int err_mask)
{
if (!err_mask)
return 0;
/* record error and determine whether speed down is necessary */
ata_ering_record(&dev->ering, is_io, err_mask);
if (!ata_eh_speed_down_needed(dev))
return 0;
/* speed down SATA link speed if possible */
if (sata_down_spd_limit(dev->ap) == 0)
return ATA_EH_HARDRESET;
/* lower transfer mode */
if (ata_down_xfermask_limit(dev, 0) == 0)
return ATA_EH_SOFTRESET;
ata_dev_printk(dev, KERN_ERR,
"speed down requested but no transfer mode left\n");
return 0;
}
/**
* ata_eh_autopsy - analyze error and determine recovery action
* @ap: ATA port to perform autopsy on
*
* Analyze why @ap failed and determine which recovery action is
* needed. This function also sets more detailed AC_ERR_* values
* and fills sense data for ATAPI CHECK SENSE.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
static void ata_eh_autopsy(struct ata_port *ap)
{
struct ata_eh_context *ehc = &ap->eh_context;
unsigned int action = ehc->i.action;
struct ata_device *failed_dev = NULL;
unsigned int all_err_mask = 0;
int tag, is_io = 0;
u32 serror;
int rc;
DPRINTK("ENTER\n");
/* obtain and analyze SError */
rc = sata_scr_read(ap, SCR_ERROR, &serror);
if (rc == 0) {
ehc->i.serror |= serror;
ata_eh_analyze_serror(ap);
} else if (rc != -EOPNOTSUPP)
action |= ATA_EH_HARDRESET;
/* analyze NCQ failure */
ata_eh_analyze_ncq_error(ap);
/* any real error trumps AC_ERR_OTHER */
if (ehc->i.err_mask & ~AC_ERR_OTHER)
ehc->i.err_mask &= ~AC_ERR_OTHER;
all_err_mask |= ehc->i.err_mask;
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED))
continue;
/* inherit upper level err_mask */
qc->err_mask |= ehc->i.err_mask;
/* analyze TF */
action |= ata_eh_analyze_tf(qc, &qc->result_tf);
/* DEV errors are probably spurious in case of ATA_BUS error */
if (qc->err_mask & AC_ERR_ATA_BUS)
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA |
AC_ERR_INVALID);
/* any real error trumps unknown error */
if (qc->err_mask & ~AC_ERR_OTHER)
qc->err_mask &= ~AC_ERR_OTHER;
/* SENSE_VALID trumps dev/unknown error and revalidation */
if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
action &= ~ATA_EH_REVALIDATE;
}
/* accumulate error info */
failed_dev = qc->dev;
all_err_mask |= qc->err_mask;
if (qc->flags & ATA_QCFLAG_IO)
is_io = 1;
}
/* enforce default EH actions */
if (ap->flags & ATA_FLAG_FROZEN ||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
action |= ATA_EH_SOFTRESET;
else if (all_err_mask)
action |= ATA_EH_REVALIDATE;
/* if we have offending qcs and the associated failed device */
if (failed_dev) {
/* speed down */
action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask);
/* perform per-dev EH action only on the offending device */
ehc->i.dev_action[failed_dev->devno] |=
action & ATA_EH_PERDEV_MASK;
action &= ~ATA_EH_PERDEV_MASK;
}
/* record autopsy result */
ehc->i.dev = failed_dev;
ehc->i.action = action;
DPRINTK("EXIT\n");
}
/**
* ata_eh_report - report error handling to user
* @ap: ATA port EH is going on
*
* Report EH to user.
*
* LOCKING:
* None.
*/
static void ata_eh_report(struct ata_port *ap)
{
struct ata_eh_context *ehc = &ap->eh_context;
const char *frozen, *desc;
int tag, nr_failed = 0;
desc = NULL;
if (ehc->i.desc[0] != '\0')
desc = ehc->i.desc;
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED))
continue;
if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
continue;
nr_failed++;
}
if (!nr_failed && !ehc->i.err_mask)
return;
frozen = "";
if (ap->flags & ATA_FLAG_FROZEN)
frozen = " frozen";
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\n",
ehc->i.err_mask, ap->sactive, ehc->i.serror,
ehc->i.action, frozen);
if (desc)
ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc);
} else {
ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x "
"SAct 0x%x SErr 0x%x action 0x%x%s\n",
ehc->i.err_mask, ap->sactive, ehc->i.serror,
ehc->i.action, frozen);
if (desc)
ata_port_printk(ap, KERN_ERR, "(%s)\n", desc);
}
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
continue;
ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
"Emask 0x%x stat 0x%x err 0x%x (%s)\n",
qc->tag, qc->tf.command, qc->err_mask,
qc->result_tf.command, qc->result_tf.feature,
ata_err_string(qc->err_mask));
}
}
static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
unsigned int *classes)
{
int i, rc;
for (i = 0; i < ATA_MAX_DEVICES; i++)
classes[i] = ATA_DEV_UNKNOWN;
rc = reset(ap, classes);
if (rc)
return rc;
/* If any class isn't ATA_DEV_UNKNOWN, consider classification
* is complete and convert all ATA_DEV_UNKNOWN to
* ATA_DEV_NONE.
*/
for (i = 0; i < ATA_MAX_DEVICES; i++)
if (classes[i] != ATA_DEV_UNKNOWN)
break;
if (i < ATA_MAX_DEVICES)
for (i = 0; i < ATA_MAX_DEVICES; i++)
if (classes[i] == ATA_DEV_UNKNOWN)
classes[i] = ATA_DEV_NONE;
return 0;
}
static int ata_eh_followup_srst_needed(int rc, int classify,
const unsigned int *classes)
{
if (rc == -EAGAIN)
return 1;
if (rc != 0)
return 0;
if (classify && classes[0] == ATA_DEV_UNKNOWN)
return 1;
return 0;
}
static int ata_eh_reset(struct ata_port *ap, int classify,
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
{
struct ata_eh_context *ehc = &ap->eh_context;
unsigned int *classes = ehc->classes;
int tries = ATA_EH_RESET_TRIES;
int verbose = !(ap->flags & ATA_FLAG_LOADING);
unsigned int action;
ata_reset_fn_t reset;
int i, did_followup_srst, rc;
/* Determine which reset to use and record in ehc->i.action.
* prereset() may examine and modify it.
*/
action = ehc->i.action;
ehc->i.action &= ~ATA_EH_RESET_MASK;
if (softreset && (!hardreset || (!sata_set_spd_needed(ap) &&
!(action & ATA_EH_HARDRESET))))
ehc->i.action |= ATA_EH_SOFTRESET;
else
ehc->i.action |= ATA_EH_HARDRESET;
if (prereset) {
rc = prereset(ap);
if (rc) {
ata_port_printk(ap, KERN_ERR,
"prereset failed (errno=%d)\n", rc);
return rc;
}
}
/* prereset() might have modified ehc->i.action */
if (ehc->i.action & ATA_EH_HARDRESET)
reset = hardreset;
else if (ehc->i.action & ATA_EH_SOFTRESET)
reset = softreset;
else {
/* prereset told us not to reset, bang classes and return */
for (i = 0; i < ATA_MAX_DEVICES; i++)
classes[i] = ATA_DEV_NONE;
return 0;
}
/* did prereset() screw up? if so, fix up to avoid oopsing */
if (!reset) {
ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested "
"invalid reset type\n");
if (softreset)
reset = softreset;
else
reset = hardreset;
}
retry:
/* shut up during boot probing */
if (verbose)
ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
reset == softreset ? "soft" : "hard");
/* reset */
ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
ehc->i.flags |= ATA_EHI_DID_RESET;
rc = ata_do_reset(ap, reset, classes);
did_followup_srst = 0;
if (reset == hardreset &&
ata_eh_followup_srst_needed(rc, classify, classes)) {
/* okay, let's do follow-up softreset */
did_followup_srst = 1;
reset = softreset;
if (!reset) {
ata_port_printk(ap, KERN_ERR,
"follow-up softreset required "
"but no softreset avaliable\n");
return -EINVAL;
}
ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
rc = ata_do_reset(ap, reset, classes);
if (rc == 0 && classify &&
classes[0] == ATA_DEV_UNKNOWN) {
ata_port_printk(ap, KERN_ERR,
"classification failed\n");
return -EINVAL;
}
}
if (rc && --tries) {
const char *type;
if (reset == softreset) {
if (did_followup_srst)
type = "follow-up soft";
else
type = "soft";
} else
type = "hard";
ata_port_printk(ap, KERN_WARNING,
"%sreset failed, retrying in 5 secs\n", type);
ssleep(5);
if (reset == hardreset)
sata_down_spd_limit(ap);
if (hardreset)
reset = hardreset;
goto retry;
}
if (rc == 0) {
/* After the reset, the device state is PIO 0 and the
* controller state is undefined. Record the mode.
*/
for (i = 0; i < ATA_MAX_DEVICES; i++)
ap->device[i].pio_mode = XFER_PIO_0;
if (postreset)
postreset(ap, classes);
/* reset successful, schedule revalidation */
ata_eh_done(ap, NULL, ATA_EH_RESET_MASK);
ehc->i.action |= ATA_EH_REVALIDATE;
}
return rc;
}
static int ata_eh_revalidate_and_attach(struct ata_port *ap,
struct ata_device **r_failed_dev)
{
struct ata_eh_context *ehc = &ap->eh_context;
struct ata_device *dev;
unsigned long flags;
int i, rc = 0;
DPRINTK("ENTER\n");
for (i = 0; i < ATA_MAX_DEVICES; i++) {
unsigned int action;
dev = &ap->device[i];
action = ehc->i.action | ehc->i.dev_action[dev->devno];
if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) {
if (ata_port_offline(ap)) {
rc = -EIO;
break;
}
ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
rc = ata_dev_revalidate(dev,
ehc->i.flags & ATA_EHI_DID_RESET);
if (rc)
break;
ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
/* schedule the scsi_rescan_device() here */
queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
} else if (dev->class == ATA_DEV_UNKNOWN &&
ehc->tries[dev->devno] &&
ata_class_enabled(ehc->classes[dev->devno])) {
dev->class = ehc->classes[dev->devno];
rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
if (rc == 0)
rc = ata_dev_configure(dev, 1);
if (rc) {
dev->class = ATA_DEV_UNKNOWN;
break;
}
spin_lock_irqsave(ap->lock, flags);
ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
spin_unlock_irqrestore(ap->lock, flags);
}
}
if (rc)
*r_failed_dev = dev;
DPRINTK("EXIT\n");
return rc;
}
static int ata_port_nr_enabled(struct ata_port *ap)
{
int i, cnt = 0;
for (i = 0; i < ATA_MAX_DEVICES; i++)
if (ata_dev_enabled(&ap->device[i]))
cnt++;
return cnt;
}
static int ata_port_nr_vacant(struct ata_port *ap)
{
int i, cnt = 0;
for (i = 0; i < ATA_MAX_DEVICES; i++)
if (ap->device[i].class == ATA_DEV_UNKNOWN)
cnt++;
return cnt;
}
static int ata_eh_skip_recovery(struct ata_port *ap)
{
struct ata_eh_context *ehc = &ap->eh_context;
int i;
if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap))
return 0;
/* skip if class codes for all vacant slots are ATA_DEV_NONE */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
if (dev->class == ATA_DEV_UNKNOWN &&
ehc->classes[dev->devno] != ATA_DEV_NONE)
return 0;
}
return 1;
}
/**
* ata_eh_recover - recover host port after error
* @ap: host port to recover
* @prereset: prereset method (can be NULL)
* @softreset: softreset method (can be NULL)
* @hardreset: hardreset method (can be NULL)
* @postreset: postreset method (can be NULL)
*
* This is the alpha and omega, eum and yang, heart and soul of
* libata exception handling. On entry, actions required to
* recover the port and hotplug requests are recorded in
* eh_context. This function executes all the operations with
* appropriate retrials and fallbacks to resurrect failed
* devices, detach goners and greet newcomers.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, -errno on failure.
*/
static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset)
{
struct ata_eh_context *ehc = &ap->eh_context;
struct ata_device *dev;
int down_xfermask, i, rc;
DPRINTK("ENTER\n");
/* prep for recovery */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
dev = &ap->device[i];
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
/* process hotplug request */
if (dev->flags & ATA_DFLAG_DETACH)
ata_eh_detach_dev(dev);
if (!ata_dev_enabled(dev) &&
((ehc->i.probe_mask & (1 << dev->devno)) &&
!(ehc->did_probe_mask & (1 << dev->devno)))) {
ata_eh_detach_dev(dev);
ata_dev_init(dev);
ehc->did_probe_mask |= (1 << dev->devno);
ehc->i.action |= ATA_EH_SOFTRESET;
}
}
retry:
down_xfermask = 0;
rc = 0;
/* if UNLOADING, finish immediately */
if (ap->flags & ATA_FLAG_UNLOADING)
goto out;
/* skip EH if possible. */
if (ata_eh_skip_recovery(ap))
ehc->i.action = 0;
for (i = 0; i < ATA_MAX_DEVICES; i++)
ehc->classes[i] = ATA_DEV_UNKNOWN;
/* reset */
if (ehc->i.action & ATA_EH_RESET_MASK) {
ata_eh_freeze_port(ap);
rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset,
softreset, hardreset, postreset);
if (rc) {
ata_port_printk(ap, KERN_ERR,
"reset failed, giving up\n");
goto out;
}
ata_eh_thaw_port(ap);
}
/* revalidate existing devices and attach new ones */
rc = ata_eh_revalidate_and_attach(ap, &dev);
if (rc)
goto dev_fail;
/* configure transfer mode if the port has been reset */
if (ehc->i.flags & ATA_EHI_DID_RESET) {
rc = ata_set_mode(ap, &dev);
if (rc) {
down_xfermask = 1;
goto dev_fail;
}
}
goto out;
dev_fail:
switch (rc) {
case -ENODEV:
/* device missing, schedule probing */
ehc->i.probe_mask |= (1 << dev->devno);
case -EINVAL:
ehc->tries[dev->devno] = 0;
break;
case -EIO:
sata_down_spd_limit(ap);
default:
ehc->tries[dev->devno]--;
if (down_xfermask &&
ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1))
ehc->tries[dev->devno] = 0;
}
if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
/* disable device if it has used up all its chances */
ata_dev_disable(dev);
/* detach if offline */
if (ata_port_offline(ap))
ata_eh_detach_dev(dev);
/* probe if requested */
if ((ehc->i.probe_mask & (1 << dev->devno)) &&
!(ehc->did_probe_mask & (1 << dev->devno))) {
ata_eh_detach_dev(dev);
ata_dev_init(dev);
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
ehc->did_probe_mask |= (1 << dev->devno);
ehc->i.action |= ATA_EH_SOFTRESET;
}
} else {
/* soft didn't work? be haaaaard */
if (ehc->i.flags & ATA_EHI_DID_RESET)
ehc->i.action |= ATA_EH_HARDRESET;
else
ehc->i.action |= ATA_EH_SOFTRESET;
}
if (ata_port_nr_enabled(ap)) {
ata_port_printk(ap, KERN_WARNING, "failed to recover some "
"devices, retrying in 5 secs\n");
ssleep(5);
} else {
/* no device left, repeat fast */
msleep(500);
}
goto retry;
out:
if (rc) {
for (i = 0; i < ATA_MAX_DEVICES; i++)
ata_dev_disable(&ap->device[i]);
}
DPRINTK("EXIT, rc=%d\n", rc);
return rc;
}
/**
* ata_eh_finish - finish up EH
* @ap: host port to finish EH for
*
* Recovery is complete. Clean up EH states and retry or finish
* failed qcs.
*
* LOCKING:
* None.
*/
static void ata_eh_finish(struct ata_port *ap)
{
int tag;
/* retry or finish qcs */
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
if (!(qc->flags & ATA_QCFLAG_FAILED))
continue;
if (qc->err_mask) {
/* FIXME: Once EH migration is complete,
* generate sense data in this function,
* considering both err_mask and tf.
*/
if (qc->err_mask & AC_ERR_INVALID)
ata_eh_qc_complete(qc);
else
ata_eh_qc_retry(qc);
} else {
if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
ata_eh_qc_complete(qc);
} else {
/* feed zero TF to sense generation */
memset(&qc->result_tf, 0, sizeof(qc->result_tf));
ata_eh_qc_retry(qc);
}
}
}
}
/**
* ata_do_eh - do standard error handling
* @ap: host port to handle error for
* @prereset: prereset method (can be NULL)
* @softreset: softreset method (can be NULL)
* @hardreset: hardreset method (can be NULL)
* @postreset: postreset method (can be NULL)
*
* Perform standard error handling sequence.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset)
{
if (!(ap->flags & ATA_FLAG_LOADING)) {
ata_eh_autopsy(ap);
ata_eh_report(ap);
}
ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
ata_eh_finish(ap);
}
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_eh.h> #include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h> #include <scsi/scsi_transport.h>
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
...@@ -51,10 +52,14 @@ ...@@ -51,10 +52,14 @@
#define SECTOR_SIZE 512 #define SECTOR_SIZE 512
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
static struct ata_device *
ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
static void ata_scsi_error(struct Scsi_Host *host); const struct scsi_device *scsidev);
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun);
#define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE 0x1
#define RW_RECOVERY_MPAGE_LEN 12 #define RW_RECOVERY_MPAGE_LEN 12
...@@ -102,6 +107,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { ...@@ -102,6 +107,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
struct scsi_transport_template ata_scsi_transport_template = { struct scsi_transport_template ata_scsi_transport_template = {
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.eh_timed_out = ata_scsi_timed_out, .eh_timed_out = ata_scsi_timed_out,
.user_scan = ata_scsi_user_scan,
}; };
...@@ -304,7 +310,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) ...@@ -304,7 +310,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
/** /**
* ata_scsi_qc_new - acquire new ata_queued_cmd reference * ata_scsi_qc_new - acquire new ata_queued_cmd reference
* @ap: ATA port to which the new command is attached
* @dev: ATA device to which the new command is attached * @dev: ATA device to which the new command is attached
* @cmd: SCSI command that originated this ATA command * @cmd: SCSI command that originated this ATA command
* @done: SCSI command completion function * @done: SCSI command completion function
...@@ -323,14 +328,13 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) ...@@ -323,14 +328,13 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
* RETURNS: * RETURNS:
* Command allocated, or %NULL if none available. * Command allocated, or %NULL if none available.
*/ */
struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
struct ata_device *dev,
struct scsi_cmnd *cmd, struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *)) void (*done)(struct scsi_cmnd *))
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_new_init(ap, dev); qc = ata_qc_new_init(dev);
if (qc) { if (qc) {
qc->scsicmd = cmd; qc->scsicmd = cmd;
qc->scsidone = done; qc->scsidone = done;
...@@ -397,18 +401,18 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) ...@@ -397,18 +401,18 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
int ata_scsi_device_resume(struct scsi_device *sdev) int ata_scsi_device_resume(struct scsi_device *sdev)
{ {
struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = &ap->device[sdev->id]; struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
return ata_device_resume(ap, dev); return ata_device_resume(dev);
} }
int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
{ {
struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = &ap->device[sdev->id]; struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
return ata_device_suspend(ap, dev, state); return ata_device_suspend(dev, state);
} }
/** /**
...@@ -419,6 +423,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) ...@@ -419,6 +423,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
* @sk: the sense key we'll fill out * @sk: the sense key we'll fill out
* @asc: the additional sense code we'll fill out * @asc: the additional sense code we'll fill out
* @ascq: the additional sense code qualifier we'll fill out * @ascq: the additional sense code qualifier we'll fill out
* @verbose: be verbose
* *
* Converts an ATA error into a SCSI error. Fill out pointers to * Converts an ATA error into a SCSI error. Fill out pointers to
* SK, ASC, and ASCQ bytes for later use in fixed or descriptor * SK, ASC, and ASCQ bytes for later use in fixed or descriptor
...@@ -428,7 +433,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) ...@@ -428,7 +433,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
*/ */
void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
u8 *ascq) u8 *ascq, int verbose)
{ {
int i; int i;
...@@ -493,6 +498,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, ...@@ -493,6 +498,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
} }
} }
/* No immediate match */ /* No immediate match */
if (verbose)
printk(KERN_WARNING "ata%u: no sense translation for " printk(KERN_WARNING "ata%u: no sense translation for "
"error 0x%02x\n", id, drv_err); "error 0x%02x\n", id, drv_err);
} }
...@@ -507,8 +513,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, ...@@ -507,8 +513,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
} }
} }
/* No error? Undecoded? */ /* No error? Undecoded? */
printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", if (verbose)
id, drv_stat); 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 /* 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 */ that won't cause people to do things like return a disk wrongly */
...@@ -517,9 +524,10 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, ...@@ -517,9 +524,10 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
*ascq = 0x00; *ascq = 0x00;
translate_done: translate_done:
printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " if (verbose)
"SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err, printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x "
*sk, *asc, *ascq); "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
id, drv_stat, drv_err, *sk, *asc, *ascq);
return; return;
} }
...@@ -539,27 +547,23 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, ...@@ -539,27 +547,23 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
{ {
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->tf; struct ata_taskfile *tf = &qc->result_tf;
unsigned char *sb = cmd->sense_buffer; unsigned char *sb = cmd->sense_buffer;
unsigned char *desc = sb + 8; unsigned char *desc = sb + 8;
int verbose = qc->ap->ops->error_handler == NULL;
memset(sb, 0, SCSI_SENSE_BUFFERSIZE); memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
/*
* Read the controller registers.
*/
WARN_ON(qc->ap->ops->tf_read == NULL);
qc->ap->ops->tf_read(qc->ap, tf);
/* /*
* Use ata_to_sense_error() to map status register bits * Use ata_to_sense_error() to map status register bits
* onto sense key, asc & ascq. * onto sense key, asc & ascq.
*/ */
if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { if (qc->err_mask ||
tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
ata_to_sense_error(qc->ap->id, tf->command, tf->feature, ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
&sb[1], &sb[2], &sb[3]); &sb[1], &sb[2], &sb[3], verbose);
sb[1] &= 0x0f; sb[1] &= 0x0f;
} }
...@@ -615,26 +619,22 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) ...@@ -615,26 +619,22 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
void ata_gen_fixed_sense(struct ata_queued_cmd *qc) void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
{ {
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->tf; struct ata_taskfile *tf = &qc->result_tf;
unsigned char *sb = cmd->sense_buffer; unsigned char *sb = cmd->sense_buffer;
int verbose = qc->ap->ops->error_handler == NULL;
memset(sb, 0, SCSI_SENSE_BUFFERSIZE); memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
/*
* Read the controller registers.
*/
WARN_ON(qc->ap->ops->tf_read == NULL);
qc->ap->ops->tf_read(qc->ap, tf);
/* /*
* Use ata_to_sense_error() to map status register bits * Use ata_to_sense_error() to map status register bits
* onto sense key, asc & ascq. * onto sense key, asc & ascq.
*/ */
if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { if (qc->err_mask ||
tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
ata_to_sense_error(qc->ap->id, tf->command, tf->feature, ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
&sb[2], &sb[12], &sb[13]); &sb[2], &sb[12], &sb[13], verbose);
sb[2] &= 0x0f; sb[2] &= 0x0f;
} }
...@@ -677,7 +677,7 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, ...@@ -677,7 +677,7 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
*/ */
max_sectors = ATA_MAX_SECTORS; max_sectors = ATA_MAX_SECTORS;
if (dev->flags & ATA_DFLAG_LBA48) if (dev->flags & ATA_DFLAG_LBA48)
max_sectors = 2048; max_sectors = ATA_MAX_SECTORS_LBA48;
if (dev->max_sectors) if (dev->max_sectors)
max_sectors = dev->max_sectors; max_sectors = dev->max_sectors;
...@@ -692,6 +692,14 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, ...@@ -692,6 +692,14 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
request_queue_t *q = sdev->request_queue; request_queue_t *q = sdev->request_queue;
blk_queue_max_hw_segments(q, q->max_hw_segments - 1); blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
} }
if (dev->flags & ATA_DFLAG_NCQ) {
int depth;
depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
depth = min(ATA_MAX_QUEUE - 1, depth);
scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
}
} }
/** /**
...@@ -708,152 +716,88 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, ...@@ -708,152 +716,88 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
int ata_scsi_slave_config(struct scsi_device *sdev) int ata_scsi_slave_config(struct scsi_device *sdev)
{ {
struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
ata_scsi_sdev_config(sdev); ata_scsi_sdev_config(sdev);
blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD);
if (sdev->id < ATA_MAX_DEVICES) { if (dev)
struct ata_port *ap;
struct ata_device *dev;
ap = (struct ata_port *) &sdev->host->hostdata[0];
dev = &ap->device[sdev->id];
ata_scsi_dev_config(sdev, dev); ata_scsi_dev_config(sdev, dev);
}
return 0; /* scsi layer doesn't check return value, sigh */ return 0; /* scsi layer doesn't check return value, sigh */
} }
/** /**
* ata_scsi_timed_out - SCSI layer time out callback * ata_scsi_slave_destroy - SCSI device is about to be destroyed
* @cmd: timed out SCSI command * @sdev: SCSI device to be destroyed
* *
* Handles SCSI layer timeout. We race with normal completion of * @sdev is about to be destroyed for hot/warm unplugging. If
* the qc for @cmd. If the qc is already gone, we lose and let * this unplugging was initiated by libata as indicated by NULL
* the scsi command finish (EH_HANDLED). Otherwise, the qc has * dev->sdev, this function doesn't have to do anything.
* timed out and EH should be invoked. Prevent ata_qc_complete() * Otherwise, SCSI layer initiated warm-unplug is in progress.
* from finishing it by setting EH_SCHEDULED and return * Clear dev->sdev, schedule the device for ATA detach and invoke
* EH_NOT_HANDLED. * EH.
* *
* LOCKING: * LOCKING:
* Called from timer context * Defined by SCSI layer. We don't really care.
*
* RETURNS:
* EH_HANDLED or EH_NOT_HANDLED
*/ */
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) void ata_scsi_slave_destroy(struct scsi_device *sdev)
{ {
struct Scsi_Host *host = cmd->device->host; struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
unsigned long flags; unsigned long flags;
struct ata_queued_cmd *qc; struct ata_device *dev;
enum scsi_eh_timer_return ret = EH_HANDLED;
DPRINTK("ENTER\n"); if (!ap->ops->error_handler)
return;
spin_lock_irqsave(&ap->host_set->lock, flags); spin_lock_irqsave(ap->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag); dev = __ata_scsi_find_dev(ap, sdev);
if (qc) { if (dev && dev->sdev) {
WARN_ON(qc->scsicmd != cmd); /* SCSI device already in CANCEL state, no need to offline it */
qc->flags |= ATA_QCFLAG_EH_SCHEDULED; dev->sdev = NULL;
qc->err_mask |= AC_ERR_TIMEOUT; dev->flags |= ATA_DFLAG_DETACH;
ret = EH_NOT_HANDLED; ata_port_schedule_eh(ap);
} }
spin_unlock_irqrestore(&ap->host_set->lock, flags); spin_unlock_irqrestore(ap->lock, flags);
DPRINTK("EXIT, ret=%d\n", ret);
return ret;
} }
/** /**
* ata_scsi_error - SCSI layer error handler callback * ata_scsi_change_queue_depth - SCSI callback for queue depth config
* @host: SCSI host on which error occurred * @sdev: SCSI device to configure queue depth for
* @queue_depth: new queue depth
* *
* Handles SCSI-layer-thrown error events. * 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: * LOCKING:
* Inherited from SCSI layer (none, can sleep) * SCSI layer (we don't care)
*
* RETURNS:
* Newly configured queue depth.
*/ */
int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
static void ata_scsi_error(struct Scsi_Host *host)
{
struct ata_port *ap;
unsigned long flags;
DPRINTK("ENTER\n");
ap = (struct ata_port *) &host->hostdata[0];
spin_lock_irqsave(&ap->host_set->lock, flags);
WARN_ON(ap->flags & ATA_FLAG_IN_EH);
ap->flags |= ATA_FLAG_IN_EH;
WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
ata_port_flush_task(ap);
ap->ops->eng_timeout(ap);
WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
scsi_eh_flush_done_q(&ap->eh_done_q);
spin_lock_irqsave(&ap->host_set->lock, flags);
ap->flags &= ~ATA_FLAG_IN_EH;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
DPRINTK("EXIT\n");
}
static void ata_eh_scsidone(struct scsi_cmnd *scmd)
{ {
/* nada */ struct ata_port *ap = ata_shost_to_port(sdev->host);
} struct ata_device *dev;
int max_depth;
static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) if (queue_depth < 1)
{ return sdev->queue_depth;
struct ata_port *ap = qc->ap;
struct scsi_cmnd *scmd = qc->scsicmd;
unsigned long flags;
spin_lock_irqsave(&ap->host_set->lock, flags); dev = ata_scsi_find_dev(ap, sdev);
qc->scsidone = ata_eh_scsidone; if (!dev || !ata_dev_enabled(dev))
__ata_qc_complete(qc); return sdev->queue_depth;
WARN_ON(ata_tag_valid(qc->tag));
spin_unlock_irqrestore(&ap->host_set->lock, flags);
scsi_eh_finish_cmd(scmd, &ap->eh_done_q); max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
} max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
if (queue_depth > max_depth)
queue_depth = max_depth;
/** scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
* ata_eh_qc_complete - Complete an active ATA command from EH return queue_depth;
* @qc: Command to complete
*
* Indicate to the mid and upper layers that an ATA command has
* completed. To be used from EH.
*/
void ata_eh_qc_complete(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
scmd->retries = scmd->allowed;
__ata_eh_qc_complete(qc);
}
/**
* ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
* @qc: Command to retry
*
* Indicate to the mid and upper layers that an ATA command
* should be retried. To be used from EH.
*
* SCSI midlayer limits the number of retries to scmd->allowed.
* This function might need to adjust scmd->retries for commands
* which get retried due to unrelated NCQ failures.
*/
void ata_eh_qc_retry(struct ata_queued_cmd *qc)
{
__ata_eh_qc_complete(qc);
} }
/** /**
...@@ -891,7 +835,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc, ...@@ -891,7 +835,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
tf->nsect = 1; /* 1 sector, lba=0 */ tf->nsect = 1; /* 1 sector, lba=0 */
if (qc->dev->flags & ATA_DFLAG_LBA) { if (qc->dev->flags & ATA_DFLAG_LBA) {
qc->tf.flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA;
tf->lbah = 0x0; tf->lbah = 0x0;
tf->lbam = 0x0; tf->lbam = 0x0;
...@@ -1195,6 +1139,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm ...@@ -1195,6 +1139,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
u64 block; u64 block;
u32 n_block; u32 n_block;
qc->flags |= ATA_QCFLAG_IO;
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 || if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
...@@ -1241,7 +1186,36 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm ...@@ -1241,7 +1186,36 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
*/ */
goto nothing_to_do; goto nothing_to_do;
if (dev->flags & ATA_DFLAG_LBA) { if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
/* yay, NCQ */
if (!lba_48_ok(block, n_block))
goto out_of_range;
tf->protocol = ATA_PROT_NCQ;
tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
if (tf->flags & ATA_TFLAG_WRITE)
tf->command = ATA_CMD_FPDMA_WRITE;
else
tf->command = ATA_CMD_FPDMA_READ;
qc->nsect = n_block;
tf->nsect = qc->tag << 3;
tf->hob_feature = (n_block >> 8) & 0xff;
tf->feature = n_block & 0xff;
tf->hob_lbah = (block >> 40) & 0xff;
tf->hob_lbam = (block >> 32) & 0xff;
tf->hob_lbal = (block >> 24) & 0xff;
tf->lbah = (block >> 16) & 0xff;
tf->lbam = (block >> 8) & 0xff;
tf->lbal = block & 0xff;
tf->device = 1 << 6;
if (tf->flags & ATA_TFLAG_FUA)
tf->device |= 1 << 7;
} else if (dev->flags & ATA_DFLAG_LBA) {
tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA;
if (lba_28_ok(block, n_block)) { if (lba_28_ok(block, n_block)) {
...@@ -1332,6 +1306,17 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ...@@ -1332,6 +1306,17 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
u8 *cdb = cmd->cmnd; u8 *cdb = cmd->cmnd;
int need_sense = (qc->err_mask != 0); int need_sense = (qc->err_mask != 0);
/* We snoop the SET_FEATURES - Write Cache ON/OFF command, and
* schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
* cache
*/
if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
((qc->tf.feature == SETFEATURES_WC_ON) ||
(qc->tf.feature == SETFEATURES_WC_OFF))) {
qc->ap->eh_info.action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(qc->ap);
}
/* For ATA pass thru (SAT) commands, generate a sense block if /* For ATA pass thru (SAT) commands, generate a sense block if
* user mandated it or if there's an error. Note that if we * user mandated it or if there's an error. Note that if we
* generate because the user forced us to, a check condition * generate because the user forced us to, a check condition
...@@ -1356,19 +1341,49 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ...@@ -1356,19 +1341,49 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
} }
} }
if (need_sense) { if (need_sense && !qc->ap->ops->error_handler)
/* The ata_gen_..._sense routines fill in tf */ ata_dump_status(qc->ap->id, &qc->result_tf);
ata_dump_status(qc->ap->id, &qc->tf);
}
qc->scsidone(cmd); qc->scsidone(cmd);
ata_qc_free(qc); ata_qc_free(qc);
} }
/**
* ata_scmd_need_defer - Check whether we need to defer scmd
* @dev: ATA device to which the command is addressed
* @is_io: Is the command IO (and thus possibly NCQ)?
*
* NCQ and non-NCQ commands cannot run together. As upper layer
* only knows the queue depth, we are responsible for maintaining
* exclusion. This function checks whether a new command can be
* issued to @dev.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS:
* 1 if deferring is needed, 0 otherwise.
*/
static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
{
struct ata_port *ap = dev->ap;
if (!(dev->flags & ATA_DFLAG_NCQ))
return 0;
if (is_io) {
if (!ata_tag_valid(ap->active_tag))
return 0;
} else {
if (!ata_tag_valid(ap->active_tag) && !ap->sactive)
return 0;
}
return 1;
}
/** /**
* ata_scsi_translate - Translate then issue SCSI command to ATA device * ata_scsi_translate - Translate then issue SCSI command to ATA device
* @ap: ATA port to which the command is addressed
* @dev: ATA device to which the command is addressed * @dev: ATA device to which the command is addressed
* @cmd: SCSI command to execute * @cmd: SCSI command to execute
* @done: SCSI command completion function * @done: SCSI command completion function
...@@ -1389,19 +1404,25 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ...@@ -1389,19 +1404,25 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
*
* RETURNS:
* 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command
* needs to be deferred.
*/ */
static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *), void (*done)(struct scsi_cmnd *),
ata_xlat_func_t xlat_func) ata_xlat_func_t xlat_func)
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
u8 *scsicmd = cmd->cmnd; u8 *scsicmd = cmd->cmnd;
int is_io = xlat_func == ata_scsi_rw_xlat;
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
qc = ata_scsi_qc_new(ap, dev, cmd, done); if (unlikely(ata_scmd_need_defer(dev, is_io)))
goto defer;
qc = ata_scsi_qc_new(dev, cmd, done);
if (!qc) if (!qc)
goto err_mem; goto err_mem;
...@@ -1409,8 +1430,8 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, ...@@ -1409,8 +1430,8 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
if (cmd->sc_data_direction == DMA_FROM_DEVICE || if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
cmd->sc_data_direction == DMA_TO_DEVICE) { cmd->sc_data_direction == DMA_TO_DEVICE) {
if (unlikely(cmd->request_bufflen < 1)) { if (unlikely(cmd->request_bufflen < 1)) {
printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", ata_dev_printk(dev, KERN_WARNING,
ap->id, dev->devno); "WARNING: zero len r/w req\n");
goto err_did; goto err_did;
} }
...@@ -1432,13 +1453,13 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, ...@@ -1432,13 +1453,13 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
ata_qc_issue(qc); ata_qc_issue(qc);
VPRINTK("EXIT\n"); VPRINTK("EXIT\n");
return; return 0;
early_finish: early_finish:
ata_qc_free(qc); ata_qc_free(qc);
done(cmd); done(cmd);
DPRINTK("EXIT - early finish (good or error)\n"); DPRINTK("EXIT - early finish (good or error)\n");
return; return 0;
err_did: err_did:
ata_qc_free(qc); ata_qc_free(qc);
...@@ -1446,7 +1467,11 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, ...@@ -1446,7 +1467,11 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
cmd->result = (DID_ERROR << 16); cmd->result = (DID_ERROR << 16);
done(cmd); done(cmd);
DPRINTK("EXIT - internal\n"); DPRINTK("EXIT - internal\n");
return; return 0;
defer:
DPRINTK("EXIT - defer\n");
return SCSI_MLQUEUE_DEVICE_BUSY;
} }
/** /**
...@@ -1944,7 +1969,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, ...@@ -1944,7 +1969,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
return 0; return 0;
dpofua = 0; dpofua = 0;
if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
(!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
dpofua = 1 << 4; dpofua = 1 << 4;
...@@ -2137,13 +2162,14 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 ...@@ -2137,13 +2162,14 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
static void atapi_sense_complete(struct ata_queued_cmd *qc) static void atapi_sense_complete(struct ata_queued_cmd *qc)
{ {
if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
/* FIXME: not quite right; we don't want the /* FIXME: not quite right; we don't want the
* translation of taskfile registers into * translation of taskfile registers into
* a sense descriptors, since that's only * a sense descriptors, since that's only
* correct for ATA, not ATAPI * correct for ATA, not ATAPI
*/ */
ata_gen_ata_desc_sense(qc); ata_gen_ata_desc_sense(qc);
}
qc->scsidone(qc->scsicmd); qc->scsidone(qc->scsicmd);
ata_qc_free(qc); ata_qc_free(qc);
...@@ -2207,21 +2233,38 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) ...@@ -2207,21 +2233,38 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
VPRINTK("ENTER, err_mask 0x%X\n", err_mask); VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
/* handle completion from new EH */
if (unlikely(qc->ap->ops->error_handler &&
(err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) {
if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
/* FIXME: not quite right; we don't want the
* translation of taskfile registers into a
* sense descriptors, since that's only
* correct for ATA, not ATAPI
*/
ata_gen_ata_desc_sense(qc);
}
qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
qc->scsidone(cmd);
ata_qc_free(qc);
return;
}
/* successful completion or old EH failure path */
if (unlikely(err_mask & AC_ERR_DEV)) { if (unlikely(err_mask & AC_ERR_DEV)) {
cmd->result = SAM_STAT_CHECK_CONDITION; cmd->result = SAM_STAT_CHECK_CONDITION;
atapi_request_sense(qc); atapi_request_sense(qc);
return; return;
} } else if (unlikely(err_mask)) {
else if (unlikely(err_mask))
/* FIXME: not quite right; we don't want the /* FIXME: not quite right; we don't want the
* translation of taskfile registers into * translation of taskfile registers into
* a sense descriptors, since that's only * a sense descriptors, since that's only
* correct for ATA, not ATAPI * correct for ATA, not ATAPI
*/ */
ata_gen_ata_desc_sense(qc); ata_gen_ata_desc_sense(qc);
} else {
else {
u8 *scsicmd = cmd->cmnd; u8 *scsicmd = cmd->cmnd;
if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) { if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
...@@ -2303,11 +2346,9 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) ...@@ -2303,11 +2346,9 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.protocol = ATA_PROT_ATAPI_DMA;
qc->tf.feature |= ATAPI_PKT_DMA; qc->tf.feature |= ATAPI_PKT_DMA;
#ifdef ATAPI_ENABLE_DMADIR if (atapi_dmadir && (cmd->sc_data_direction != DMA_TO_DEVICE))
/* some SATA bridges need us to indicate data xfer direction */ /* some SATA bridges need us to indicate data xfer direction */
if (cmd->sc_data_direction != DMA_TO_DEVICE)
qc->tf.feature |= ATAPI_DMADIR; qc->tf.feature |= ATAPI_DMADIR;
#endif
} }
qc->nbytes = cmd->request_bufflen; qc->nbytes = cmd->request_bufflen;
...@@ -2315,6 +2356,53 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) ...@@ -2315,6 +2356,53 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
return 0; return 0;
} }
static struct ata_device * ata_find_dev(struct ata_port *ap, int id)
{
if (likely(id < ATA_MAX_DEVICES))
return &ap->device[id];
return NULL;
}
static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev)
{
/* skip commands not addressed to targets we simulate */
if (unlikely(scsidev->channel || scsidev->lun))
return NULL;
return ata_find_dev(ap, scsidev->id);
}
/**
* ata_scsi_dev_enabled - determine if device is enabled
* @dev: ATA device
*
* Determine if commands should be sent to the specified device.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS:
* 0 if commands are not allowed / 1 if commands are allowed
*/
static int ata_scsi_dev_enabled(struct ata_device *dev)
{
if (unlikely(!ata_dev_enabled(dev)))
return 0;
if (!atapi_enabled || (dev->ap->flags & ATA_FLAG_NO_ATAPI)) {
if (unlikely(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");
return 0;
}
}
return 1;
}
/** /**
* ata_scsi_find_dev - lookup ata_device from scsi_cmnd * ata_scsi_find_dev - lookup ata_device from scsi_cmnd
* @ap: ATA port to which the device is attached * @ap: ATA port to which the device is attached
...@@ -2331,33 +2419,14 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) ...@@ -2331,33 +2419,14 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
* RETURNS: * RETURNS:
* Associated ATA device, or %NULL if not found. * Associated ATA device, or %NULL if not found.
*/ */
static struct ata_device * static struct ata_device *
ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
{ {
struct ata_device *dev; struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev);
/* skip commands not addressed to targets we simulate */
if (likely(scsidev->id < ATA_MAX_DEVICES))
dev = &ap->device[scsidev->id];
else
return NULL;
if (unlikely((scsidev->channel != 0) || if (unlikely(!dev || !ata_scsi_dev_enabled(dev)))
(scsidev->lun != 0)))
return NULL; return NULL;
if (unlikely(!ata_dev_present(dev)))
return NULL;
if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) {
if (unlikely(dev->class == ATA_DEV_ATAPI)) {
printk(KERN_WARNING "ata%u(%u): WARNING: ATAPI is %s, device ignored.\n",
ap->id, dev->devno, atapi_enabled ? "not supported with this driver" : "disabled");
return NULL;
}
}
return dev; return dev;
} }
...@@ -2414,10 +2483,15 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) ...@@ -2414,10 +2483,15 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
{ {
struct ata_taskfile *tf = &(qc->tf); struct ata_taskfile *tf = &(qc->tf);
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_device *dev = qc->dev;
if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
goto invalid_fld; goto invalid_fld;
/* We may not issue DMA commands if no DMA mode is set */
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
goto invalid_fld;
if (scsicmd[1] & 0xe0) if (scsicmd[1] & 0xe0)
/* PIO multi not supported yet */ /* PIO multi not supported yet */
goto invalid_fld; goto invalid_fld;
...@@ -2502,6 +2576,9 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) ...@@ -2502,6 +2576,9 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
*/ */
qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE; qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE;
/* request result TF */
qc->flags |= ATA_QCFLAG_RESULT_TF;
return 0; return 0;
invalid_fld: invalid_fld:
...@@ -2578,19 +2655,24 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap, ...@@ -2578,19 +2655,24 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
#endif #endif
} }
static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd,
struct ata_port *ap, struct ata_device *dev) void (*done)(struct scsi_cmnd *),
struct ata_device *dev)
{ {
int rc = 0;
if (dev->class == ATA_DEV_ATA) { if (dev->class == ATA_DEV_ATA) {
ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
cmd->cmnd[0]); cmd->cmnd[0]);
if (xlat_func) if (xlat_func)
ata_scsi_translate(ap, dev, cmd, done, xlat_func); rc = ata_scsi_translate(dev, cmd, done, xlat_func);
else else
ata_scsi_simulate(ap, dev, cmd, done); ata_scsi_simulate(dev, cmd, done);
} else } else
ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); rc = ata_scsi_translate(dev, cmd, done, atapi_xlat);
return rc;
} }
/** /**
...@@ -2609,39 +2691,39 @@ static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struc ...@@ -2609,39 +2691,39 @@ static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struc
* Releases scsi-layer-held lock, and obtains host_set lock. * Releases scsi-layer-held lock, and obtains host_set lock.
* *
* RETURNS: * RETURNS:
* Zero. * 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_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
struct ata_port *ap; struct ata_port *ap;
struct ata_device *dev; struct ata_device *dev;
struct scsi_device *scsidev = cmd->device; struct scsi_device *scsidev = cmd->device;
struct Scsi_Host *shost = scsidev->host; struct Scsi_Host *shost = scsidev->host;
int rc = 0;
ap = (struct ata_port *) &shost->hostdata[0]; ap = ata_shost_to_port(shost);
spin_unlock(shost->host_lock); spin_unlock(shost->host_lock);
spin_lock(&ap->host_set->lock); spin_lock(ap->lock);
ata_scsi_dump_cdb(ap, cmd); ata_scsi_dump_cdb(ap, cmd);
dev = ata_scsi_find_dev(ap, scsidev); dev = ata_scsi_find_dev(ap, scsidev);
if (likely(dev)) if (likely(dev))
__ata_scsi_queuecmd(cmd, done, ap, dev); rc = __ata_scsi_queuecmd(cmd, done, dev);
else { else {
cmd->result = (DID_BAD_TARGET << 16); cmd->result = (DID_BAD_TARGET << 16);
done(cmd); done(cmd);
} }
spin_unlock(&ap->host_set->lock); spin_unlock(ap->lock);
spin_lock(shost->host_lock); spin_lock(shost->host_lock);
return 0; return rc;
} }
/** /**
* ata_scsi_simulate - simulate SCSI command on ATA device * ata_scsi_simulate - simulate SCSI command on ATA device
* @ap: port the device is connected to
* @dev: the target device * @dev: the target device
* @cmd: SCSI command being sent to device. * @cmd: SCSI command being sent to device.
* @done: SCSI command completion function. * @done: SCSI command completion function.
...@@ -2653,14 +2735,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) ...@@ -2653,14 +2735,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
*/ */
void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *)) void (*done)(struct scsi_cmnd *))
{ {
struct ata_scsi_args args; struct ata_scsi_args args;
const u8 *scsicmd = cmd->cmnd; const u8 *scsicmd = cmd->cmnd;
args.ap = ap;
args.dev = dev; args.dev = dev;
args.id = dev->id; args.id = dev->id;
args.cmd = cmd; args.cmd = cmd;
...@@ -2732,17 +2812,241 @@ void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, ...@@ -2732,17 +2812,241 @@ void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
void ata_scsi_scan_host(struct ata_port *ap) void ata_scsi_scan_host(struct ata_port *ap)
{ {
struct ata_device *dev;
unsigned int i; unsigned int i;
if (ap->flags & ATA_FLAG_PORT_DISABLED) if (ap->flags & ATA_FLAG_DISABLED)
return; return;
for (i = 0; i < ATA_MAX_DEVICES; i++) { for (i = 0; i < ATA_MAX_DEVICES; i++) {
dev = &ap->device[i]; struct ata_device *dev = &ap->device[i];
struct scsi_device *sdev;
if (!ata_dev_enabled(dev) || dev->sdev)
continue;
sdev = __scsi_add_device(ap->host, 0, i, 0, NULL);
if (!IS_ERR(sdev)) {
dev->sdev = sdev;
scsi_device_put(sdev);
}
}
}
/**
* ata_scsi_offline_dev - offline attached SCSI device
* @dev: ATA device to offline attached SCSI device for
*
* This function is called from ata_eh_hotplug() and responsible
* for taking the SCSI device attached to @dev offline. This
* function is called with host_set lock which protects dev->sdev
* against clearing.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS:
* 1 if attached SCSI device exists, 0 otherwise.
*/
int ata_scsi_offline_dev(struct ata_device *dev)
{
if (dev->sdev) {
scsi_device_set_state(dev->sdev, SDEV_OFFLINE);
return 1;
}
return 0;
}
/**
* ata_scsi_remove_dev - remove attached SCSI device
* @dev: ATA device to remove attached SCSI device for
*
* This function is called from ata_eh_scsi_hotplug() and
* responsible for removing the SCSI device attached to @dev.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
static void ata_scsi_remove_dev(struct ata_device *dev)
{
struct ata_port *ap = dev->ap;
struct scsi_device *sdev;
unsigned long flags;
/* Alas, we need to grab scan_mutex to ensure SCSI device
* state doesn't change underneath us and thus
* scsi_device_get() always succeeds. The mutex locking can
* be removed if there is __scsi_device_get() interface which
* increments reference counts regardless of device state.
*/
mutex_lock(&ap->host->scan_mutex);
spin_lock_irqsave(ap->lock, flags);
/* clearing dev->sdev is protected by host_set lock */
sdev = dev->sdev;
dev->sdev = NULL;
if (sdev) {
/* If user initiated unplug races with us, sdev can go
* away underneath us after the host_set lock and
* scan_mutex are released. Hold onto it.
*/
if (scsi_device_get(sdev) == 0) {
/* The following ensures the attached sdev is
* offline on return from ata_scsi_offline_dev()
* regardless it wins or loses the race
* against this function.
*/
scsi_device_set_state(sdev, SDEV_OFFLINE);
} else {
WARN_ON(1);
sdev = NULL;
}
}
spin_unlock_irqrestore(ap->lock, flags);
mutex_unlock(&ap->host->scan_mutex);
if (ata_dev_present(dev)) if (sdev) {
scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0); ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
sdev->sdev_gendev.bus_id);
scsi_remove_device(sdev);
scsi_device_put(sdev);
} }
} }
/**
* ata_scsi_hotplug - SCSI part of hotplug
* @data: Pointer to ATA port to perform SCSI hotplug on
*
* Perform SCSI part of hotplug. It's executed from a separate
* workqueue after EH completes. This is necessary because SCSI
* hot plugging requires working EH and hot unplugging is
* synchronized with hot plugging with a mutex.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
void ata_scsi_hotplug(void *data)
{
struct ata_port *ap = data;
int i;
if (ap->flags & ATA_FLAG_UNLOADING) {
DPRINTK("ENTER/EXIT - unloading\n");
return;
}
DPRINTK("ENTER\n");
/* unplug detached devices */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
unsigned long flags;
if (!(dev->flags & ATA_DFLAG_DETACHED))
continue;
spin_lock_irqsave(ap->lock, flags);
dev->flags &= ~ATA_DFLAG_DETACHED;
spin_unlock_irqrestore(ap->lock, flags);
ata_scsi_remove_dev(dev);
}
/* scan for new ones */
ata_scsi_scan_host(ap);
/* If we scanned while EH was in progress, scan would have
* failed silently. Requeue if there are enabled but
* unattached devices.
*/
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
if (ata_dev_enabled(dev) && !dev->sdev) {
queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ);
break;
}
}
DPRINTK("EXIT\n");
}
/**
* ata_scsi_user_scan - indication for user-initiated bus scan
* @shost: SCSI host to scan
* @channel: Channel to scan
* @id: ID to scan
* @lun: LUN to scan
*
* This function is called when user explicitly requests bus
* scan. Set probe pending flag and invoke EH.
*
* LOCKING:
* SCSI layer (we don't care)
*
* RETURNS:
* Zero.
*/
static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun)
{
struct ata_port *ap = ata_shost_to_port(shost);
unsigned long flags;
int rc = 0;
if (!ap->ops->error_handler)
return -EOPNOTSUPP;
if ((channel != SCAN_WILD_CARD && channel != 0) ||
(lun != SCAN_WILD_CARD && lun != 0))
return -EINVAL;
spin_lock_irqsave(ap->lock, flags);
if (id == SCAN_WILD_CARD) {
ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
ap->eh_info.action |= ATA_EH_SOFTRESET;
} else {
struct ata_device *dev = ata_find_dev(ap, id);
if (dev) {
ap->eh_info.probe_mask |= 1 << dev->devno;
ap->eh_info.action |= ATA_EH_SOFTRESET;
} else
rc = -EINVAL;
}
if (rc == 0)
ata_port_schedule_eh(ap);
spin_unlock_irqrestore(ap->lock, flags);
return rc;
}
/**
* ata_scsi_dev_rescan - initiate scsi_rescan_device()
* @data: Pointer to ATA port to perform scsi_rescan_device()
*
* After ATA pass thru (SAT) commands are executed successfully,
* libata need to propagate the changes to SCSI layer. This
* function must be executed from ata_aux_wq such that sdev
* attach/detach don't race with rescan.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
void ata_scsi_dev_rescan(void *data)
{
struct ata_port *ap = data;
struct ata_device *dev;
unsigned int i;
for (i = 0; i < ATA_MAX_DEVICES; i++) {
dev = &ap->device[i];
if (ata_dev_enabled(dev) && dev->sdev)
scsi_rescan_device(&(dev->sdev->sdev_gendev));
}
}
...@@ -29,10 +29,9 @@ ...@@ -29,10 +29,9 @@
#define __LIBATA_H__ #define __LIBATA_H__
#define DRV_NAME "libata" #define DRV_NAME "libata"
#define DRV_VERSION "1.20" /* must be exactly four chars */ #define DRV_VERSION "1.30" /* must be exactly four chars */
struct ata_scsi_args { struct ata_scsi_args {
struct ata_port *ap;
struct ata_device *dev; struct ata_device *dev;
u16 *id; u16 *id;
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
...@@ -40,18 +39,32 @@ struct ata_scsi_args { ...@@ -40,18 +39,32 @@ struct ata_scsi_args {
}; };
/* libata-core.c */ /* libata-core.c */
extern struct workqueue_struct *ata_aux_wq;
extern int atapi_enabled; extern int atapi_enabled;
extern int atapi_dmadir;
extern int libata_fua; extern int libata_fua;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
struct ata_device *dev);
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_dev_disable(struct ata_device *dev);
extern void ata_port_flush_task(struct ata_port *ap); extern void ata_port_flush_task(struct ata_port *ap);
extern unsigned ata_exec_internal(struct ata_device *dev,
struct ata_taskfile *tf, const u8 *cdb,
int dma_dir, void *buf, unsigned int buflen);
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
int post_reset, u16 *id);
extern int ata_dev_configure(struct ata_device *dev, int print_info);
extern int sata_down_spd_limit(struct ata_port *ap);
extern int sata_set_spd_needed(struct ata_port *ap);
extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc);
extern void ata_qc_issue(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc);
extern void __ata_qc_complete(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device, extern void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep); unsigned int wait, unsigned int can_sleep);
extern void swap_buf_le16(u16 *buf, unsigned int buf_words); extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
extern void ata_dev_init(struct ata_device *dev);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); 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 int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
...@@ -60,6 +73,8 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); ...@@ -60,6 +73,8 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern struct scsi_transport_template ata_scsi_transport_template; extern struct scsi_transport_template ata_scsi_transport_template;
extern void ata_scsi_scan_host(struct ata_port *ap); extern void ata_scsi_scan_host(struct ata_port *ap);
extern int ata_scsi_offline_dev(struct ata_device *dev);
extern void ata_scsi_hotplug(void *data);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen); unsigned int buflen);
...@@ -88,5 +103,13 @@ extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, ...@@ -88,5 +103,13 @@ extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen)); u8 *rbuf, unsigned int buflen));
extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(void *data);
/* libata-eh.c */
extern enum scsi_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_qc_schedule_eh(struct ata_queued_cmd *qc);
#endif /* __LIBATA_H__ */ #endif /* __LIBATA_H__ */
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "pdc_adma" #define DRV_NAME "pdc_adma"
#define DRV_VERSION "0.03" #define DRV_VERSION "0.04"
/* macro to calculate base address for ATA regs */ /* macro to calculate base address for ATA regs */
#define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40)) #define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40))
...@@ -152,6 +152,7 @@ static struct scsi_host_template adma_ata_sht = { ...@@ -152,6 +152,7 @@ static struct scsi_host_template adma_ata_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ADMA_DMA_BOUNDARY, .dma_boundary = ADMA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -167,6 +168,7 @@ static const struct ata_port_operations adma_ata_ops = { ...@@ -167,6 +168,7 @@ static const struct ata_port_operations adma_ata_ops = {
.qc_prep = adma_qc_prep, .qc_prep = adma_qc_prep,
.qc_issue = adma_qc_issue, .qc_issue = adma_qc_issue,
.eng_timeout = adma_eng_timeout, .eng_timeout = adma_eng_timeout,
.data_xfer = ata_mmio_data_xfer,
.irq_handler = adma_intr, .irq_handler = adma_intr,
.irq_clear = adma_irq_clear, .irq_clear = adma_irq_clear,
.port_start = adma_port_start, .port_start = adma_port_start,
...@@ -455,13 +457,13 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set) ...@@ -455,13 +457,13 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
continue; continue;
handled = 1; handled = 1;
adma_enter_reg_mode(ap); adma_enter_reg_mode(ap);
if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) if (ap->flags & ATA_FLAG_DISABLED)
continue; continue;
pp = ap->private_data; pp = ap->private_data;
if (!pp || pp->state != adma_state_pkt) if (!pp || pp->state != adma_state_pkt)
continue; continue;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
if ((status & (aPERR | aPSD | aUIRQ))) if ((status & (aPERR | aPSD | aUIRQ)))
qc->err_mask |= AC_ERR_OTHER; qc->err_mask |= AC_ERR_OTHER;
else if (pp->pkt[0] != cDONE) else if (pp->pkt[0] != cDONE)
...@@ -480,13 +482,13 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set) ...@@ -480,13 +482,13 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
for (port_no = 0; port_no < host_set->n_ports; ++port_no) { for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
struct ata_port *ap; struct ata_port *ap;
ap = host_set->ports[port_no]; ap = host_set->ports[port_no];
if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) { if (ap && (!(ap->flags & ATA_FLAG_DISABLED))) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
struct adma_port_priv *pp = ap->private_data; struct adma_port_priv *pp = ap->private_data;
if (!pp || pp->state != adma_state_mmio) if (!pp || pp->state != adma_state_mmio)
continue; continue;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
/* check main status, clearing INTRQ */ /* check main status, clearing INTRQ */
u8 status = ata_check_status(ap); u8 status = ata_check_status(ap);
......
...@@ -93,7 +93,7 @@ enum { ...@@ -93,7 +93,7 @@ enum {
MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
ATA_FLAG_NO_ATAPI), ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE,
CRQB_FLAG_READ = (1 << 0), CRQB_FLAG_READ = (1 << 0),
...@@ -272,33 +272,33 @@ enum chip_type { ...@@ -272,33 +272,33 @@ enum chip_type {
/* Command ReQuest Block: 32B */ /* Command ReQuest Block: 32B */
struct mv_crqb { struct mv_crqb {
u32 sg_addr; __le32 sg_addr;
u32 sg_addr_hi; __le32 sg_addr_hi;
u16 ctrl_flags; __le16 ctrl_flags;
u16 ata_cmd[11]; __le16 ata_cmd[11];
}; };
struct mv_crqb_iie { struct mv_crqb_iie {
u32 addr; __le32 addr;
u32 addr_hi; __le32 addr_hi;
u32 flags; __le32 flags;
u32 len; __le32 len;
u32 ata_cmd[4]; __le32 ata_cmd[4];
}; };
/* Command ResPonse Block: 8B */ /* Command ResPonse Block: 8B */
struct mv_crpb { struct mv_crpb {
u16 id; __le16 id;
u16 flags; __le16 flags;
u32 tmstmp; __le32 tmstmp;
}; };
/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */ /* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
struct mv_sg { struct mv_sg {
u32 addr; __le32 addr;
u32 flags_size; __le32 flags_size;
u32 addr_hi; __le32 addr_hi;
u32 reserved; __le32 reserved;
}; };
struct mv_port_priv { struct mv_port_priv {
...@@ -390,6 +390,7 @@ static struct scsi_host_template mv_sht = { ...@@ -390,6 +390,7 @@ static struct scsi_host_template mv_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = MV_DMA_BOUNDARY, .dma_boundary = MV_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -406,6 +407,7 @@ static const struct ata_port_operations mv5_ops = { ...@@ -406,6 +407,7 @@ static const struct ata_port_operations mv5_ops = {
.qc_prep = mv_qc_prep, .qc_prep = mv_qc_prep,
.qc_issue = mv_qc_issue, .qc_issue = mv_qc_issue,
.data_xfer = ata_mmio_data_xfer,
.eng_timeout = mv_eng_timeout, .eng_timeout = mv_eng_timeout,
...@@ -433,6 +435,7 @@ static const struct ata_port_operations mv6_ops = { ...@@ -433,6 +435,7 @@ static const struct ata_port_operations mv6_ops = {
.qc_prep = mv_qc_prep, .qc_prep = mv_qc_prep,
.qc_issue = mv_qc_issue, .qc_issue = mv_qc_issue,
.data_xfer = ata_mmio_data_xfer,
.eng_timeout = mv_eng_timeout, .eng_timeout = mv_eng_timeout,
...@@ -683,7 +686,7 @@ static void mv_stop_dma(struct ata_port *ap) ...@@ -683,7 +686,7 @@ static void mv_stop_dma(struct ata_port *ap)
} }
if (EDMA_EN & reg) { if (EDMA_EN & reg) {
printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id); ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
/* FIXME: Consider doing a reset here to recover */ /* FIXME: Consider doing a reset here to recover */
} }
} }
...@@ -1028,7 +1031,7 @@ static inline unsigned mv_inc_q_index(unsigned index) ...@@ -1028,7 +1031,7 @@ static inline unsigned mv_inc_q_index(unsigned index)
return (index + 1) & MV_MAX_Q_DEPTH_MASK; return (index + 1) & MV_MAX_Q_DEPTH_MASK;
} }
static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last) static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
{ {
u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
(last ? CRQB_CMD_LAST : 0); (last ? CRQB_CMD_LAST : 0);
...@@ -1051,7 +1054,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) ...@@ -1051,7 +1054,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct mv_port_priv *pp = ap->private_data; struct mv_port_priv *pp = ap->private_data;
u16 *cw; __le16 *cw;
struct ata_taskfile *tf; struct ata_taskfile *tf;
u16 flags = 0; u16 flags = 0;
unsigned in_index; unsigned in_index;
...@@ -1307,8 +1310,8 @@ static void mv_err_intr(struct ata_port *ap, int reset_allowed) ...@@ -1307,8 +1310,8 @@ static void mv_err_intr(struct ata_port *ap, int reset_allowed)
edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
if (EDMA_ERR_SERR & edma_err_cause) { if (EDMA_ERR_SERR & edma_err_cause) {
serr = scr_read(ap, SCR_ERROR); sata_scr_read(ap, SCR_ERROR, &serr);
scr_write_flush(ap, SCR_ERROR, serr); sata_scr_write_flush(ap, SCR_ERROR, serr);
} }
if (EDMA_ERR_SELF_DIS & edma_err_cause) { if (EDMA_ERR_SELF_DIS & edma_err_cause) {
struct mv_port_priv *pp = ap->private_data; struct mv_port_priv *pp = ap->private_data;
...@@ -1398,7 +1401,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, ...@@ -1398,7 +1401,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
} }
} }
if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) if (ap && (ap->flags & ATA_FLAG_DISABLED))
continue; continue;
err_mask = ac_err_mask(ata_status); err_mask = ac_err_mask(ata_status);
...@@ -1419,7 +1422,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, ...@@ -1419,7 +1422,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
VPRINTK("port %u IRQ found for qc, " VPRINTK("port %u IRQ found for qc, "
"ata_status 0x%x\n", port,ata_status); "ata_status 0x%x\n", port,ata_status);
/* mark qc status appropriately */ /* mark qc status appropriately */
if (!(qc->tf.ctl & ATA_NIEN)) { if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
qc->err_mask |= err_mask; qc->err_mask |= err_mask;
ata_qc_complete(qc); ata_qc_complete(qc);
} }
...@@ -1949,15 +1952,16 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep) ...@@ -1949,15 +1952,16 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
/* Issue COMRESET via SControl */ /* Issue COMRESET via SControl */
comreset_retry: comreset_retry:
scr_write_flush(ap, SCR_CONTROL, 0x301); sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
__msleep(1, can_sleep); __msleep(1, can_sleep);
scr_write_flush(ap, SCR_CONTROL, 0x300); sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
__msleep(20, can_sleep); __msleep(20, can_sleep);
timeout = jiffies + msecs_to_jiffies(200); timeout = jiffies + msecs_to_jiffies(200);
do { do {
sstatus = scr_read(ap, SCR_STATUS) & 0x3; sata_scr_read(ap, SCR_STATUS, &sstatus);
sstatus &= 0x3;
if ((sstatus == 3) || (sstatus == 0)) if ((sstatus == 3) || (sstatus == 0))
break; break;
...@@ -1974,11 +1978,12 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep) ...@@ -1974,11 +1978,12 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
if (sata_dev_present(ap)) { if (ata_port_online(ap)) {
ata_port_probe(ap); ata_port_probe(ap);
} else { } else {
printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n", sata_scr_read(ap, SCR_STATUS, &sstatus);
ap->id, scr_read(ap, SCR_STATUS)); ata_port_printk(ap, KERN_INFO,
"no device found (phy stat %08x)\n", sstatus);
ata_port_disable(ap); ata_port_disable(ap);
return; return;
} }
...@@ -2005,7 +2010,7 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep) ...@@ -2005,7 +2010,7 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr); tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
dev->class = ata_dev_classify(&tf); dev->class = ata_dev_classify(&tf);
if (!ata_dev_present(dev)) { if (!ata_dev_enabled(dev)) {
VPRINTK("Port disabled post-sig: No device present.\n"); VPRINTK("Port disabled post-sig: No device present.\n");
ata_port_disable(ap); ata_port_disable(ap);
} }
...@@ -2037,7 +2042,7 @@ static void mv_eng_timeout(struct ata_port *ap) ...@@ -2037,7 +2042,7 @@ static void mv_eng_timeout(struct ata_port *ap)
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
unsigned long flags; unsigned long flags;
printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
DPRINTK("All regs @ start of eng_timeout\n"); DPRINTK("All regs @ start of eng_timeout\n");
mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no, mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
to_pci_dev(ap->host_set->dev)); to_pci_dev(ap->host_set->dev));
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "sata_nv" #define DRV_NAME "sata_nv"
#define DRV_VERSION "0.8" #define DRV_VERSION "0.9"
enum { enum {
NV_PORTS = 2, NV_PORTS = 2,
...@@ -54,40 +54,25 @@ enum { ...@@ -54,40 +54,25 @@ enum {
NV_PORT0_SCR_REG_OFFSET = 0x00, NV_PORT0_SCR_REG_OFFSET = 0x00,
NV_PORT1_SCR_REG_OFFSET = 0x40, NV_PORT1_SCR_REG_OFFSET = 0x40,
/* INT_STATUS/ENABLE */
NV_INT_STATUS = 0x10, NV_INT_STATUS = 0x10,
NV_INT_STATUS_CK804 = 0x440,
NV_INT_STATUS_PDEV_INT = 0x01,
NV_INT_STATUS_PDEV_PM = 0x02,
NV_INT_STATUS_PDEV_ADDED = 0x04,
NV_INT_STATUS_PDEV_REMOVED = 0x08,
NV_INT_STATUS_SDEV_INT = 0x10,
NV_INT_STATUS_SDEV_PM = 0x20,
NV_INT_STATUS_SDEV_ADDED = 0x40,
NV_INT_STATUS_SDEV_REMOVED = 0x80,
NV_INT_STATUS_PDEV_HOTPLUG = (NV_INT_STATUS_PDEV_ADDED |
NV_INT_STATUS_PDEV_REMOVED),
NV_INT_STATUS_SDEV_HOTPLUG = (NV_INT_STATUS_SDEV_ADDED |
NV_INT_STATUS_SDEV_REMOVED),
NV_INT_STATUS_HOTPLUG = (NV_INT_STATUS_PDEV_HOTPLUG |
NV_INT_STATUS_SDEV_HOTPLUG),
NV_INT_ENABLE = 0x11, NV_INT_ENABLE = 0x11,
NV_INT_STATUS_CK804 = 0x440,
NV_INT_ENABLE_CK804 = 0x441, NV_INT_ENABLE_CK804 = 0x441,
NV_INT_ENABLE_PDEV_MASK = 0x01,
NV_INT_ENABLE_PDEV_PM = 0x02,
NV_INT_ENABLE_PDEV_ADDED = 0x04,
NV_INT_ENABLE_PDEV_REMOVED = 0x08,
NV_INT_ENABLE_SDEV_MASK = 0x10,
NV_INT_ENABLE_SDEV_PM = 0x20,
NV_INT_ENABLE_SDEV_ADDED = 0x40,
NV_INT_ENABLE_SDEV_REMOVED = 0x80,
NV_INT_ENABLE_PDEV_HOTPLUG = (NV_INT_ENABLE_PDEV_ADDED |
NV_INT_ENABLE_PDEV_REMOVED),
NV_INT_ENABLE_SDEV_HOTPLUG = (NV_INT_ENABLE_SDEV_ADDED |
NV_INT_ENABLE_SDEV_REMOVED),
NV_INT_ENABLE_HOTPLUG = (NV_INT_ENABLE_PDEV_HOTPLUG |
NV_INT_ENABLE_SDEV_HOTPLUG),
/* INT_STATUS/ENABLE bits */
NV_INT_DEV = 0x01,
NV_INT_PM = 0x02,
NV_INT_ADDED = 0x04,
NV_INT_REMOVED = 0x08,
NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */
NV_INT_ALL = 0x0f,
NV_INT_MASK = NV_INT_DEV |
NV_INT_ADDED | NV_INT_REMOVED,
/* INT_CONFIG */
NV_INT_CONFIG = 0x12, NV_INT_CONFIG = 0x12,
NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI
...@@ -97,23 +82,27 @@ enum { ...@@ -97,23 +82,27 @@ enum {
}; };
static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static irqreturn_t nv_interrupt (int irq, void *dev_instance, static void nv_ck804_host_stop(struct ata_host_set *host_set);
static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
struct pt_regs *regs);
static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
struct pt_regs *regs);
static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
struct pt_regs *regs); struct pt_regs *regs);
static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static void nv_host_stop (struct ata_host_set *host_set);
static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); static void nv_nf2_freeze(struct ata_port *ap);
static void nv_disable_hotplug(struct ata_host_set *host_set); static void nv_nf2_thaw(struct ata_port *ap);
static int nv_check_hotplug(struct ata_host_set *host_set); static void nv_ck804_freeze(struct ata_port *ap);
static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); static void nv_ck804_thaw(struct ata_port *ap);
static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); static void nv_error_handler(struct ata_port *ap);
static int nv_check_hotplug_ck804(struct ata_host_set *host_set);
enum nv_host_type enum nv_host_type
{ {
GENERIC, GENERIC,
NFORCE2, NFORCE2,
NFORCE3, NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */
CK804 CK804
}; };
...@@ -140,6 +129,16 @@ static const struct pci_device_id nv_pci_tbl[] = { ...@@ -140,6 +129,16 @@ static const struct pci_device_id nv_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, 0x045c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, 0x045d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, 0x045e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, 0x045f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
...@@ -149,46 +148,6 @@ static const struct pci_device_id nv_pci_tbl[] = { ...@@ -149,46 +148,6 @@ static const struct pci_device_id nv_pci_tbl[] = {
{ 0, } /* terminate list */ { 0, } /* terminate list */
}; };
struct nv_host_desc
{
enum nv_host_type host_type;
void (*enable_hotplug)(struct ata_probe_ent *probe_ent);
void (*disable_hotplug)(struct ata_host_set *host_set);
int (*check_hotplug)(struct ata_host_set *host_set);
};
static struct nv_host_desc nv_device_tbl[] = {
{
.host_type = GENERIC,
.enable_hotplug = NULL,
.disable_hotplug= NULL,
.check_hotplug = NULL,
},
{
.host_type = NFORCE2,
.enable_hotplug = nv_enable_hotplug,
.disable_hotplug= nv_disable_hotplug,
.check_hotplug = nv_check_hotplug,
},
{
.host_type = NFORCE3,
.enable_hotplug = nv_enable_hotplug,
.disable_hotplug= nv_disable_hotplug,
.check_hotplug = nv_check_hotplug,
},
{ .host_type = CK804,
.enable_hotplug = nv_enable_hotplug_ck804,
.disable_hotplug= nv_disable_hotplug_ck804,
.check_hotplug = nv_check_hotplug_ck804,
},
};
struct nv_host
{
struct nv_host_desc *host_desc;
unsigned long host_flags;
};
static struct pci_driver nv_pci_driver = { static struct pci_driver nv_pci_driver = {
.name = DRV_NAME, .name = DRV_NAME,
.id_table = nv_pci_tbl, .id_table = nv_pci_tbl,
...@@ -210,51 +169,119 @@ static struct scsi_host_template nv_sht = { ...@@ -210,51 +169,119 @@ static struct scsi_host_template nv_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
static const struct ata_port_operations nv_ops = { static const struct ata_port_operations nv_generic_ops = {
.port_disable = ata_port_disable, .port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.check_status = ata_check_status, .check_status = ata_check_status,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .freeze = ata_bmdma_freeze,
.irq_handler = nv_interrupt, .thaw = ata_bmdma_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_generic_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.scr_read = nv_scr_read, .scr_read = nv_scr_read,
.scr_write = nv_scr_write, .scr_write = nv_scr_write,
.port_start = ata_port_start, .port_start = ata_port_start,
.port_stop = ata_port_stop, .port_stop = ata_port_stop,
.host_stop = nv_host_stop, .host_stop = ata_pci_host_stop,
}; };
/* FIXME: The hardware provides the necessary SATA PHY controls static const struct ata_port_operations nv_nf2_ops = {
* to support ATA_FLAG_SATA_RESET. However, it is currently .port_disable = ata_port_disable,
* necessary to disable that flag, to solve misdetection problems. .tf_load = ata_tf_load,
* See http://bugme.osdl.org/show_bug.cgi?id=3352 for more info. .tf_read = ata_tf_read,
* .exec_command = ata_exec_command,
* This problem really needs to be investigated further. But in the .check_status = ata_check_status,
* meantime, we avoid ATA_FLAG_SATA_RESET to get people working. .dev_select = ata_std_dev_select,
*/ .bmdma_setup = ata_bmdma_setup,
static struct ata_port_info nv_port_info = { .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.freeze = nv_nf2_freeze,
.thaw = nv_nf2_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_nf2_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = nv_scr_read,
.scr_write = nv_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = ata_pci_host_stop,
};
static const struct ata_port_operations nv_ck804_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.exec_command = ata_exec_command,
.check_status = ata_check_status,
.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,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.freeze = nv_ck804_freeze,
.thaw = nv_ck804_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_ck804_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = nv_scr_read,
.scr_write = nv_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = nv_ck804_host_stop,
};
static struct ata_port_info nv_port_info[] = {
/* generic */
{
.sht = &nv_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
.port_ops = &nv_generic_ops,
},
/* nforce2/3 */
{
.sht = &nv_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
.port_ops = &nv_nf2_ops,
},
/* ck804 */
{
.sht = &nv_sht, .sht = &nv_sht,
.host_flags = ATA_FLAG_SATA | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
/* ATA_FLAG_SATA_RESET | */
ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY,
.pio_mask = NV_PIO_MASK, .pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK, .mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK, .udma_mask = NV_UDMA_MASK,
.port_ops = &nv_ops, .port_ops = &nv_ck804_ops,
},
}; };
MODULE_AUTHOR("NVIDIA"); MODULE_AUTHOR("NVIDIA");
...@@ -263,11 +290,10 @@ MODULE_LICENSE("GPL"); ...@@ -263,11 +290,10 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, nv_pci_tbl); MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
static irqreturn_t nv_interrupt (int irq, void *dev_instance, static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct ata_host_set *host_set = dev_instance; struct ata_host_set *host_set = dev_instance;
struct nv_host *host = host_set->private_data;
unsigned int i; unsigned int i;
unsigned int handled = 0; unsigned int handled = 0;
unsigned long flags; unsigned long flags;
...@@ -279,11 +305,11 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, ...@@ -279,11 +305,11 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance,
ap = host_set->ports[i]; ap = host_set->ports[i];
if (ap && if (ap &&
!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += ata_host_intr(ap, qc); handled += ata_host_intr(ap, qc);
else else
// No request pending? Clear interrupt status // No request pending? Clear interrupt status
...@@ -293,14 +319,88 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, ...@@ -293,14 +319,88 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance,
} }
if (host->host_desc->check_hotplug)
handled += host->host_desc->check_hotplug(host_set);
spin_unlock_irqrestore(&host_set->lock, flags); spin_unlock_irqrestore(&host_set->lock, flags);
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
{
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
int handled;
/* freeze if hotplugged */
if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
ata_port_freeze(ap);
return 1;
}
/* bail out if not our interrupt */
if (!(irq_stat & NV_INT_DEV))
return 0;
/* DEV interrupt w/ no active qc? */
if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
ata_check_status(ap);
return 1;
}
/* handle interrupt */
handled = ata_host_intr(ap, qc);
if (unlikely(!handled)) {
/* spurious, clear it */
ata_check_status(ap);
}
return 1;
}
static irqreturn_t nv_do_interrupt(struct ata_host_set *host_set, u8 irq_stat)
{
int i, handled = 0;
for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap = host_set->ports[i];
if (ap && !(ap->flags & ATA_FLAG_DISABLED))
handled += nv_host_intr(ap, irq_stat);
irq_stat >>= NV_INT_PORT_SHIFT;
}
return IRQ_RETVAL(handled);
}
static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
u8 irq_stat;
irqreturn_t ret;
spin_lock(&host_set->lock);
irq_stat = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
ret = nv_do_interrupt(host_set, irq_stat);
spin_unlock(&host_set->lock);
return ret;
}
static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
u8 irq_stat;
irqreturn_t ret;
spin_lock(&host_set->lock);
irq_stat = readb(host_set->mmio_base + NV_INT_STATUS_CK804);
ret = nv_do_interrupt(host_set, irq_stat);
spin_unlock(&host_set->lock);
return ret;
}
static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg) static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
{ {
if (sc_reg > SCR_CONTROL) if (sc_reg > SCR_CONTROL)
...@@ -317,23 +417,74 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) ...@@ -317,23 +417,74 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
} }
static void nv_host_stop (struct ata_host_set *host_set) static void nv_nf2_freeze(struct ata_port *ap)
{ {
struct nv_host *host = host_set->private_data; unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr;
int shift = ap->port_no * NV_INT_PORT_SHIFT;
u8 mask;
// Disable hotplug event interrupts. mask = inb(scr_addr + NV_INT_ENABLE);
if (host->host_desc->disable_hotplug) mask &= ~(NV_INT_ALL << shift);
host->host_desc->disable_hotplug(host_set); outb(mask, scr_addr + NV_INT_ENABLE);
}
kfree(host); static void nv_nf2_thaw(struct ata_port *ap)
{
unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr;
int shift = ap->port_no * NV_INT_PORT_SHIFT;
u8 mask;
ata_pci_host_stop(host_set); outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
mask = inb(scr_addr + NV_INT_ENABLE);
mask |= (NV_INT_MASK << shift);
outb(mask, scr_addr + NV_INT_ENABLE);
}
static void nv_ck804_freeze(struct ata_port *ap)
{
void __iomem *mmio_base = ap->host_set->mmio_base;
int shift = ap->port_no * NV_INT_PORT_SHIFT;
u8 mask;
mask = readb(mmio_base + NV_INT_ENABLE_CK804);
mask &= ~(NV_INT_ALL << shift);
writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
}
static void nv_ck804_thaw(struct ata_port *ap)
{
void __iomem *mmio_base = ap->host_set->mmio_base;
int shift = ap->port_no * NV_INT_PORT_SHIFT;
u8 mask;
writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804);
mask = readb(mmio_base + NV_INT_ENABLE_CK804);
mask |= (NV_INT_MASK << shift);
writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
}
static int nv_hardreset(struct ata_port *ap, unsigned int *class)
{
unsigned int dummy;
/* SATA hardreset fails to retrieve proper device signature on
* some controllers. Don't classify on hardreset. For more
* info, see http://bugme.osdl.org/show_bug.cgi?id=3352
*/
return sata_std_hardreset(ap, &dummy);
}
static void nv_error_handler(struct ata_port *ap)
{
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
nv_hardreset, ata_std_postreset);
} }
static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
static int printed_version = 0; static int printed_version = 0;
struct nv_host *host;
struct ata_port_info *ppi; struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent; struct ata_probe_ent *probe_ent;
int pci_dev_busy = 0; int pci_dev_busy = 0;
...@@ -370,24 +521,15 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -370,24 +521,15 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
rc = -ENOMEM; rc = -ENOMEM;
ppi = &nv_port_info; ppi = &nv_port_info[ent->driver_data];
probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent) if (!probe_ent)
goto err_out_regions; goto err_out_regions;
host = kmalloc(sizeof(struct nv_host), GFP_KERNEL);
if (!host)
goto err_out_free_ent;
memset(host, 0, sizeof(struct nv_host));
host->host_desc = &nv_device_tbl[ent->driver_data];
probe_ent->private_data = host;
probe_ent->mmio_base = pci_iomap(pdev, 5, 0); probe_ent->mmio_base = pci_iomap(pdev, 5, 0);
if (!probe_ent->mmio_base) { if (!probe_ent->mmio_base) {
rc = -EIO; rc = -EIO;
goto err_out_free_host; goto err_out_free_ent;
} }
base = (unsigned long)probe_ent->mmio_base; base = (unsigned long)probe_ent->mmio_base;
...@@ -395,24 +537,27 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -395,24 +537,27 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET; probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET; probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
/* enable SATA space for CK804 */
if (ent->driver_data == CK804) {
u8 regval;
pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
}
pci_set_master(pdev); pci_set_master(pdev);
rc = ata_device_add(probe_ent); rc = ata_device_add(probe_ent);
if (rc != NV_PORTS) if (rc != NV_PORTS)
goto err_out_iounmap; goto err_out_iounmap;
// Enable hotplug event interrupts.
if (host->host_desc->enable_hotplug)
host->host_desc->enable_hotplug(probe_ent);
kfree(probe_ent); kfree(probe_ent);
return 0; return 0;
err_out_iounmap: err_out_iounmap:
pci_iounmap(pdev, probe_ent->mmio_base); pci_iounmap(pdev, probe_ent->mmio_base);
err_out_free_host:
kfree(host);
err_out_free_ent: err_out_free_ent:
kfree(probe_ent); kfree(probe_ent);
err_out_regions: err_out_regions:
...@@ -424,127 +569,17 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -424,127 +569,17 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc; return rc;
} }
static void nv_enable_hotplug(struct ata_probe_ent *probe_ent) static void nv_ck804_host_stop(struct ata_host_set *host_set)
{
u8 intr_mask;
outb(NV_INT_STATUS_HOTPLUG,
probe_ent->port[0].scr_addr + NV_INT_STATUS);
intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE);
intr_mask |= NV_INT_ENABLE_HOTPLUG;
outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE);
}
static void nv_disable_hotplug(struct ata_host_set *host_set)
{
u8 intr_mask;
intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
}
static int nv_check_hotplug(struct ata_host_set *host_set)
{
u8 intr_status;
intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
// Clear interrupt status.
outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
if (intr_status & NV_INT_STATUS_HOTPLUG) {
if (intr_status & NV_INT_STATUS_PDEV_ADDED)
printk(KERN_WARNING "nv_sata: "
"Primary device added\n");
if (intr_status & NV_INT_STATUS_PDEV_REMOVED)
printk(KERN_WARNING "nv_sata: "
"Primary device removed\n");
if (intr_status & NV_INT_STATUS_SDEV_ADDED)
printk(KERN_WARNING "nv_sata: "
"Secondary device added\n");
if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
printk(KERN_WARNING "nv_sata: "
"Secondary device removed\n");
return 1;
}
return 0;
}
static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent)
{
struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
u8 intr_mask;
u8 regval;
pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804);
intr_mask = readb(probe_ent->mmio_base + NV_INT_ENABLE_CK804);
intr_mask |= NV_INT_ENABLE_HOTPLUG;
writeb(intr_mask, probe_ent->mmio_base + NV_INT_ENABLE_CK804);
}
static void nv_disable_hotplug_ck804(struct ata_host_set *host_set)
{ {
struct pci_dev *pdev = to_pci_dev(host_set->dev); struct pci_dev *pdev = to_pci_dev(host_set->dev);
u8 intr_mask;
u8 regval; u8 regval;
intr_mask = readb(host_set->mmio_base + NV_INT_ENABLE_CK804); /* disable SATA space for CK804 */
intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804);
pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval); pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN; regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
}
static int nv_check_hotplug_ck804(struct ata_host_set *host_set) ata_pci_host_stop(host_set);
{
u8 intr_status;
intr_status = readb(host_set->mmio_base + NV_INT_STATUS_CK804);
// Clear interrupt status.
writeb(0xff, host_set->mmio_base + NV_INT_STATUS_CK804);
if (intr_status & NV_INT_STATUS_HOTPLUG) {
if (intr_status & NV_INT_STATUS_PDEV_ADDED)
printk(KERN_WARNING "nv_sata: "
"Primary device added\n");
if (intr_status & NV_INT_STATUS_PDEV_REMOVED)
printk(KERN_WARNING "nv_sata: "
"Primary device removed\n");
if (intr_status & NV_INT_STATUS_SDEV_ADDED)
printk(KERN_WARNING "nv_sata: "
"Secondary device added\n");
if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
printk(KERN_WARNING "nv_sata: "
"Secondary device removed\n");
return 1;
}
return 0;
} }
static int __init nv_init(void) static int __init nv_init(void)
......
...@@ -76,7 +76,8 @@ enum { ...@@ -76,7 +76,8 @@ enum {
PDC_RESET = (1 << 11), /* HDMA reset */ PDC_RESET = (1 << 11), /* HDMA reset */
PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI, ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
ATA_FLAG_PIO_POLLING,
}; };
...@@ -120,6 +121,7 @@ static struct scsi_host_template pdc_ata_sht = { ...@@ -120,6 +121,7 @@ static struct scsi_host_template pdc_ata_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -136,6 +138,7 @@ static const struct ata_port_operations pdc_sata_ops = { ...@@ -136,6 +138,7 @@ static const struct ata_port_operations pdc_sata_ops = {
.qc_prep = pdc_qc_prep, .qc_prep = pdc_qc_prep,
.qc_issue = pdc_qc_issue_prot, .qc_issue = pdc_qc_issue_prot,
.eng_timeout = pdc_eng_timeout, .eng_timeout = pdc_eng_timeout,
.data_xfer = ata_mmio_data_xfer,
.irq_handler = pdc_interrupt, .irq_handler = pdc_interrupt,
.irq_clear = pdc_irq_clear, .irq_clear = pdc_irq_clear,
...@@ -158,6 +161,7 @@ static const struct ata_port_operations pdc_pata_ops = { ...@@ -158,6 +161,7 @@ static const struct ata_port_operations pdc_pata_ops = {
.qc_prep = pdc_qc_prep, .qc_prep = pdc_qc_prep,
.qc_issue = pdc_qc_issue_prot, .qc_issue = pdc_qc_issue_prot,
.data_xfer = ata_mmio_data_xfer,
.eng_timeout = pdc_eng_timeout, .eng_timeout = pdc_eng_timeout,
.irq_handler = pdc_interrupt, .irq_handler = pdc_interrupt,
.irq_clear = pdc_irq_clear, .irq_clear = pdc_irq_clear,
...@@ -363,12 +367,23 @@ static void pdc_sata_phy_reset(struct ata_port *ap) ...@@ -363,12 +367,23 @@ static void pdc_sata_phy_reset(struct ata_port *ap)
sata_phy_reset(ap); sata_phy_reset(ap);
} }
static void pdc_pata_phy_reset(struct ata_port *ap) static void pdc_pata_cbl_detect(struct ata_port *ap)
{ {
/* FIXME: add cable detect. Don't assume 40-pin cable */ u8 tmp;
void __iomem *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
tmp = readb(mmio);
if (tmp & 0x01) {
ap->cbl = ATA_CBL_PATA40; ap->cbl = ATA_CBL_PATA40;
ap->udma_mask &= ATA_UDMA_MASK_40C; ap->udma_mask &= ATA_UDMA_MASK_40C;
} else
ap->cbl = ATA_CBL_PATA80;
}
static void pdc_pata_phy_reset(struct ata_port *ap)
{
pdc_pata_cbl_detect(ap);
pdc_reset_port(ap); pdc_reset_port(ap);
ata_port_probe(ap); ata_port_probe(ap);
ata_bus_reset(ap); ata_bus_reset(ap);
...@@ -435,7 +450,7 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -435,7 +450,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_NODATA: case ATA_PROT_NODATA:
printk(KERN_ERR "ata%u: command timeout\n", ap->id); ata_port_printk(ap, KERN_ERR, "command timeout\n");
drv_stat = ata_wait_idle(ap); drv_stat = ata_wait_idle(ap);
qc->err_mask |= __ac_err_mask(drv_stat); qc->err_mask |= __ac_err_mask(drv_stat);
break; break;
...@@ -443,8 +458,9 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -443,8 +458,9 @@ static void pdc_eng_timeout(struct ata_port *ap)
default: default:
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", ata_port_printk(ap, KERN_ERR,
ap->id, qc->tf.command, drv_stat); "unknown timeout, cmd 0x%x stat 0x%x\n",
qc->tf.command, drv_stat);
qc->err_mask |= ac_err_mask(drv_stat); qc->err_mask |= ac_err_mask(drv_stat);
break; break;
...@@ -533,11 +549,11 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ...@@ -533,11 +549,11 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
ap = host_set->ports[i]; ap = host_set->ports[i];
tmp = mask & (1 << (i + 1)); tmp = mask & (1 << (i + 1));
if (tmp && ap && if (tmp && ap &&
!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += pdc_host_intr(ap, qc); handled += pdc_host_intr(ap, qc);
} }
} }
...@@ -676,10 +692,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -676,10 +692,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/*
* If this driver happens to only be useful on Apple's K2, then
* we should check that here as it has a normal Serverworks ID
*/
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc) if (rc)
return rc; return rc;
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "sata_qstor" #define DRV_NAME "sata_qstor"
#define DRV_VERSION "0.05" #define DRV_VERSION "0.06"
enum { enum {
QS_PORTS = 4, QS_PORTS = 4,
...@@ -142,6 +142,7 @@ static struct scsi_host_template qs_ata_sht = { ...@@ -142,6 +142,7 @@ static struct scsi_host_template qs_ata_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = QS_DMA_BOUNDARY, .dma_boundary = QS_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -156,6 +157,7 @@ static const struct ata_port_operations qs_ata_ops = { ...@@ -156,6 +157,7 @@ static const struct ata_port_operations qs_ata_ops = {
.phy_reset = qs_phy_reset, .phy_reset = qs_phy_reset,
.qc_prep = qs_qc_prep, .qc_prep = qs_qc_prep,
.qc_issue = qs_qc_issue, .qc_issue = qs_qc_issue,
.data_xfer = ata_mmio_data_xfer,
.eng_timeout = qs_eng_timeout, .eng_timeout = qs_eng_timeout,
.irq_handler = qs_intr, .irq_handler = qs_intr,
.irq_clear = qs_irq_clear, .irq_clear = qs_irq_clear,
...@@ -175,7 +177,7 @@ static const struct ata_port_info qs_port_info[] = { ...@@ -175,7 +177,7 @@ static const struct ata_port_info qs_port_info[] = {
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_SATA_RESET |
//FIXME ATA_FLAG_SRST | //FIXME ATA_FLAG_SRST |
ATA_FLAG_MMIO, ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */ .pio_mask = 0x10, /* pio4 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &qs_ata_ops, .port_ops = &qs_ata_ops,
...@@ -394,14 +396,13 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) ...@@ -394,14 +396,13 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n", DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
sff1, sff0, port_no, sHST, sDST); sff1, sff0, port_no, sHST, sDST);
handled = 1; handled = 1;
if (ap && !(ap->flags & if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
(ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
struct qs_port_priv *pp = ap->private_data; struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_pkt) if (!pp || pp->state != qs_state_pkt)
continue; continue;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
switch (sHST) { switch (sHST) {
case 0: /* successful CPB */ case 0: /* successful CPB */
case 3: /* device error */ case 3: /* device error */
...@@ -428,13 +429,13 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) ...@@ -428,13 +429,13 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
struct ata_port *ap; struct ata_port *ap;
ap = host_set->ports[port_no]; ap = host_set->ports[port_no];
if (ap && if (ap &&
!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
struct qs_port_priv *pp = ap->private_data; struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_mmio) if (!pp || pp->state != qs_state_mmio)
continue; continue;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
/* check main status, clearing INTRQ */ /* check main status, clearing INTRQ */
u8 status = ata_check_status(ap); u8 status = ata_check_status(ap);
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "sata_sil" #define DRV_NAME "sata_sil"
#define DRV_VERSION "0.9" #define DRV_VERSION "1.0"
enum { enum {
/* /*
...@@ -54,8 +54,9 @@ enum { ...@@ -54,8 +54,9 @@ enum {
*/ */
SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
SIL_FLAG_MOD15WRITE = (1 << 30), SIL_FLAG_MOD15WRITE = (1 << 30),
SIL_DFL_HOST_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | SIL_DFL_HOST_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO, ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME,
/* /*
* Controller IDs * Controller IDs
...@@ -84,6 +85,20 @@ enum { ...@@ -84,6 +85,20 @@ enum {
/* BMDMA/BMDMA2 */ /* BMDMA/BMDMA2 */
SIL_INTR_STEERING = (1 << 1), SIL_INTR_STEERING = (1 << 1),
SIL_DMA_ENABLE = (1 << 0), /* DMA run switch */
SIL_DMA_RDWR = (1 << 3), /* DMA Rd-Wr */
SIL_DMA_SATA_IRQ = (1 << 4), /* OR of all SATA IRQs */
SIL_DMA_ACTIVE = (1 << 16), /* DMA running */
SIL_DMA_ERROR = (1 << 17), /* PCI bus error */
SIL_DMA_COMPLETE = (1 << 18), /* cmd complete / IRQ pending */
SIL_DMA_N_SATA_IRQ = (1 << 6), /* SATA_IRQ for the next channel */
SIL_DMA_N_ACTIVE = (1 << 24), /* ACTIVE for the next channel */
SIL_DMA_N_ERROR = (1 << 25), /* ERROR for the next channel */
SIL_DMA_N_COMPLETE = (1 << 26), /* COMPLETE for the next channel */
/* SIEN */
SIL_SIEN_N = (1 << 16), /* triggered by SError.N */
/* /*
* Others * Others
*/ */
...@@ -96,6 +111,10 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); ...@@ -96,6 +111,10 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static void sil_post_set_mode (struct ata_port *ap); static void sil_post_set_mode (struct ata_port *ap);
static irqreturn_t sil_interrupt(int irq, void *dev_instance,
struct pt_regs *regs);
static void sil_freeze(struct ata_port *ap);
static void sil_thaw(struct ata_port *ap);
static const struct pci_device_id sil_pci_tbl[] = { static const struct pci_device_id sil_pci_tbl[] = {
...@@ -155,6 +174,7 @@ static struct scsi_host_template sil_sht = { ...@@ -155,6 +174,7 @@ static struct scsi_host_template sil_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -166,7 +186,6 @@ static const struct ata_port_operations sil_ops = { ...@@ -166,7 +186,6 @@ static const struct ata_port_operations sil_ops = {
.check_status = ata_check_status, .check_status = ata_check_status,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.probe_reset = ata_std_probe_reset,
.post_set_mode = sil_post_set_mode, .post_set_mode = sil_post_set_mode,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
...@@ -174,8 +193,12 @@ static const struct ata_port_operations sil_ops = { ...@@ -174,8 +193,12 @@ static const struct ata_port_operations sil_ops = {
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .data_xfer = ata_mmio_data_xfer,
.irq_handler = ata_interrupt, .freeze = sil_freeze,
.thaw = sil_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = sil_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.scr_read = sil_scr_read, .scr_read = sil_scr_read,
.scr_write = sil_scr_write, .scr_write = sil_scr_write,
...@@ -220,6 +243,7 @@ static const struct { ...@@ -220,6 +243,7 @@ static const struct {
unsigned long tf; /* ATA taskfile register block */ unsigned long tf; /* ATA taskfile register block */
unsigned long ctl; /* ATA control/altstatus register block */ unsigned long ctl; /* ATA control/altstatus register block */
unsigned long bmdma; /* DMA register block */ unsigned long bmdma; /* DMA register block */
unsigned long bmdma2; /* DMA register block #2 */
unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */ unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */
unsigned long scr; /* SATA control register block */ unsigned long scr; /* SATA control register block */
unsigned long sien; /* SATA Interrupt Enable register */ unsigned long sien; /* SATA Interrupt Enable register */
...@@ -227,10 +251,10 @@ static const struct { ...@@ -227,10 +251,10 @@ static const struct {
unsigned long sfis_cfg; /* SATA FIS reception config register */ unsigned long sfis_cfg; /* SATA FIS reception config register */
} sil_port[] = { } sil_port[] = {
/* port 0 ... */ /* port 0 ... */
{ 0x80, 0x8A, 0x00, 0x40, 0x100, 0x148, 0xb4, 0x14c }, { 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
{ 0xC0, 0xCA, 0x08, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, { 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
{ 0x280, 0x28A, 0x200, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
{ 0x2C0, 0x2CA, 0x208, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
/* ... port 3 */ /* ... port 3 */
}; };
...@@ -263,7 +287,7 @@ static void sil_post_set_mode (struct ata_port *ap) ...@@ -263,7 +287,7 @@ static void sil_post_set_mode (struct ata_port *ap)
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
dev = &ap->device[i]; dev = &ap->device[i];
if (!ata_dev_present(dev)) if (!ata_dev_enabled(dev))
dev_mode[i] = 0; /* PIO0/1/2 */ dev_mode[i] = 0; /* PIO0/1/2 */
else if (dev->flags & ATA_DFLAG_PIO) else if (dev->flags & ATA_DFLAG_PIO)
dev_mode[i] = 1; /* PIO3/4 */ dev_mode[i] = 1; /* PIO3/4 */
...@@ -314,6 +338,151 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) ...@@ -314,6 +338,151 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
writel(val, mmio); writel(val, mmio);
} }
static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
{
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
u8 status;
if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) {
u32 serror;
/* SIEN doesn't mask SATA IRQs on some 3112s. Those
* controllers continue to assert IRQ as long as
* SError bits are pending. Clear SError immediately.
*/
serror = sil_scr_read(ap, SCR_ERROR);
sil_scr_write(ap, SCR_ERROR, serror);
/* Trigger hotplug and accumulate SError only if the
* port isn't already frozen. Otherwise, PHY events
* during hardreset makes controllers with broken SIEN
* repeat probing needlessly.
*/
if (!(ap->flags & ATA_FLAG_FROZEN)) {
ata_ehi_hotplugged(&ap->eh_info);
ap->eh_info.serror |= serror;
}
goto freeze;
}
if (unlikely(!qc || qc->tf.ctl & ATA_NIEN))
goto freeze;
/* Check whether we are expecting interrupt in this state */
switch (ap->hsm_task_state) {
case HSM_ST_FIRST:
/* Some pre-ATAPI-4 devices assert INTRQ
* at this state when ready to receive CDB.
*/
/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
* The flag was turned on only for atapi devices.
* No need to check is_atapi_taskfile(&qc->tf) again.
*/
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
goto err_hsm;
break;
case HSM_ST_LAST:
if (qc->tf.protocol == ATA_PROT_DMA ||
qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
/* clear DMA-Start bit */
ap->ops->bmdma_stop(qc);
if (bmdma2 & SIL_DMA_ERROR) {
qc->err_mask |= AC_ERR_HOST_BUS;
ap->hsm_task_state = HSM_ST_ERR;
}
}
break;
case HSM_ST:
break;
default:
goto err_hsm;
}
/* check main status, clearing INTRQ */
status = ata_chk_status(ap);
if (unlikely(status & ATA_BUSY))
goto err_hsm;
/* ack bmdma irq events */
ata_bmdma_irq_clear(ap);
/* kick HSM in the ass */
ata_hsm_move(ap, qc, status, 0);
return;
err_hsm:
qc->err_mask |= AC_ERR_HSM;
freeze:
ata_port_freeze(ap);
}
static irqreturn_t sil_interrupt(int irq, void *dev_instance,
struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
void __iomem *mmio_base = host_set->mmio_base;
int handled = 0;
int i;
spin_lock(&host_set->lock);
for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap = host_set->ports[i];
u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
continue;
if (bmdma2 == 0xffffffff ||
!(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ)))
continue;
sil_host_intr(ap, bmdma2);
handled = 1;
}
spin_unlock(&host_set->lock);
return IRQ_RETVAL(handled);
}
static void sil_freeze(struct ata_port *ap)
{
void __iomem *mmio_base = ap->host_set->mmio_base;
u32 tmp;
/* global IRQ mask doesn't block SATA IRQ, turn off explicitly */
writel(0, mmio_base + sil_port[ap->port_no].sien);
/* plug IRQ */
tmp = readl(mmio_base + SIL_SYSCFG);
tmp |= SIL_MASK_IDE0_INT << ap->port_no;
writel(tmp, mmio_base + SIL_SYSCFG);
readl(mmio_base + SIL_SYSCFG); /* flush */
}
static void sil_thaw(struct ata_port *ap)
{
void __iomem *mmio_base = ap->host_set->mmio_base;
u32 tmp;
/* clear IRQ */
ata_chk_status(ap);
ata_bmdma_irq_clear(ap);
/* turn on SATA IRQ */
writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien);
/* turn on IRQ */
tmp = readl(mmio_base + SIL_SYSCFG);
tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no);
writel(tmp, mmio_base + SIL_SYSCFG);
}
/** /**
* sil_dev_config - Apply device/host-specific errata fixups * sil_dev_config - Apply device/host-specific errata fixups
* @ap: Port containing device to be examined * @ap: Port containing device to be examined
...@@ -360,16 +529,16 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) ...@@ -360,16 +529,16 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
if (slow_down || if (slow_down ||
((ap->flags & SIL_FLAG_MOD15WRITE) && ((ap->flags & SIL_FLAG_MOD15WRITE) &&
(quirks & SIL_QUIRK_MOD15WRITE))) { (quirks & SIL_QUIRK_MOD15WRITE))) {
printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix "
ap->id, dev->devno); "(mod15write workaround)\n");
dev->max_sectors = 15; dev->max_sectors = 15;
return; return;
} }
/* limit to udma5 */ /* limit to udma5 */
if (quirks & SIL_QUIRK_UDMA5MAX) { if (quirks & SIL_QUIRK_UDMA5MAX) {
printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", ata_dev_printk(dev, KERN_INFO,
ap->id, dev->devno, model_num); "applying Maxtor errata fix %s\n", model_num);
dev->udma_mask &= ATA_UDMA5; dev->udma_mask &= ATA_UDMA5;
return; return;
} }
...@@ -384,16 +553,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -384,16 +553,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
int rc; int rc;
unsigned int i; unsigned int i;
int pci_dev_busy = 0; int pci_dev_busy = 0;
u32 tmp, irq_mask; u32 tmp;
u8 cls; u8 cls;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/*
* If this driver happens to only be useful on Apple's K2, then
* we should check that here as it has a normal Serverworks ID
*/
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc) if (rc)
return rc; return rc;
...@@ -478,31 +643,13 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -478,31 +643,13 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
} }
if (ent->driver_data == sil_3114) { if (ent->driver_data == sil_3114) {
irq_mask = SIL_MASK_4PORT;
/* flip the magic "make 4 ports work" bit */ /* flip the magic "make 4 ports work" bit */
tmp = readl(mmio_base + sil_port[2].bmdma); tmp = readl(mmio_base + sil_port[2].bmdma);
if ((tmp & SIL_INTR_STEERING) == 0) if ((tmp & SIL_INTR_STEERING) == 0)
writel(tmp | SIL_INTR_STEERING, writel(tmp | SIL_INTR_STEERING,
mmio_base + sil_port[2].bmdma); mmio_base + sil_port[2].bmdma);
} else {
irq_mask = SIL_MASK_2PORT;
} }
/* make sure IDE0/1/2/3 interrupts are not masked */
tmp = readl(mmio_base + SIL_SYSCFG);
if (tmp & irq_mask) {
tmp &= ~irq_mask;
writel(tmp, mmio_base + SIL_SYSCFG);
readl(mmio_base + SIL_SYSCFG); /* flush */
}
/* mask all SATA phy-related interrupts */
/* TODO: unmask bit 6 (SError N bit) for hotplug */
for (i = 0; i < probe_ent->n_ports; i++)
writel(0, mmio_base + sil_port[i].sien);
pci_set_master(pdev); pci_set_master(pdev);
/* FIXME: check ata_device_add return value */ /* FIXME: check ata_device_add return value */
......
...@@ -31,15 +31,15 @@ ...@@ -31,15 +31,15 @@
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "sata_sil24" #define DRV_NAME "sata_sil24"
#define DRV_VERSION "0.23" #define DRV_VERSION "0.24"
/* /*
* Port request block (PRB) 32 bytes * Port request block (PRB) 32 bytes
*/ */
struct sil24_prb { struct sil24_prb {
u16 ctrl; __le16 ctrl;
u16 prot; __le16 prot;
u32 rx_cnt; __le32 rx_cnt;
u8 fis[6 * 4]; u8 fis[6 * 4];
}; };
...@@ -47,17 +47,17 @@ struct sil24_prb { ...@@ -47,17 +47,17 @@ struct sil24_prb {
* Scatter gather entry (SGE) 16 bytes * Scatter gather entry (SGE) 16 bytes
*/ */
struct sil24_sge { struct sil24_sge {
u64 addr; __le64 addr;
u32 cnt; __le32 cnt;
u32 flags; __le32 flags;
}; };
/* /*
* Port multiplier * Port multiplier
*/ */
struct sil24_port_multiplier { struct sil24_port_multiplier {
u32 diag; __le32 diag;
u32 sactive; __le32 sactive;
}; };
enum { enum {
...@@ -86,12 +86,21 @@ enum { ...@@ -86,12 +86,21 @@ enum {
/* HOST_SLOT_STAT bits */ /* HOST_SLOT_STAT bits */
HOST_SSTAT_ATTN = (1 << 31), HOST_SSTAT_ATTN = (1 << 31),
/* HOST_CTRL bits */
HOST_CTRL_M66EN = (1 << 16), /* M66EN PCI bus signal */
HOST_CTRL_TRDY = (1 << 17), /* latched PCI TRDY */
HOST_CTRL_STOP = (1 << 18), /* latched PCI STOP */
HOST_CTRL_DEVSEL = (1 << 19), /* latched PCI DEVSEL */
HOST_CTRL_REQ64 = (1 << 20), /* latched PCI REQ64 */
/* /*
* Port registers * Port registers
* (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2) * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
*/ */
PORT_REGS_SIZE = 0x2000, PORT_REGS_SIZE = 0x2000,
PORT_PRB = 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */
PORT_LRAM = 0x0000, /* 31 LRAM slots and PM regs */
PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */
PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */ PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
/* 32 bit regs */ /* 32 bit regs */
...@@ -142,8 +151,16 @@ enum { ...@@ -142,8 +151,16 @@ enum {
PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */ PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */
PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */ PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */
PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */ PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */
PORT_IRQ_UNK_FIS = (1 << 6), /* Unknown FIS received */ PORT_IRQ_UNK_FIS = (1 << 6), /* unknown FIS received */
PORT_IRQ_SDB_FIS = (1 << 11), /* SDB FIS received */ PORT_IRQ_DEV_XCHG = (1 << 7), /* device exchanged */
PORT_IRQ_8B10B = (1 << 8), /* 8b/10b decode error threshold */
PORT_IRQ_CRC = (1 << 9), /* CRC error threshold */
PORT_IRQ_HANDSHAKE = (1 << 10), /* handshake error threshold */
PORT_IRQ_SDB_NOTIFY = (1 << 11), /* SDB notify received */
DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR |
PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG |
PORT_IRQ_UNK_FIS,
/* bits[27:16] are unmasked (raw) */ /* bits[27:16] are unmasked (raw) */
PORT_IRQ_RAW_SHIFT = 16, PORT_IRQ_RAW_SHIFT = 16,
...@@ -174,7 +191,7 @@ enum { ...@@ -174,7 +191,7 @@ enum {
PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */ PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */ PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */
PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */ PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */
PORT_CERR_XFR_MSGABRT = 34, /* PSD ecode 10 - master abort */ PORT_CERR_XFR_MSTABRT = 34, /* PSD ecode 10 - master abort */
PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */ PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */
PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */ PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */
...@@ -202,11 +219,19 @@ enum { ...@@ -202,11 +219,19 @@ enum {
SGE_DRD = (1 << 29), /* discard data read (/dev/null) SGE_DRD = (1 << 29), /* discard data read (/dev/null)
data address ignored */ data address ignored */
SIL24_MAX_CMDS = 31,
/* board id */ /* board id */
BID_SIL3124 = 0, BID_SIL3124 = 0,
BID_SIL3132 = 1, BID_SIL3132 = 1,
BID_SIL3131 = 2, BID_SIL3131 = 2,
/* host flags */
SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY,
SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
IRQ_STAT_4PORTS = 0xf, IRQ_STAT_4PORTS = 0xf,
}; };
...@@ -226,6 +251,58 @@ union sil24_cmd_block { ...@@ -226,6 +251,58 @@ union sil24_cmd_block {
struct sil24_atapi_block atapi; struct sil24_atapi_block atapi;
}; };
static struct sil24_cerr_info {
unsigned int err_mask, action;
const char *desc;
} sil24_cerr_db[] = {
[0] = { AC_ERR_DEV, ATA_EH_REVALIDATE,
"device error" },
[PORT_CERR_DEV] = { AC_ERR_DEV, ATA_EH_REVALIDATE,
"device error via D2H FIS" },
[PORT_CERR_SDB] = { AC_ERR_DEV, ATA_EH_REVALIDATE,
"device error via SDB FIS" },
[PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
"error in data FIS" },
[PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
"failed to transmit command FIS" },
[PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
"protocol mismatch" },
[PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
"data directon mismatch" },
[PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
"ran out of SGEs while writing" },
[PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
"ran out of SGEs while reading" },
[PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
"invalid data directon for ATAPI CDB" },
[PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
"SGT no on qword boundary" },
[PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI target abort while fetching SGT" },
[PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI master abort while fetching SGT" },
[PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI parity error while fetching SGT" },
[PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
"PRB not on qword boundary" },
[PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI target abort while fetching PRB" },
[PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI master abort while fetching PRB" },
[PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI parity error while fetching PRB" },
[PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"undefined error while transferring data" },
[PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI target abort while transferring data" },
[PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI master abort while transferring data" },
[PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
"PCI parity error while transferring data" },
[PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
"FIS received while sending service FIS" },
};
/* /*
* ap->private_data * ap->private_data
* *
...@@ -249,12 +326,14 @@ static u8 sil24_check_status(struct ata_port *ap); ...@@ -249,12 +326,14 @@ static u8 sil24_check_status(struct ata_port *ap);
static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes);
static void sil24_qc_prep(struct ata_queued_cmd *qc); static void sil24_qc_prep(struct ata_queued_cmd *qc);
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
static void sil24_irq_clear(struct ata_port *ap); static void sil24_irq_clear(struct ata_port *ap);
static void sil24_eng_timeout(struct ata_port *ap);
static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
static void sil24_freeze(struct ata_port *ap);
static void sil24_thaw(struct ata_port *ap);
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_port_start(struct ata_port *ap);
static void sil24_port_stop(struct ata_port *ap); static void sil24_port_stop(struct ata_port *ap);
static void sil24_host_stop(struct ata_host_set *host_set); static void sil24_host_stop(struct ata_host_set *host_set);
...@@ -281,7 +360,8 @@ static struct scsi_host_template sil24_sht = { ...@@ -281,7 +360,8 @@ static struct scsi_host_template sil24_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE, .change_queue_depth = ata_scsi_change_queue_depth,
.can_queue = SIL24_MAX_CMDS,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
...@@ -290,6 +370,7 @@ static struct scsi_host_template sil24_sht = { ...@@ -290,6 +370,7 @@ static struct scsi_host_template sil24_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -304,19 +385,20 @@ static const struct ata_port_operations sil24_ops = { ...@@ -304,19 +385,20 @@ static const struct ata_port_operations sil24_ops = {
.tf_read = sil24_tf_read, .tf_read = sil24_tf_read,
.probe_reset = sil24_probe_reset,
.qc_prep = sil24_qc_prep, .qc_prep = sil24_qc_prep,
.qc_issue = sil24_qc_issue, .qc_issue = sil24_qc_issue,
.eng_timeout = sil24_eng_timeout,
.irq_handler = sil24_interrupt, .irq_handler = sil24_interrupt,
.irq_clear = sil24_irq_clear, .irq_clear = sil24_irq_clear,
.scr_read = sil24_scr_read, .scr_read = sil24_scr_read,
.scr_write = sil24_scr_write, .scr_write = sil24_scr_write,
.freeze = sil24_freeze,
.thaw = sil24_thaw,
.error_handler = sil24_error_handler,
.post_internal_cmd = sil24_post_internal_cmd,
.port_start = sil24_port_start, .port_start = sil24_port_start,
.port_stop = sil24_port_stop, .port_stop = sil24_port_stop,
.host_stop = sil24_host_stop, .host_stop = sil24_host_stop,
...@@ -333,9 +415,8 @@ static struct ata_port_info sil24_port_info[] = { ...@@ -333,9 +415,8 @@ static struct ata_port_info sil24_port_info[] = {
/* sil_3124 */ /* sil_3124 */
{ {
.sht = &sil24_sht, .sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | SIL24_FLAG_PCIX_IRQ_WOC,
SIL24_NPORTS2FLAG(4),
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -344,9 +425,7 @@ static struct ata_port_info sil24_port_info[] = { ...@@ -344,9 +425,7 @@ static struct ata_port_info sil24_port_info[] = {
/* sil_3132 */ /* sil_3132 */
{ {
.sht = &sil24_sht, .sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
SIL24_NPORTS2FLAG(2),
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -355,9 +434,7 @@ static struct ata_port_info sil24_port_info[] = { ...@@ -355,9 +434,7 @@ static struct ata_port_info sil24_port_info[] = {
/* sil_3131/sil_3531 */ /* sil_3131/sil_3531 */
{ {
.sht = &sil24_sht, .sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
SIL24_NPORTS2FLAG(1),
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -365,6 +442,13 @@ static struct ata_port_info sil24_port_info[] = { ...@@ -365,6 +442,13 @@ static struct ata_port_info sil24_port_info[] = {
}, },
}; };
static int sil24_tag(int tag)
{
if (unlikely(ata_tag_internal(tag)))
return 0;
return tag;
}
static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
{ {
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
...@@ -426,56 +510,65 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) ...@@ -426,56 +510,65 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
*tf = pp->tf; *tf = pp->tf;
} }
static int sil24_softreset(struct ata_port *ap, int verbose, static int sil24_init_port(struct ata_port *ap)
unsigned int *class) {
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
u32 tmp;
writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
ata_wait_register(port + PORT_CTRL_STAT,
PORT_CS_INIT, PORT_CS_INIT, 10, 100);
tmp = ata_wait_register(port + PORT_CTRL_STAT,
PORT_CS_RDY, 0, 10, 100);
if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY)
return -EIO;
return 0;
}
static int sil24_softreset(struct ata_port *ap, unsigned int *class)
{ {
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data; struct sil24_port_priv *pp = ap->private_data;
struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
dma_addr_t paddr = pp->cmd_block_dma; dma_addr_t paddr = pp->cmd_block_dma;
unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ; u32 mask, irq_stat;
u32 irq_enable, irq_stat; const char *reason;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
if (!sata_dev_present(ap)) { if (ata_port_offline(ap)) {
DPRINTK("PHY reports no device\n"); DPRINTK("PHY reports no device\n");
*class = ATA_DEV_NONE; *class = ATA_DEV_NONE;
goto out; goto out;
} }
/* temporarily turn off IRQs during SRST */ /* put the port into known state */
irq_enable = readl(port + PORT_IRQ_ENABLE_SET); if (sil24_init_port(ap)) {
writel(irq_enable, port + PORT_IRQ_ENABLE_CLR); reason ="port not ready";
goto err;
/* }
* XXX: Not sure whether the following sleep is needed or not.
* The original driver had it. So....
*/
msleep(10);
/* do SRST */
prb->ctrl = cpu_to_le16(PRB_CTRL_SRST); prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
prb->fis[1] = 0; /* no PM yet */ prb->fis[1] = 0; /* no PM yet */
writel((u32)paddr, port + PORT_CMD_ACTIVATE); writel((u32)paddr, port + PORT_CMD_ACTIVATE);
writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
do { mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
irq_stat = readl(port + PORT_IRQ_STAT); irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0,
writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ 100, ATA_TMOUT_BOOT / HZ * 1000);
writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */
irq_stat >>= PORT_IRQ_RAW_SHIFT; irq_stat >>= PORT_IRQ_RAW_SHIFT;
if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR))
break;
msleep(100);
} while (time_before(jiffies, timeout));
/* restore IRQs */
writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
if (!(irq_stat & PORT_IRQ_COMPLETE)) { if (!(irq_stat & PORT_IRQ_COMPLETE)) {
DPRINTK("EXIT, srst failed\n"); if (irq_stat & PORT_IRQ_ERROR)
return -EIO; reason = "SRST command error";
else
reason = "timeout";
goto err;
} }
sil24_update_tf(ap); sil24_update_tf(ap);
...@@ -487,22 +580,57 @@ static int sil24_softreset(struct ata_port *ap, int verbose, ...@@ -487,22 +580,57 @@ static int sil24_softreset(struct ata_port *ap, int verbose,
out: out:
DPRINTK("EXIT, class=%u\n", *class); DPRINTK("EXIT, class=%u\n", *class);
return 0; return 0;
err:
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
return -EIO;
} }
static int sil24_hardreset(struct ata_port *ap, int verbose, static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
unsigned int *class)
{ {
unsigned int dummy_class; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
const char *reason;
int tout_msec, rc;
u32 tmp;
/* sil24 doesn't report device signature after hard reset */ /* sil24 does the right thing(tm) without any protection */
return sata_std_hardreset(ap, verbose, &dummy_class); sata_set_spd(ap);
}
static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) tout_msec = 100;
{ if (ata_port_online(ap))
return ata_drive_probe_reset(ap, ata_std_probeinit, tout_msec = 5000;
sil24_softreset, sil24_hardreset,
ata_std_postreset, classes); writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
tmp = ata_wait_register(port + PORT_CTRL_STAT,
PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec);
/* SStatus oscillates between zero and valid status after
* DEV_RST, debounce it.
*/
rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst);
if (rc) {
reason = "PHY debouncing failed";
goto err;
}
if (tmp & PORT_CS_DEV_RST) {
if (ata_port_offline(ap))
return 0;
reason = "link not ready";
goto err;
}
/* Sil24 doesn't store signature FIS after hardreset, so we
* can't wait for BSY to clear. Some devices take a long time
* to get ready and those devices will choke if we don't wait
* for BSY clearance here. Tell libata to perform follow-up
* softreset.
*/
return -EAGAIN;
err:
ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason);
return -EIO;
} }
static inline void sil24_fill_sg(struct ata_queued_cmd *qc, static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
...@@ -528,17 +656,20 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) ...@@ -528,17 +656,20 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct sil24_port_priv *pp = ap->private_data; struct sil24_port_priv *pp = ap->private_data;
union sil24_cmd_block *cb = pp->cmd_block + qc->tag; union sil24_cmd_block *cb;
struct sil24_prb *prb; struct sil24_prb *prb;
struct sil24_sge *sge; struct sil24_sge *sge;
u16 ctrl = 0;
cb = &pp->cmd_block[sil24_tag(qc->tag)];
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_PIO: case ATA_PROT_PIO:
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_NCQ:
case ATA_PROT_NODATA: case ATA_PROT_NODATA:
prb = &cb->ata.prb; prb = &cb->ata.prb;
sge = cb->ata.sge; sge = cb->ata.sge;
prb->ctrl = 0;
break; break;
case ATA_PROT_ATAPI: case ATA_PROT_ATAPI:
...@@ -551,12 +682,10 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) ...@@ -551,12 +682,10 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
if (qc->tf.flags & ATA_TFLAG_WRITE) if (qc->tf.flags & ATA_TFLAG_WRITE)
prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_WRITE); ctrl = PRB_CTRL_PACKET_WRITE;
else else
prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_READ); ctrl = PRB_CTRL_PACKET_READ;
} else }
prb->ctrl = 0;
break; break;
default: default:
...@@ -565,6 +694,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) ...@@ -565,6 +694,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
BUG(); BUG();
} }
prb->ctrl = cpu_to_le16(ctrl);
ata_tf_to_fis(&qc->tf, prb->fis, 0); ata_tf_to_fis(&qc->tf, prb->fis, 0);
if (qc->flags & ATA_QCFLAG_DMAMAP) if (qc->flags & ATA_QCFLAG_DMAMAP)
...@@ -574,11 +704,18 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) ...@@ -574,11 +704,18 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data; struct sil24_port_priv *pp = ap->private_data;
dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block); void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
unsigned int tag = sil24_tag(qc->tag);
dma_addr_t paddr;
void __iomem *activate;
paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
activate = port + PORT_CMD_ACTIVATE + tag * 8;
writel((u32)paddr, activate);
writel((u64)paddr >> 32, activate + 4);
writel((u32)paddr, port + PORT_CMD_ACTIVATE);
return 0; return 0;
} }
...@@ -587,162 +724,139 @@ static void sil24_irq_clear(struct ata_port *ap) ...@@ -587,162 +724,139 @@ static void sil24_irq_clear(struct ata_port *ap)
/* unused */ /* unused */
} }
static int __sil24_restart_controller(void __iomem *port) static void sil24_freeze(struct ata_port *ap)
{ {
u32 tmp; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
int cnt;
writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
/* Max ~10ms */
for (cnt = 0; cnt < 10000; cnt++) {
tmp = readl(port + PORT_CTRL_STAT);
if (tmp & PORT_CS_RDY)
return 0;
udelay(1);
}
return -1;
}
static void sil24_restart_controller(struct ata_port *ap) /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
{ * PORT_IRQ_ENABLE instead.
if (__sil24_restart_controller((void __iomem *)ap->ioaddr.cmd_addr)) */
printk(KERN_ERR DRV_NAME writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
" ata%u: failed to restart controller\n", ap->id);
} }
static int __sil24_reset_controller(void __iomem *port) static void sil24_thaw(struct ata_port *ap)
{ {
int cnt; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
u32 tmp; u32 tmp;
/* Reset controller state. Is this correct? */ /* clear IRQ */
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); tmp = readl(port + PORT_IRQ_STAT);
readl(port + PORT_CTRL_STAT); /* sync */ writel(tmp, port + PORT_IRQ_STAT);
/* Max ~100ms */
for (cnt = 0; cnt < 1000; cnt++) {
udelay(100);
tmp = readl(port + PORT_CTRL_STAT);
if (!(tmp & PORT_CS_DEV_RST))
break;
}
if (tmp & PORT_CS_DEV_RST)
return -1;
if (tmp & PORT_CS_RDY) /* turn IRQ back on */
return 0; writel(DEF_PORT_IRQ, port + PORT_IRQ_ENABLE_SET);
return __sil24_restart_controller(port);
}
static void sil24_reset_controller(struct ata_port *ap)
{
printk(KERN_NOTICE DRV_NAME
" ata%u: resetting controller...\n", ap->id);
if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr))
printk(KERN_ERR DRV_NAME
" ata%u: failed to reset controller\n", ap->id);
} }
static void sil24_eng_timeout(struct ata_port *ap) static void sil24_error_intr(struct ata_port *ap)
{ {
struct ata_queued_cmd *qc; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
struct ata_eh_info *ehi = &ap->eh_info;
qc = ata_qc_from_tag(ap, ap->active_tag); int freeze = 0;
u32 irq_stat;
printk(KERN_ERR "ata%u: command timeout\n", ap->id); /* on error, we need to clear IRQ explicitly */
qc->err_mask |= AC_ERR_TIMEOUT; irq_stat = readl(port + PORT_IRQ_STAT);
ata_eh_qc_complete(qc); writel(irq_stat, port + PORT_IRQ_STAT);
sil24_reset_controller(ap); /* first, analyze and record host port events */
} ata_ehi_clear_desc(ehi);
static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
{
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
struct sil24_port_priv *pp = ap->private_data;
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
u32 irq_stat, cmd_err, sstatus, serror;
unsigned int err_mask;
irq_stat = readl(port + PORT_IRQ_STAT); if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) {
writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ ata_ehi_hotplugged(ehi);
ata_ehi_push_desc(ehi, ", %s",
irq_stat & PORT_IRQ_PHYRDY_CHG ?
"PHY RDY changed" : "device exchanged");
freeze = 1;
}
if (!(irq_stat & PORT_IRQ_ERROR)) { if (irq_stat & PORT_IRQ_UNK_FIS) {
/* ignore non-completion, non-error irqs for now */ ehi->err_mask |= AC_ERR_HSM;
printk(KERN_WARNING DRV_NAME ehi->action |= ATA_EH_SOFTRESET;
"ata%u: non-error exception irq (irq_stat %x)\n", ata_ehi_push_desc(ehi , ", unknown FIS");
ap->id, irq_stat); freeze = 1;
return;
} }
cmd_err = readl(port + PORT_CMD_ERR); /* deal with command error */
sstatus = readl(port + PORT_SSTATUS); if (irq_stat & PORT_IRQ_ERROR) {
serror = readl(port + PORT_SERROR); struct sil24_cerr_info *ci = NULL;
if (serror) unsigned int err_mask = 0, action = 0;
writel(serror, port + PORT_SERROR); struct ata_queued_cmd *qc;
u32 cerr;
/* /* analyze CMD_ERR */
* Don't log ATAPI device errors. They're supposed to happen cerr = readl(port + PORT_CMD_ERR);
* and any serious errors will be logged using sense data by if (cerr < ARRAY_SIZE(sil24_cerr_db))
* the SCSI layer. ci = &sil24_cerr_db[cerr];
*/
if (ap->device[0].class != ATA_DEV_ATAPI || cmd_err > PORT_CERR_SDB)
printk("ata%u: error interrupt on port%d\n"
" stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) { if (ci && ci->desc) {
/* err_mask |= ci->err_mask;
* Device is reporting error, tf registers are valid. action |= ci->action;
*/ ata_ehi_push_desc(ehi, ", %s", ci->desc);
sil24_update_tf(ap);
err_mask = ac_err_mask(pp->tf.command);
sil24_restart_controller(ap);
} else { } else {
/* err_mask |= AC_ERR_OTHER;
* Other errors. libata currently doesn't have any action |= ATA_EH_SOFTRESET;
* mechanism to report these errors. Just turn on ata_ehi_push_desc(ehi, ", unknown command error %d",
* ATA_ERR. cerr);
*/
err_mask = AC_ERR_OTHER;
sil24_reset_controller(ap);
} }
/* record error info */
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc) { if (qc) {
sil24_update_tf(ap);
qc->err_mask |= err_mask; qc->err_mask |= err_mask;
ata_qc_complete(qc); } else
ehi->err_mask |= err_mask;
ehi->action |= action;
} }
/* freeze or abort */
if (freeze)
ata_port_freeze(ap);
else
ata_port_abort(ap);
}
static void sil24_finish_qc(struct ata_queued_cmd *qc)
{
if (qc->flags & ATA_QCFLAG_RESULT_TF)
sil24_update_tf(qc->ap);
} }
static inline void sil24_host_intr(struct ata_port *ap) static inline void sil24_host_intr(struct ata_port *ap)
{ {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
u32 slot_stat; u32 slot_stat, qc_active;
int rc;
slot_stat = readl(port + PORT_SLOT_STAT); slot_stat = readl(port + PORT_SLOT_STAT);
if (!(slot_stat & HOST_SSTAT_ATTN)) {
struct sil24_port_priv *pp = ap->private_data;
/*
* !HOST_SSAT_ATTN guarantees successful completion,
* so reading back tf registers is unnecessary for
* most commands. TODO: read tf registers for
* commands which require these values on successful
* completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
* DEVICE RESET and READ PORT MULTIPLIER (any more?).
*/
sil24_update_tf(ap);
if (qc) { if (unlikely(slot_stat & HOST_SSTAT_ATTN)) {
qc->err_mask |= ac_err_mask(pp->tf.command); sil24_error_intr(ap);
ata_qc_complete(qc); return;
} }
} else
sil24_error_intr(ap, slot_stat); if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
qc_active = slot_stat & ~HOST_SSTAT_ATTN;
rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
if (rc > 0)
return;
if (rc < 0) {
struct ata_eh_info *ehi = &ap->eh_info;
ehi->err_mask |= AC_ERR_HSM;
ehi->action |= ATA_EH_SOFTRESET;
ata_port_freeze(ap);
return;
}
if (ata_ratelimit())
ata_port_printk(ap, KERN_INFO, "spurious interrupt "
"(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
slot_stat, ap->active_tag, ap->sactive);
} }
static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs) static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
...@@ -769,7 +883,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs * ...@@ -769,7 +883,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *
for (i = 0; i < host_set->n_ports; i++) for (i = 0; i < host_set->n_ports; i++)
if (status & (1 << i)) { if (status & (1 << i)) {
struct ata_port *ap = host_set->ports[i]; struct ata_port *ap = host_set->ports[i];
if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) { if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
sil24_host_intr(host_set->ports[i]); sil24_host_intr(host_set->ports[i]);
handled++; handled++;
} else } else
...@@ -782,9 +896,35 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs * ...@@ -782,9 +896,35 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
static void sil24_error_handler(struct ata_port *ap)
{
struct ata_eh_context *ehc = &ap->eh_context;
if (sil24_init_port(ap)) {
ata_eh_freeze_port(ap);
ehc->i.action |= ATA_EH_HARDRESET;
}
/* perform recovery */
ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
ata_std_postreset);
}
static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
if (qc->flags & ATA_QCFLAG_FAILED)
qc->err_mask |= AC_ERR_OTHER;
/* make DMA engine forget about the failed command */
if (qc->err_mask)
sil24_init_port(ap);
}
static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev)
{ {
const size_t cb_size = sizeof(*pp->cmd_block); const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS;
dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
} }
...@@ -794,7 +934,7 @@ static int sil24_port_start(struct ata_port *ap) ...@@ -794,7 +934,7 @@ static int sil24_port_start(struct ata_port *ap)
struct device *dev = ap->host_set->dev; struct device *dev = ap->host_set->dev;
struct sil24_port_priv *pp; struct sil24_port_priv *pp;
union sil24_cmd_block *cb; union sil24_cmd_block *cb;
size_t cb_size = sizeof(*cb); size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS;
dma_addr_t cb_dma; dma_addr_t cb_dma;
int rc = -ENOMEM; int rc = -ENOMEM;
...@@ -858,6 +998,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -858,6 +998,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem *host_base = NULL; void __iomem *host_base = NULL;
void __iomem *port_base = NULL; void __iomem *port_base = NULL;
int i, rc; int i, rc;
u32 tmp;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
...@@ -910,11 +1051,17 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -910,11 +1051,17 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* /*
* Configure the device * Configure the device
*/ */
/* if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
* FIXME: This device is certainly 64-bit capable. We just rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
* don't know how to use it. After fixing 32bit activation in if (rc) {
* this function, enable 64bit masks here. rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
*/ if (rc) {
dev_printk(KERN_ERR, &pdev->dev,
"64-bit DMA enable failed\n");
goto out_free;
}
}
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) { if (rc) {
dev_printk(KERN_ERR, &pdev->dev, dev_printk(KERN_ERR, &pdev->dev,
...@@ -927,20 +1074,30 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -927,20 +1074,30 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
"32-bit consistent DMA enable failed\n"); "32-bit consistent DMA enable failed\n");
goto out_free; goto out_free;
} }
}
/* GPIO off */ /* GPIO off */
writel(0, host_base + HOST_FLASH_CMD); writel(0, host_base + HOST_FLASH_CMD);
/* Mask interrupts during initialization */ /* Apply workaround for completion IRQ loss on PCI-X errata */
if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
tmp = readl(host_base + 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");
else
probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
}
/* clear global reset & mask interrupts during initialization */
writel(0, host_base + HOST_CTRL); writel(0, host_base + HOST_CTRL);
for (i = 0; i < probe_ent->n_ports; i++) { for (i = 0; i < probe_ent->n_ports; i++) {
void __iomem *port = port_base + i * PORT_REGS_SIZE; void __iomem *port = port_base + i * PORT_REGS_SIZE;
unsigned long portu = (unsigned long)port; unsigned long portu = (unsigned long)port;
u32 tmp;
int cnt;
probe_ent->port[i].cmd_addr = portu + PORT_PRB; probe_ent->port[i].cmd_addr = portu;
probe_ent->port[i].scr_addr = portu + PORT_SCONTROL; probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
ata_std_ports(&probe_ent->port[i]); ata_std_ports(&probe_ent->port[i]);
...@@ -952,18 +1109,20 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -952,18 +1109,20 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tmp = readl(port + PORT_CTRL_STAT); tmp = readl(port + PORT_CTRL_STAT);
if (tmp & PORT_CS_PORT_RST) { if (tmp & PORT_CS_PORT_RST) {
writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR); writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
readl(port + PORT_CTRL_STAT); /* sync */ tmp = ata_wait_register(port + PORT_CTRL_STAT,
for (cnt = 0; cnt < 10; cnt++) { PORT_CS_PORT_RST,
msleep(10); PORT_CS_PORT_RST, 10, 100);
tmp = readl(port + PORT_CTRL_STAT);
if (!(tmp & PORT_CS_PORT_RST))
break;
}
if (tmp & PORT_CS_PORT_RST) if (tmp & PORT_CS_PORT_RST)
dev_printk(KERN_ERR, &pdev->dev, dev_printk(KERN_ERR, &pdev->dev,
"failed to clear port RST\n"); "failed to clear port RST\n");
} }
/* Configure IRQ WoC */
if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
else
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
/* Zero error counters. */ /* Zero error counters. */
writel(0x8000, port + PORT_DECODE_ERR_THRESH); writel(0x8000, port + PORT_DECODE_ERR_THRESH);
writel(0x8000, port + PORT_CRC_ERR_THRESH); writel(0x8000, port + PORT_CRC_ERR_THRESH);
...@@ -972,26 +1131,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -972,26 +1131,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
writel(0x0000, port + PORT_CRC_ERR_CNT); writel(0x0000, port + PORT_CRC_ERR_CNT);
writel(0x0000, port + PORT_HSHK_ERR_CNT); writel(0x0000, port + PORT_HSHK_ERR_CNT);
/* FIXME: 32bit activation? */ /* Always use 64bit activation */
writel(0, port + PORT_ACTIVATE_UPPER_ADDR); writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT);
/* Configure interrupts */
writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS,
port + PORT_IRQ_ENABLE_SET);
/* Clear interrupts */
writel(0x0fff0fff, port + PORT_IRQ_STAT);
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
/* Clear port multiplier enable and resume bits */ /* Clear port multiplier enable and resume bits */
writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR); writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
/* Reset itself */
if (__sil24_reset_controller(port))
dev_printk(KERN_ERR, &pdev->dev,
"failed to reset controller\n");
} }
/* Turn on interrupts */ /* Turn on interrupts */
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "sata_sis" #define DRV_NAME "sata_sis"
#define DRV_VERSION "0.5" #define DRV_VERSION "0.6"
enum { enum {
sis_180 = 0, sis_180 = 0,
...@@ -96,6 +96,7 @@ static struct scsi_host_template sis_sht = { ...@@ -96,6 +96,7 @@ static struct scsi_host_template sis_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -106,14 +107,17 @@ static const struct ata_port_operations sis_ops = { ...@@ -106,14 +107,17 @@ static const struct ata_port_operations sis_ops = {
.check_status = ata_check_status, .check_status = ata_check_status,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .data_xfer = ata_pio_data_xfer,
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.scr_read = sis_scr_read, .scr_read = sis_scr_read,
...@@ -125,8 +129,7 @@ static const struct ata_port_operations sis_ops = { ...@@ -125,8 +129,7 @@ static const struct ata_port_operations sis_ops = {
static struct ata_port_info sis_port_info = { static struct ata_port_info sis_port_info = {
.sht = &sis_sht, .sht = &sis_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f, .pio_mask = 0x1f,
.mwdma_mask = 0x7, .mwdma_mask = 0x7,
.udma_mask = 0x7f, .udma_mask = 0x7f,
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
#endif /* CONFIG_PPC_OF */ #endif /* CONFIG_PPC_OF */
#define DRV_NAME "sata_svw" #define DRV_NAME "sata_svw"
#define DRV_VERSION "1.07" #define DRV_VERSION "1.8"
enum { enum {
/* Taskfile registers offsets */ /* Taskfile registers offsets */
...@@ -257,7 +257,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, ...@@ -257,7 +257,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
int len, index; int len, index;
/* Find the ata_port */ /* Find the ata_port */
ap = (struct ata_port *) &shost->hostdata[0]; ap = ata_shost_to_port(shost);
if (ap == NULL) if (ap == NULL)
return 0; return 0;
...@@ -299,6 +299,7 @@ static struct scsi_host_template k2_sata_sht = { ...@@ -299,6 +299,7 @@ static struct scsi_host_template k2_sata_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
#ifdef CONFIG_PPC_OF #ifdef CONFIG_PPC_OF
.proc_info = k2_sata_proc_info, .proc_info = k2_sata_proc_info,
#endif #endif
...@@ -313,14 +314,17 @@ static const struct ata_port_operations k2_sata_ops = { ...@@ -313,14 +314,17 @@ static const struct ata_port_operations k2_sata_ops = {
.check_status = k2_stat_check_status, .check_status = k2_stat_check_status,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = k2_bmdma_setup_mmio, .bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio, .bmdma_start = k2_bmdma_start_mmio,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .data_xfer = ata_mmio_data_xfer,
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.scr_read = k2_sata_scr_read, .scr_read = k2_sata_scr_read,
...@@ -420,8 +424,8 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -420,8 +424,8 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
probe_ent->sht = &k2_sata_sht; probe_ent->sht = &k2_sata_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; ATA_FLAG_MMIO;
probe_ent->port_ops = &k2_sata_ops; probe_ent->port_ops = &k2_sata_ops;
probe_ent->n_ports = 4; probe_ent->n_ports = 4;
probe_ent->irq = pdev->irq; probe_ent->irq = pdev->irq;
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include "sata_promise.h" #include "sata_promise.h"
#define DRV_NAME "sata_sx4" #define DRV_NAME "sata_sx4"
#define DRV_VERSION "0.8" #define DRV_VERSION "0.9"
enum { enum {
...@@ -191,6 +191,7 @@ static struct scsi_host_template pdc_sata_sht = { ...@@ -191,6 +191,7 @@ static struct scsi_host_template pdc_sata_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -204,6 +205,7 @@ static const struct ata_port_operations pdc_20621_ops = { ...@@ -204,6 +205,7 @@ static const struct ata_port_operations pdc_20621_ops = {
.phy_reset = pdc_20621_phy_reset, .phy_reset = pdc_20621_phy_reset,
.qc_prep = pdc20621_qc_prep, .qc_prep = pdc20621_qc_prep,
.qc_issue = pdc20621_qc_issue_prot, .qc_issue = pdc20621_qc_issue_prot,
.data_xfer = ata_mmio_data_xfer,
.eng_timeout = pdc_eng_timeout, .eng_timeout = pdc_eng_timeout,
.irq_handler = pdc20621_interrupt, .irq_handler = pdc20621_interrupt,
.irq_clear = pdc20621_irq_clear, .irq_clear = pdc20621_irq_clear,
...@@ -218,7 +220,7 @@ static const struct ata_port_info pdc_port_info[] = { ...@@ -218,7 +220,7 @@ static const struct ata_port_info pdc_port_info[] = {
.sht = &pdc_sata_sht, .sht = &pdc_sata_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_SRST | ATA_FLAG_MMIO |
ATA_FLAG_NO_ATAPI, ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
...@@ -833,11 +835,11 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re ...@@ -833,11 +835,11 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
tmp = mask & (1 << i); tmp = mask & (1 << i);
VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
if (tmp && ap && if (tmp && ap &&
!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += pdc20621_host_intr(ap, qc, (i > 4), handled += pdc20621_host_intr(ap, qc, (i > 4),
mmio_base); mmio_base);
} }
...@@ -868,15 +870,16 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -868,15 +870,16 @@ static void pdc_eng_timeout(struct ata_port *ap)
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_NODATA: case ATA_PROT_NODATA:
printk(KERN_ERR "ata%u: command timeout\n", ap->id); ata_port_printk(ap, KERN_ERR, "command timeout\n");
qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
break; break;
default: default:
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", ata_port_printk(ap, KERN_ERR,
ap->id, qc->tf.command, drv_stat); "unknown timeout, cmd 0x%x stat 0x%x\n",
qc->tf.command, drv_stat);
qc->err_mask |= ac_err_mask(drv_stat); qc->err_mask |= ac_err_mask(drv_stat);
break; break;
...@@ -1375,10 +1378,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1375,10 +1378,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/*
* If this driver happens to only be useful on Apple's K2, then
* we should check that here as it has a normal Serverworks ID
*/
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc) if (rc)
return rc; return rc;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "sata_uli" #define DRV_NAME "sata_uli"
#define DRV_VERSION "0.5" #define DRV_VERSION "0.6"
enum { enum {
uli_5289 = 0, uli_5289 = 0,
...@@ -90,6 +90,7 @@ static struct scsi_host_template uli_sht = { ...@@ -90,6 +90,7 @@ static struct scsi_host_template uli_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -102,16 +103,18 @@ static const struct ata_port_operations uli_ops = { ...@@ -102,16 +103,18 @@ static const struct ata_port_operations uli_ops = {
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.data_xfer = ata_pio_data_xfer,
.eng_timeout = ata_eng_timeout, .freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
...@@ -126,8 +129,7 @@ static const struct ata_port_operations uli_ops = { ...@@ -126,8 +129,7 @@ static const struct ata_port_operations uli_ops = {
static struct ata_port_info uli_port_info = { static struct ata_port_info uli_port_info = {
.sht = &uli_sht, .sht = &uli_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &uli_ops, .port_ops = &uli_ops,
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "sata_via" #define DRV_NAME "sata_via"
#define DRV_VERSION "1.1" #define DRV_VERSION "1.2"
enum board_ids_enum { enum board_ids_enum {
vt6420, vt6420,
...@@ -103,6 +103,7 @@ static struct scsi_host_template svia_sht = { ...@@ -103,6 +103,7 @@ static struct scsi_host_template svia_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -115,8 +116,6 @@ static const struct ata_port_operations svia_sata_ops = { ...@@ -115,8 +116,6 @@ static const struct ata_port_operations svia_sata_ops = {
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
...@@ -124,8 +123,12 @@ static const struct ata_port_operations svia_sata_ops = { ...@@ -124,8 +123,12 @@ static const struct ata_port_operations svia_sata_ops = {
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.data_xfer = ata_pio_data_xfer,
.eng_timeout = ata_eng_timeout, .freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
...@@ -140,7 +143,7 @@ static const struct ata_port_operations svia_sata_ops = { ...@@ -140,7 +143,7 @@ static const struct ata_port_operations svia_sata_ops = {
static struct ata_port_info svia_port_info = { static struct ata_port_info svia_port_info = {
.sht = &svia_sht, .sht = &svia_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f, .pio_mask = 0x1f,
.mwdma_mask = 0x07, .mwdma_mask = 0x07,
.udma_mask = 0x7f, .udma_mask = 0x7f,
...@@ -235,8 +238,7 @@ static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev) ...@@ -235,8 +238,7 @@ static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
INIT_LIST_HEAD(&probe_ent->node); INIT_LIST_HEAD(&probe_ent->node);
probe_ent->sht = &svia_sht; probe_ent->sht = &svia_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY;
ATA_FLAG_NO_LEGACY;
probe_ent->port_ops = &svia_sata_ops; probe_ent->port_ops = &svia_sata_ops;
probe_ent->n_ports = N_PORTS; probe_ent->n_ports = N_PORTS;
probe_ent->irq = pdev->irq; probe_ent->irq = pdev->irq;
......
...@@ -221,14 +221,21 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, ...@@ -221,14 +221,21 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
ap = host_set->ports[i]; ap = host_set->ports[i];
if (ap && !(ap->flags & if (is_vsc_sata_int_err(i, int_status)) {
(ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { u32 err_status;
printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
vsc_sata_scr_write(ap, SCR_ERROR, err_status);
handled++;
}
if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += ata_host_intr(ap, qc); handled += ata_host_intr(ap, qc);
} else if (is_vsc_sata_int_err(i, int_status)) { else if (is_vsc_sata_int_err(i, int_status)) {
/* /*
* On some chips (i.e. Intel 31244), an error * On some chips (i.e. Intel 31244), an error
* interrupt will sneak in at initialization * interrupt will sneak in at initialization
...@@ -272,6 +279,7 @@ static struct scsi_host_template vsc_sata_sht = { ...@@ -272,6 +279,7 @@ static struct scsi_host_template vsc_sata_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param, .bios_param = ata_std_bios_param,
}; };
...@@ -283,14 +291,17 @@ static const struct ata_port_operations vsc_sata_ops = { ...@@ -283,14 +291,17 @@ static const struct ata_port_operations vsc_sata_ops = {
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.check_status = ata_check_status, .check_status = ata_check_status,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .data_xfer = ata_pio_data_xfer,
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = vsc_sata_interrupt, .irq_handler = vsc_sata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.scr_read = vsc_sata_scr_read, .scr_read = vsc_sata_scr_read,
...@@ -385,7 +396,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d ...@@ -385,7 +396,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
probe_ent->sht = &vsc_sata_sht; probe_ent->sht = &vsc_sata_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET; ATA_FLAG_MMIO;
probe_ent->port_ops = &vsc_sata_ops; probe_ent->port_ops = &vsc_sata_ops;
probe_ent->n_ports = 4; probe_ent->n_ports = 4;
probe_ent->irq = pdev->irq; probe_ent->irq = pdev->irq;
......
...@@ -578,6 +578,24 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) ...@@ -578,6 +578,24 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
*/ */
static DEFINE_PER_CPU(struct list_head, scsi_done_q); static DEFINE_PER_CPU(struct list_head, scsi_done_q);
/**
* scsi_req_abort_cmd -- Request command recovery for the specified command
* cmd: pointer to the SCSI command of interest
*
* This function requests that SCSI Core start recovery for the
* command by deleting the timer and adding the command to the eh
* queue. It can be called by either LLDDs or SCSI Core. LLDDs who
* implement their own error recovery MAY ignore the timeout event if
* they generated scsi_req_abort_cmd.
*/
void scsi_req_abort_cmd(struct scsi_cmnd *cmd)
{
if (!scsi_delete_timer(cmd))
return;
scsi_times_out(cmd);
}
EXPORT_SYMBOL(scsi_req_abort_cmd);
/** /**
* scsi_done - Enqueue the finished SCSI command into the done queue. * scsi_done - Enqueue the finished SCSI command into the done queue.
* @cmd: The SCSI Command for which a low-level device driver (LLDD) gives * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
......
...@@ -57,6 +57,28 @@ void scsi_eh_wakeup(struct Scsi_Host *shost) ...@@ -57,6 +57,28 @@ void scsi_eh_wakeup(struct Scsi_Host *shost)
} }
} }
/**
* scsi_schedule_eh - schedule EH for SCSI host
* @shost: SCSI host to invoke error handling on.
*
* Schedule SCSI EH without scmd.
**/
void scsi_schedule_eh(struct Scsi_Host *shost)
{
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
shost->host_eh_scheduled++;
scsi_eh_wakeup(shost);
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
EXPORT_SYMBOL_GPL(scsi_schedule_eh);
/** /**
* scsi_eh_scmd_add - add scsi cmd to error handling. * scsi_eh_scmd_add - add scsi cmd to error handling.
* @scmd: scmd to run eh on. * @scmd: scmd to run eh on.
...@@ -1515,7 +1537,7 @@ int scsi_error_handler(void *data) ...@@ -1515,7 +1537,7 @@ int scsi_error_handler(void *data)
*/ */
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
if (shost->host_failed == 0 || if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
shost->host_failed != shost->host_busy) { shost->host_failed != shost->host_busy) {
SCSI_LOG_ERROR_RECOVERY(1, SCSI_LOG_ERROR_RECOVERY(1,
printk("Error handler scsi_eh_%d sleeping\n", printk("Error handler scsi_eh_%d sleeping\n",
......
...@@ -500,7 +500,7 @@ void scsi_device_unbusy(struct scsi_device *sdev) ...@@ -500,7 +500,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
spin_lock_irqsave(shost->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy--; shost->host_busy--;
if (unlikely(scsi_host_in_recovery(shost) && if (unlikely(scsi_host_in_recovery(shost) &&
shost->host_failed)) (shost->host_failed || shost->host_eh_scheduled)))
scsi_eh_wakeup(shost); scsi_eh_wakeup(shost);
spin_unlock(shost->host_lock); spin_unlock(shost->host_lock);
spin_lock(sdev->request_queue->queue_lock); spin_lock(sdev->request_queue->queue_lock);
......
#ifndef _SCSI_TRANSPORT_API_H
#define _SCSI_TRANSPORT_API_H
void scsi_schedule_eh(struct Scsi_Host *shost);
#endif /* _SCSI_TRANSPORT_API_H */
...@@ -97,6 +97,9 @@ enum { ...@@ -97,6 +97,9 @@ enum {
ATA_DRQ = (1 << 3), /* data request i/o */ ATA_DRQ = (1 << 3), /* data request i/o */
ATA_ERR = (1 << 0), /* have an error */ ATA_ERR = (1 << 0), /* have an error */
ATA_SRST = (1 << 2), /* software reset */ ATA_SRST = (1 << 2), /* software reset */
ATA_ICRC = (1 << 7), /* interface CRC error */
ATA_UNC = (1 << 6), /* uncorrectable media error */
ATA_IDNF = (1 << 4), /* ID not found */
ATA_ABORTED = (1 << 2), /* command aborted */ ATA_ABORTED = (1 << 2), /* command aborted */
/* ATA command block registers */ /* ATA command block registers */
...@@ -130,6 +133,8 @@ enum { ...@@ -130,6 +133,8 @@ enum {
ATA_CMD_WRITE = 0xCA, ATA_CMD_WRITE = 0xCA,
ATA_CMD_WRITE_EXT = 0x35, ATA_CMD_WRITE_EXT = 0x35,
ATA_CMD_WRITE_FUA_EXT = 0x3D, ATA_CMD_WRITE_FUA_EXT = 0x3D,
ATA_CMD_FPDMA_READ = 0x60,
ATA_CMD_FPDMA_WRITE = 0x61,
ATA_CMD_PIO_READ = 0x20, ATA_CMD_PIO_READ = 0x20,
ATA_CMD_PIO_READ_EXT = 0x24, ATA_CMD_PIO_READ_EXT = 0x24,
ATA_CMD_PIO_WRITE = 0x30, ATA_CMD_PIO_WRITE = 0x30,
...@@ -148,6 +153,10 @@ enum { ...@@ -148,6 +153,10 @@ enum {
ATA_CMD_INIT_DEV_PARAMS = 0x91, ATA_CMD_INIT_DEV_PARAMS = 0x91,
ATA_CMD_READ_NATIVE_MAX = 0xF8, ATA_CMD_READ_NATIVE_MAX = 0xF8,
ATA_CMD_READ_NATIVE_MAX_EXT = 0x27, ATA_CMD_READ_NATIVE_MAX_EXT = 0x27,
ATA_CMD_READ_LOG_EXT = 0x2f,
/* READ_LOG_EXT pages */
ATA_LOG_SATA_NCQ = 0x10,
/* SETFEATURES stuff */ /* SETFEATURES stuff */
SETFEATURES_XFER = 0x03, SETFEATURES_XFER = 0x03,
...@@ -172,6 +181,9 @@ enum { ...@@ -172,6 +181,9 @@ enum {
XFER_PIO_0 = 0x08, XFER_PIO_0 = 0x08,
XFER_PIO_SLOW = 0x00, XFER_PIO_SLOW = 0x00,
SETFEATURES_WC_ON = 0x02, /* Enable write cache */
SETFEATURES_WC_OFF = 0x82, /* Disable write cache */
/* ATAPI stuff */ /* ATAPI stuff */
ATAPI_PKT_DMA = (1 << 0), ATAPI_PKT_DMA = (1 << 0),
ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: ATAPI_DMADIR = (1 << 2), /* ATAPI data dir:
...@@ -192,6 +204,16 @@ enum { ...@@ -192,6 +204,16 @@ enum {
SCR_ACTIVE = 3, SCR_ACTIVE = 3,
SCR_NOTIFICATION = 4, SCR_NOTIFICATION = 4,
/* SError bits */
SERR_DATA_RECOVERED = (1 << 0), /* recovered data error */
SERR_COMM_RECOVERED = (1 << 1), /* recovered comm failure */
SERR_DATA = (1 << 8), /* unrecovered data error */
SERR_PERSISTENT = (1 << 9), /* persistent data/comm error */
SERR_PROTOCOL = (1 << 10), /* protocol violation */
SERR_INTERNAL = (1 << 11), /* host internal error */
SERR_PHYRDY_CHG = (1 << 16), /* PHY RDY changed */
SERR_DEV_XCHG = (1 << 26), /* device exchanged */
/* struct ata_taskfile flags */ /* struct ata_taskfile flags */
ATA_TFLAG_LBA48 = (1 << 0), /* enable 48-bit LBA and "HOB" */ ATA_TFLAG_LBA48 = (1 << 0), /* enable 48-bit LBA and "HOB" */
ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */
...@@ -199,6 +221,7 @@ enum { ...@@ -199,6 +221,7 @@ enum {
ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */
ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ ATA_TFLAG_LBA = (1 << 4), /* enable LBA */
ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ ATA_TFLAG_FUA = (1 << 5), /* enable FUA */
ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */
}; };
enum ata_tf_protocols { enum ata_tf_protocols {
...@@ -207,6 +230,7 @@ enum ata_tf_protocols { ...@@ -207,6 +230,7 @@ enum ata_tf_protocols {
ATA_PROT_NODATA, /* no data */ ATA_PROT_NODATA, /* no data */
ATA_PROT_PIO, /* PIO single sector */ ATA_PROT_PIO, /* PIO single sector */
ATA_PROT_DMA, /* DMA */ ATA_PROT_DMA, /* DMA */
ATA_PROT_NCQ, /* NCQ */
ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ ATA_PROT_ATAPI, /* packet command, PIO data xfer*/
ATA_PROT_ATAPI_NODATA, /* packet command, no data */ ATA_PROT_ATAPI_NODATA, /* packet command, no data */
ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */ ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */
...@@ -262,6 +286,8 @@ struct ata_taskfile { ...@@ -262,6 +286,8 @@ struct ata_taskfile {
#define ata_id_has_pm(id) ((id)[82] & (1 << 3)) #define ata_id_has_pm(id) ((id)[82] & (1 << 3))
#define ata_id_has_lba(id) ((id)[49] & (1 << 9)) #define ata_id_has_lba(id) ((id)[49] & (1 << 9))
#define ata_id_has_dma(id) ((id)[49] & (1 << 8)) #define ata_id_has_dma(id) ((id)[49] & (1 << 8))
#define ata_id_has_ncq(id) ((id)[76] & (1 << 8))
#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1)
#define ata_id_removeable(id) ((id)[0] & (1 << 7)) #define ata_id_removeable(id) ((id)[0] & (1 << 7))
#define ata_id_has_dword_io(id) ((id)[50] & (1 << 0)) #define ata_id_has_dword_io(id) ((id)[50] & (1 << 0))
#define ata_id_u32(id,n) \ #define ata_id_u32(id,n) \
...@@ -272,6 +298,8 @@ struct ata_taskfile { ...@@ -272,6 +298,8 @@ struct ata_taskfile {
((u64) (id)[(n) + 1] << 16) | \ ((u64) (id)[(n) + 1] << 16) | \
((u64) (id)[(n) + 0]) ) ((u64) (id)[(n) + 0]) )
#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
static inline unsigned int ata_id_major_version(const u16 *id) static inline unsigned int ata_id_major_version(const u16 *id)
{ {
unsigned int mver; unsigned int mver;
...@@ -311,6 +339,15 @@ static inline int is_atapi_taskfile(const struct ata_taskfile *tf) ...@@ -311,6 +339,15 @@ static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
(tf->protocol == ATA_PROT_ATAPI_DMA); (tf->protocol == ATA_PROT_ATAPI_DMA);
} }
static inline int is_multi_taskfile(struct ata_taskfile *tf)
{
return (tf->command == ATA_CMD_READ_MULTI) ||
(tf->command == ATA_CMD_WRITE_MULTI) ||
(tf->command == ATA_CMD_READ_MULTI_EXT) ||
(tf->command == ATA_CMD_WRITE_MULTI_EXT) ||
(tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT);
}
static inline int ata_ok(u8 status) static inline int ata_ok(u8 status)
{ {
return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR)) return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/ata.h> #include <linux/ata.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <scsi/scsi_host.h>
/* /*
* compile-time options: to be removed as soon as all the drivers are * compile-time options: to be removed as soon as all the drivers are
...@@ -44,7 +45,6 @@ ...@@ -44,7 +45,6 @@
#undef ATA_NDEBUG /* define to disable quick runtime checks */ #undef ATA_NDEBUG /* define to disable quick runtime checks */
#undef ATA_ENABLE_PATA /* define to enable PATA support in some #undef ATA_ENABLE_PATA /* define to enable PATA support in some
* low-level drivers */ * low-level drivers */
#undef ATAPI_ENABLE_DMADIR /* enables ATAPI DMADIR bridge support */
/* note: prints function name for you */ /* note: prints function name for you */
...@@ -108,8 +108,11 @@ enum { ...@@ -108,8 +108,11 @@ enum {
LIBATA_MAX_PRD = ATA_MAX_PRD / 2, LIBATA_MAX_PRD = ATA_MAX_PRD / 2,
ATA_MAX_PORTS = 8, ATA_MAX_PORTS = 8,
ATA_DEF_QUEUE = 1, ATA_DEF_QUEUE = 1,
ATA_MAX_QUEUE = 1, /* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
ATA_MAX_QUEUE = 32,
ATA_TAG_INTERNAL = ATA_MAX_QUEUE - 1,
ATA_MAX_SECTORS = 200, /* FIXME */ ATA_MAX_SECTORS = 200, /* FIXME */
ATA_MAX_SECTORS_LBA48 = 65535,
ATA_MAX_BUS = 2, ATA_MAX_BUS = 2,
ATA_DEF_BUSY_WAIT = 10000, ATA_DEF_BUSY_WAIT = 10000,
ATA_SHORT_PAUSE = (HZ >> 6) + 1, ATA_SHORT_PAUSE = (HZ >> 6) + 1,
...@@ -120,9 +123,17 @@ enum { ...@@ -120,9 +123,17 @@ enum {
ATA_SHT_USE_CLUSTERING = 1, ATA_SHT_USE_CLUSTERING = 1,
/* struct ata_device stuff */ /* struct ata_device stuff */
ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */
ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */
ATA_DFLAG_LBA = (1 << 2), /* device supports LBA */ ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */
ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */
ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */
ATA_DFLAG_INIT_MASK = (1 << 16) - 1,
ATA_DFLAG_DETACH = (1 << 16),
ATA_DFLAG_DETACHED = (1 << 17),
ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_UNKNOWN = 0, /* unknown device */
ATA_DEV_ATA = 1, /* ATA device */ ATA_DEV_ATA = 1, /* ATA device */
...@@ -132,43 +143,57 @@ enum { ...@@ -132,43 +143,57 @@ enum {
ATA_DEV_NONE = 5, /* no device */ ATA_DEV_NONE = 5, /* no device */
/* struct ata_port flags */ /* struct ata_port flags */
ATA_FLAG_SLAVE_POSS = (1 << 1), /* host supports slave dev */ ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
/* (doesn't imply presence) */ /* (doesn't imply presence) */
ATA_FLAG_PORT_DISABLED = (1 << 2), /* port is disabled, ignore it */ ATA_FLAG_SATA = (1 << 1),
ATA_FLAG_SATA = (1 << 3), ATA_FLAG_NO_LEGACY = (1 << 2), /* no legacy mode check */
ATA_FLAG_NO_LEGACY = (1 << 4), /* no legacy mode check */ ATA_FLAG_MMIO = (1 << 3), /* use MMIO, not PIO */
ATA_FLAG_SRST = (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */ ATA_FLAG_SRST = (1 << 4), /* (obsolete) use ATA SRST, not E.D.D. */
ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ ATA_FLAG_SATA_RESET = (1 << 5), /* (obsolete) use COMRESET */
ATA_FLAG_SATA_RESET = (1 << 7), /* (obsolete) use COMRESET */ ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */
ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */
ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */
* proper HSM is in place. */ ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD
ATA_FLAG_DEBUGMSG = (1 << 10), * doesn't handle PIO interrupts */
ATA_FLAG_NO_ATAPI = (1 << 11), /* No ATAPI support */ ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */
ATA_FLAG_HRST_TO_RESUME = (1 << 11), /* hardreset to resume phy */
ATA_FLAG_SUSPENDED = (1 << 12), /* port is suspended */ ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H
* Register FIS clearing BSY */
ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */
ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ ATA_FLAG_DEBUGMSG = (1 << 13),
ATA_FLAG_FLUSH_PORT_TASK = (1 << 14), /* flush port task */
ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */
ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */ ATA_FLAG_EH_PENDING = (1 << 15), /* EH pending */
ATA_FLAG_EH_IN_PROGRESS = (1 << 16), /* EH in progress */
ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_FLAG_FROZEN = (1 << 17), /* port is frozen */
ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ ATA_FLAG_RECOVERED = (1 << 18), /* recovery action performed */
ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ ATA_FLAG_LOADING = (1 << 19), /* boot/loading probe */
ATA_FLAG_UNLOADING = (1 << 20), /* module is unloading */
ATA_FLAG_SCSI_HOTPLUG = (1 << 21), /* SCSI hotplug scheduled */
ATA_FLAG_DISABLED = (1 << 22), /* port is disabled, ignore it */
ATA_FLAG_SUSPENDED = (1 << 23), /* port is suspended (power) */
/* bits 24:31 of ap->flags are reserved for LLDD specific flags */
/* struct ata_queued_cmd flags */
ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */
ATA_QCFLAG_SG = (1 << 1), /* have s/g table? */
ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ ATA_QCFLAG_IO = (1 << 3), /* standard IO command */
ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */
ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */
ATA_QCFLAG_EH_SCHEDULED = (1 << 18), /* EH scheduled (obsolete) */
/* host set flags */ /* host set flags */
ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */
/* various lengths of time */ /* various lengths of time */
ATA_TMOUT_PIO = 30 * HZ,
ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */ ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */
ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */ ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */
ATA_TMOUT_CDB = 30 * HZ,
ATA_TMOUT_CDB_QUICK = 5 * HZ,
ATA_TMOUT_INTERNAL = 30 * HZ, ATA_TMOUT_INTERNAL = 30 * HZ,
ATA_TMOUT_INTERNAL_QUICK = 5 * HZ, ATA_TMOUT_INTERNAL_QUICK = 5 * HZ,
...@@ -208,20 +233,55 @@ enum { ...@@ -208,20 +233,55 @@ enum {
ATA_DMA_PAD_SZ = 4, ATA_DMA_PAD_SZ = 4,
ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE,
/* Masks for port functions */ /* masks for port functions */
ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_PRIMARY = (1 << 0),
ATA_PORT_SECONDARY = (1 << 1), ATA_PORT_SECONDARY = (1 << 1),
/* ering size */
ATA_ERING_SIZE = 32,
/* desc_len for ata_eh_info and context */
ATA_EH_DESC_LEN = 80,
/* reset / recovery action types */
ATA_EH_REVALIDATE = (1 << 0),
ATA_EH_SOFTRESET = (1 << 1),
ATA_EH_HARDRESET = (1 << 2),
ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE,
/* ata_eh_info->flags */
ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */
/* max repeat if error condition is still set after ->error_handler */
ATA_EH_MAX_REPEAT = 5,
/* how hard are we gonna try to probe/recover devices */
ATA_PROBE_MAX_TRIES = 3,
ATA_EH_RESET_TRIES = 3,
ATA_EH_DEV_TRIES = 3,
/* Drive spinup time (time from power-on to the first D2H FIS)
* in msecs - 8s currently. Failing to get ready in this time
* isn't critical. It will result in reset failure for
* controllers which can't wait for the first D2H FIS. libata
* will retry, so it just has to be long enough to spin up
* most devices.
*/
ATA_SPINUP_WAIT = 8000,
}; };
enum hsm_task_states { enum hsm_task_states {
HSM_ST_UNKNOWN, HSM_ST_UNKNOWN, /* state unknown */
HSM_ST_IDLE, HSM_ST_IDLE, /* no command on going */
HSM_ST_POLL, HSM_ST, /* (waiting the device to) transfer data */
HSM_ST_TMOUT, HSM_ST_LAST, /* (waiting the device to) complete command */
HSM_ST, HSM_ST_ERR, /* error */
HSM_ST_LAST, HSM_ST_FIRST, /* (waiting the device to)
HSM_ST_LAST_POLL, write CDB or first data block */
HSM_ST_ERR,
}; };
enum ata_completion_errors { enum ata_completion_errors {
...@@ -244,9 +304,9 @@ struct ata_queued_cmd; ...@@ -244,9 +304,9 @@ struct ata_queued_cmd;
/* typedefs */ /* typedefs */
typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
typedef void (*ata_probeinit_fn_t)(struct ata_port *); typedef int (*ata_prereset_fn_t)(struct ata_port *ap);
typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *); typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes);
typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes);
struct ata_ioports { struct ata_ioports {
unsigned long cmd_addr; unsigned long cmd_addr;
...@@ -297,7 +357,8 @@ struct ata_host_set { ...@@ -297,7 +357,8 @@ struct ata_host_set {
unsigned long flags; unsigned long flags;
int simplex_claimed; /* Keep seperate in case we int simplex_claimed; /* Keep seperate in case we
ever need to do this locked */ ever need to do this locked */
struct ata_port * ports[0]; struct ata_host_set *next; /* for legacy mode */
struct ata_port *ports[0];
}; };
struct ata_queued_cmd { struct ata_queued_cmd {
...@@ -336,7 +397,7 @@ struct ata_queued_cmd { ...@@ -336,7 +397,7 @@ struct ata_queued_cmd {
struct scatterlist *__sg; struct scatterlist *__sg;
unsigned int err_mask; unsigned int err_mask;
struct ata_taskfile result_tf;
ata_qc_cb_t complete_fn; ata_qc_cb_t complete_fn;
void *private_data; void *private_data;
...@@ -348,12 +409,26 @@ struct ata_host_stats { ...@@ -348,12 +409,26 @@ struct ata_host_stats {
unsigned long rw_reqbuf; unsigned long rw_reqbuf;
}; };
struct ata_ering_entry {
int is_io;
unsigned int err_mask;
u64 timestamp;
};
struct ata_ering {
int cursor;
struct ata_ering_entry ring[ATA_ERING_SIZE];
};
struct ata_device { struct ata_device {
u64 n_sectors; /* size of device, if ATA */ struct ata_port *ap;
unsigned int devno; /* 0 or 1 */
unsigned long flags; /* ATA_DFLAG_xxx */ unsigned long flags; /* ATA_DFLAG_xxx */
struct scsi_device *sdev; /* attached SCSI device */
/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
u64 n_sectors; /* size of device, if ATA */
unsigned int class; /* ATA_DEV_xxx */ unsigned int class; /* ATA_DEV_xxx */
unsigned int devno; /* 0 or 1 */ u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
u16 *id; /* IDENTIFY xxx DEVICE data */
u8 pio_mode; u8 pio_mode;
u8 dma_mode; u8 dma_mode;
u8 xfer_mode; u8 xfer_mode;
...@@ -373,11 +448,42 @@ struct ata_device { ...@@ -373,11 +448,42 @@ struct ata_device {
u16 cylinders; /* Number of cylinders */ u16 cylinders; /* Number of cylinders */
u16 heads; /* Number of heads */ u16 heads; /* Number of heads */
u16 sectors; /* Number of sectors per track */ u16 sectors; /* Number of sectors per track */
/* error history */
struct ata_ering ering;
};
/* Offset into struct ata_device. Fields above it are maintained
* acress device init. Fields below are zeroed.
*/
#define ATA_DEVICE_CLEAR_OFFSET offsetof(struct ata_device, n_sectors)
struct ata_eh_info {
struct ata_device *dev; /* offending device */
u32 serror; /* SError from LLDD */
unsigned int err_mask; /* port-wide err_mask */
unsigned int action; /* ATA_EH_* action mask */
unsigned int dev_action[ATA_MAX_DEVICES]; /* dev EH action */
unsigned int flags; /* ATA_EHI_* flags */
unsigned long hotplug_timestamp;
unsigned int probe_mask;
char desc[ATA_EH_DESC_LEN];
int desc_len;
};
struct ata_eh_context {
struct ata_eh_info i;
int tries[ATA_MAX_DEVICES];
unsigned int classes[ATA_MAX_DEVICES];
unsigned int did_probe_mask;
}; };
struct ata_port { struct ata_port {
struct Scsi_Host *host; /* our co-allocated scsi host */ struct Scsi_Host *host; /* our co-allocated scsi host */
const struct ata_port_operations *ops; const struct ata_port_operations *ops;
spinlock_t *lock;
unsigned long flags; /* ATA_FLAG_xxx */ unsigned long flags; /* ATA_FLAG_xxx */
unsigned int id; /* unique id req'd by scsi midlyr */ unsigned int id; /* unique id req'd by scsi midlyr */
unsigned int port_no; /* unique port #; from zero */ unsigned int port_no; /* unique port #; from zero */
...@@ -397,26 +503,40 @@ struct ata_port { ...@@ -397,26 +503,40 @@ struct ata_port {
unsigned int mwdma_mask; unsigned int mwdma_mask;
unsigned int udma_mask; unsigned int udma_mask;
unsigned int cbl; /* cable type; ATA_CBL_xxx */ unsigned int cbl; /* cable type; ATA_CBL_xxx */
unsigned int hw_sata_spd_limit;
unsigned int sata_spd_limit; /* SATA PHY speed limit */
/* record runtime error info, protected by host_set lock */
struct ata_eh_info eh_info;
/* EH context owned by EH */
struct ata_eh_context eh_context;
struct ata_device device[ATA_MAX_DEVICES]; struct ata_device device[ATA_MAX_DEVICES];
struct ata_queued_cmd qcmd[ATA_MAX_QUEUE]; struct ata_queued_cmd qcmd[ATA_MAX_QUEUE];
unsigned long qactive; unsigned long qc_allocated;
unsigned int qc_active;
unsigned int active_tag; unsigned int active_tag;
u32 sactive;
struct ata_host_stats stats; struct ata_host_stats stats;
struct ata_host_set *host_set; struct ata_host_set *host_set;
struct device *dev; struct device *dev;
struct work_struct port_task; struct work_struct port_task;
struct work_struct hotplug_task;
struct work_struct scsi_rescan_task;
unsigned int hsm_task_state; unsigned int hsm_task_state;
unsigned long pio_task_timeout;
u32 msg_enable; u32 msg_enable;
struct list_head eh_done_q; struct list_head eh_done_q;
wait_queue_head_t eh_wait_q;
void *private_data; void *private_data;
u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */
}; };
struct ata_port_operations { struct ata_port_operations {
...@@ -438,7 +558,6 @@ struct ata_port_operations { ...@@ -438,7 +558,6 @@ struct ata_port_operations {
void (*phy_reset) (struct ata_port *ap); /* obsolete */ void (*phy_reset) (struct ata_port *ap); /* obsolete */
void (*set_mode) (struct ata_port *ap); void (*set_mode) (struct ata_port *ap);
int (*probe_reset) (struct ata_port *ap, unsigned int *classes);
void (*post_set_mode) (struct ata_port *ap); void (*post_set_mode) (struct ata_port *ap);
...@@ -447,10 +566,20 @@ struct ata_port_operations { ...@@ -447,10 +566,20 @@ struct ata_port_operations {
void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_setup) (struct ata_queued_cmd *qc);
void (*bmdma_start) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc);
void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
void (*qc_prep) (struct ata_queued_cmd *qc); void (*qc_prep) (struct ata_queued_cmd *qc);
unsigned int (*qc_issue) (struct ata_queued_cmd *qc); unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
void (*eng_timeout) (struct ata_port *ap); /* Error handlers. ->error_handler overrides ->eng_timeout and
* indicates that new-style EH is in place.
*/
void (*eng_timeout) (struct ata_port *ap); /* obsolete */
void (*freeze) (struct ata_port *ap);
void (*thaw) (struct ata_port *ap);
void (*error_handler) (struct ata_port *ap);
void (*post_internal_cmd) (struct ata_queued_cmd *qc);
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
void (*irq_clear) (struct ata_port *); void (*irq_clear) (struct ata_port *);
...@@ -492,22 +621,22 @@ struct ata_timing { ...@@ -492,22 +621,22 @@ struct ata_timing {
#define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin) #define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin)
extern const unsigned long sata_deb_timing_boot[];
extern const unsigned long sata_deb_timing_eh[];
extern const unsigned long sata_deb_timing_before_fsrst[];
extern void ata_port_probe(struct ata_port *); extern void ata_port_probe(struct ata_port *);
extern void __sata_phy_reset(struct ata_port *ap); extern void __sata_phy_reset(struct ata_port *ap);
extern void sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap);
extern void ata_bus_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap);
extern int ata_drive_probe_reset(struct ata_port *ap, extern int sata_set_spd(struct ata_port *ap);
ata_probeinit_fn_t probeinit, extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param);
ata_reset_fn_t softreset, ata_reset_fn_t hardreset, extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param);
ata_postreset_fn_t postreset, unsigned int *classes); extern int ata_std_prereset(struct ata_port *ap);
extern void ata_std_probeinit(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes);
extern int ata_std_softreset(struct ata_port *ap, int verbose, extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class);
unsigned int *classes);
extern int sata_std_hardreset(struct ata_port *ap, int verbose,
unsigned int *class);
extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, extern int ata_dev_revalidate(struct ata_device *dev, int post_reset);
int post_reset);
extern void ata_port_disable(struct ata_port *); extern void ata_port_disable(struct ata_port *);
extern void ata_std_ports(struct ata_ioports *ioaddr); extern void ata_std_ports(struct ata_ioports *ioaddr);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -519,24 +648,32 @@ extern int ata_pci_device_resume(struct pci_dev *pdev); ...@@ -519,24 +648,32 @@ extern int ata_pci_device_resume(struct pci_dev *pdev);
extern int ata_pci_clear_simplex(struct pci_dev *pdev); extern int ata_pci_clear_simplex(struct pci_dev *pdev);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
extern int ata_device_add(const struct ata_probe_ent *ent); extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_port_detach(struct ata_port *ap);
extern void ata_host_set_remove(struct ata_host_set *host_set); extern void ata_host_set_remove(struct ata_host_set *host_set);
extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_detect(struct scsi_host_template *sht);
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
extern int ata_scsi_release(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host);
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
extern int sata_scr_valid(struct ata_port *ap);
extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val);
extern int sata_scr_write(struct ata_port *ap, int reg, u32 val);
extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val);
extern int ata_port_online(struct ata_port *ap);
extern int ata_port_offline(struct ata_port *ap);
extern int ata_scsi_device_resume(struct scsi_device *); extern int ata_scsi_device_resume(struct scsi_device *);
extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
extern int ata_device_resume(struct ata_port *, struct ata_device *); extern int ata_device_resume(struct ata_device *);
extern int ata_device_suspend(struct ata_port *, struct ata_device *, pm_message_t state); extern int ata_device_suspend(struct ata_device *, pm_message_t state);
extern int ata_ratelimit(void); extern int ata_ratelimit(void);
extern unsigned int ata_busy_sleep(struct ata_port *ap, extern unsigned int ata_busy_sleep(struct ata_port *ap,
unsigned long timeout_pat, unsigned long timeout_pat,
unsigned long timeout); unsigned long timeout);
extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
void *data, unsigned long delay); void *data, unsigned long delay);
extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
unsigned long interval_msec,
unsigned long timeout_msec);
/* /*
* Default driver ops implementations * Default driver ops implementations
...@@ -550,11 +687,16 @@ extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); ...@@ -550,11 +687,16 @@ extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
extern u8 ata_check_status(struct ata_port *ap); extern u8 ata_check_status(struct ata_port *ap);
extern u8 ata_altstatus(struct ata_port *ap); extern u8 ata_altstatus(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf); extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
extern int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes);
extern int ata_port_start (struct ata_port *ap); extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap);
extern void ata_host_stop (struct ata_host_set *host_set); extern void ata_host_stop (struct ata_host_set *host_set);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data);
extern void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data);
extern void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data);
extern void ata_qc_prep(struct ata_queued_cmd *qc); extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
...@@ -572,17 +714,29 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc); ...@@ -572,17 +714,29 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
extern u8 ata_bmdma_status(struct ata_port *ap); extern u8 ata_bmdma_status(struct ata_port *ap);
extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap);
extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern void ata_bmdma_freeze(struct ata_port *ap);
extern void ata_eng_timeout(struct ata_port *ap); extern void ata_bmdma_thaw(struct ata_port *ap);
extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
struct scsi_cmnd *cmd, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset);
extern void ata_bmdma_error_handler(struct ata_port *ap);
extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
extern int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
u8 status, int in_wq);
extern void ata_qc_complete(struct ata_queued_cmd *qc);
extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
void (*finish_qc)(struct ata_queued_cmd *));
extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *)); void (*done)(struct scsi_cmnd *));
extern int ata_std_bios_param(struct scsi_device *sdev, extern int ata_std_bios_param(struct scsi_device *sdev,
struct block_device *bdev, struct block_device *bdev,
sector_t capacity, int geom[]); sector_t capacity, int geom[]);
extern int ata_scsi_slave_config(struct scsi_device *sdev); extern int ata_scsi_slave_config(struct scsi_device *sdev);
extern struct ata_device *ata_dev_pair(struct ata_port *ap, extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
struct ata_device *adev); extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
int queue_depth);
extern struct ata_device *ata_dev_pair(struct ata_device *adev);
/* /*
* Timing helpers * Timing helpers
...@@ -628,7 +782,64 @@ extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bit ...@@ -628,7 +782,64 @@ extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bit
extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_device *, unsigned long); extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_device *, unsigned long);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
/*
* EH
*/
extern void ata_eng_timeout(struct ata_port *ap);
extern void ata_port_schedule_eh(struct ata_port *ap);
extern int ata_port_abort(struct ata_port *ap);
extern int ata_port_freeze(struct ata_port *ap);
extern void ata_eh_freeze_port(struct ata_port *ap);
extern void ata_eh_thaw_port(struct ata_port *ap);
extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset);
/*
* printk helpers
*/
#define ata_port_printk(ap, lv, fmt, args...) \
printk(lv"ata%u: "fmt, (ap)->id , ##args)
#define ata_dev_printk(dev, lv, fmt, args...) \
printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args)
/*
* ata_eh_info helpers
*/
#define ata_ehi_push_desc(ehi, fmt, args...) do { \
(ehi)->desc_len += scnprintf((ehi)->desc + (ehi)->desc_len, \
ATA_EH_DESC_LEN - (ehi)->desc_len, \
fmt , ##args); \
} while (0)
#define ata_ehi_clear_desc(ehi) do { \
(ehi)->desc[0] = '\0'; \
(ehi)->desc_len = 0; \
} while (0)
static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
{
if (ehi->flags & ATA_EHI_HOTPLUGGED)
return;
ehi->flags |= ATA_EHI_HOTPLUGGED;
ehi->hotplug_timestamp = jiffies;
ehi->err_mask |= AC_ERR_ATA_BUS;
ehi->action |= ATA_EH_SOFTRESET;
ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
}
/*
* qc helpers
*/
static inline int static inline int
ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc) ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc)
{ {
...@@ -671,14 +882,39 @@ static inline unsigned int ata_tag_valid(unsigned int tag) ...@@ -671,14 +882,39 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
return (tag < ATA_MAX_QUEUE) ? 1 : 0; return (tag < ATA_MAX_QUEUE) ? 1 : 0;
} }
static inline unsigned int ata_class_present(unsigned int class) static inline unsigned int ata_tag_internal(unsigned int tag)
{
return tag == ATA_MAX_QUEUE - 1;
}
static inline unsigned int ata_class_enabled(unsigned int class)
{ {
return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI; return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI;
} }
static inline unsigned int ata_dev_present(const struct ata_device *dev) static inline unsigned int ata_class_disabled(unsigned int class)
{ {
return ata_class_present(dev->class); return class == ATA_DEV_ATA_UNSUP || class == ATA_DEV_ATAPI_UNSUP;
}
static inline unsigned int ata_class_absent(unsigned int class)
{
return !ata_class_enabled(class) && !ata_class_disabled(class);
}
static inline unsigned int ata_dev_enabled(const struct ata_device *dev)
{
return ata_class_enabled(dev->class);
}
static inline unsigned int ata_dev_disabled(const struct ata_device *dev)
{
return ata_class_disabled(dev->class);
}
static inline unsigned int ata_dev_absent(const struct ata_device *dev)
{
return ata_class_absent(dev->class);
} }
static inline u8 ata_chk_status(struct ata_port *ap) static inline u8 ata_chk_status(struct ata_port *ap)
...@@ -759,7 +995,7 @@ static inline void ata_qc_set_polling(struct ata_queued_cmd *qc) ...@@ -759,7 +995,7 @@ static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)
qc->tf.ctl |= ATA_NIEN; qc->tf.ctl |= ATA_NIEN;
} }
static inline struct ata_queued_cmd *ata_qc_from_tag (struct ata_port *ap, static inline struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
unsigned int tag) unsigned int tag)
{ {
if (likely(ata_tag_valid(tag))) if (likely(ata_tag_valid(tag)))
...@@ -767,12 +1003,27 @@ static inline struct ata_queued_cmd *ata_qc_from_tag (struct ata_port *ap, ...@@ -767,12 +1003,27 @@ static inline struct ata_queued_cmd *ata_qc_from_tag (struct ata_port *ap,
return NULL; return NULL;
} }
static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, unsigned int device) static inline struct ata_queued_cmd *ata_qc_from_tag(struct ata_port *ap,
unsigned int tag)
{
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
if (unlikely(!qc) || !ap->ops->error_handler)
return qc;
if ((qc->flags & (ATA_QCFLAG_ACTIVE |
ATA_QCFLAG_FAILED)) == ATA_QCFLAG_ACTIVE)
return qc;
return NULL;
}
static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf)
{ {
memset(tf, 0, sizeof(*tf)); memset(tf, 0, sizeof(*tf));
tf->ctl = ap->ctl; tf->ctl = dev->ap->ctl;
if (device == 0) if (dev->devno == 0)
tf->device = ATA_DEVICE_OBS; tf->device = ATA_DEVICE_OBS;
else else
tf->device = ATA_DEVICE_OBS | ATA_DEV1; tf->device = ATA_DEVICE_OBS | ATA_DEV1;
...@@ -787,26 +1038,11 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) ...@@ -787,26 +1038,11 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
qc->nbytes = qc->curbytes = 0; qc->nbytes = qc->curbytes = 0;
qc->err_mask = 0; qc->err_mask = 0;
ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); ata_tf_init(qc->dev, &qc->tf);
}
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
* @err_mask: ATA Status register contents
*
* Indicate to the mid and upper layers that an ATA
* command has completed, with either an ok or not-ok status.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static inline void ata_qc_complete(struct ata_queued_cmd *qc)
{
if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
return;
__ata_qc_complete(qc); /* init result_tf such that it indicates normal completion */
qc->result_tf.command = ATA_DRDY;
qc->result_tf.feature = 0;
} }
/** /**
...@@ -885,28 +1121,6 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) ...@@ -885,28 +1121,6 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
return status; return status;
} }
static inline u32 scr_read(struct ata_port *ap, unsigned int reg)
{
return ap->ops->scr_read(ap, reg);
}
static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val)
{
ap->ops->scr_write(ap, reg, val);
}
static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
u32 val)
{
ap->ops->scr_write(ap, reg, val);
(void) ap->ops->scr_read(ap, reg);
}
static inline unsigned int sata_dev_present(struct ata_port *ap)
{
return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
}
static inline int ata_try_flush_cache(const struct ata_device *dev) static inline int ata_try_flush_cache(const struct ata_device *dev)
{ {
return ata_id_wcache_enabled(dev->id) || return ata_id_wcache_enabled(dev->id) ||
...@@ -916,7 +1130,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev) ...@@ -916,7 +1130,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
static inline unsigned int ac_err_mask(u8 status) static inline unsigned int ac_err_mask(u8 status)
{ {
if (status & ATA_BUSY) if (status & (ATA_BUSY | ATA_DRQ))
return AC_ERR_HSM; return AC_ERR_HSM;
if (status & (ATA_ERR | ATA_DF)) if (status & (ATA_ERR | ATA_DF))
return AC_ERR_DEV; return AC_ERR_DEV;
...@@ -944,4 +1158,9 @@ static inline void ata_pad_free(struct ata_port *ap, struct device *dev) ...@@ -944,4 +1158,9 @@ static inline void ata_pad_free(struct ata_port *ap, struct device *dev)
dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
} }
static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host)
{
return (struct ata_port *) &host->hostdata[0];
}
#endif /* __LINUX_LIBATA_H__ */ #endif /* __LINUX_LIBATA_H__ */
...@@ -1196,8 +1196,12 @@ ...@@ -1196,8 +1196,12 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373 #define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373
#define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5 #define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5
#define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6 #define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC
#define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE #define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE
#define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF #define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7
#define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450 #define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450
#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451 #define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451
#define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452 #define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452
...@@ -1255,6 +1259,7 @@ ...@@ -1255,6 +1259,7 @@
#define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259 #define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259
#define PCI_DEVICE_ID_VIA_3269_0 0x0269 #define PCI_DEVICE_ID_VIA_3269_0 0x0269
#define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282 #define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282
#define PCI_DEVICE_ID_VIA_3296_0 0x0296
#define PCI_DEVICE_ID_VIA_8363_0 0x0305 #define PCI_DEVICE_ID_VIA_8363_0 0x0305
#define PCI_DEVICE_ID_VIA_P4M800CE 0x0314 #define PCI_DEVICE_ID_VIA_P4M800CE 0x0314
#define PCI_DEVICE_ID_VIA_8371_0 0x0391 #define PCI_DEVICE_ID_VIA_8371_0 0x0391
...@@ -1262,6 +1267,7 @@ ...@@ -1262,6 +1267,7 @@
#define PCI_DEVICE_ID_VIA_82C561 0x0561 #define PCI_DEVICE_ID_VIA_82C561 0x0561
#define PCI_DEVICE_ID_VIA_82C586_1 0x0571 #define PCI_DEVICE_ID_VIA_82C586_1 0x0571
#define PCI_DEVICE_ID_VIA_82C576 0x0576 #define PCI_DEVICE_ID_VIA_82C576 0x0576
#define PCI_DEVICE_ID_VIA_SATA_EIDE 0x0581
#define PCI_DEVICE_ID_VIA_82C586_0 0x0586 #define PCI_DEVICE_ID_VIA_82C586_0 0x0586
#define PCI_DEVICE_ID_VIA_82C596 0x0596 #define PCI_DEVICE_ID_VIA_82C596 0x0596
#define PCI_DEVICE_ID_VIA_82C597_0 0x0597 #define PCI_DEVICE_ID_VIA_82C597_0 0x0597
...@@ -1302,10 +1308,11 @@ ...@@ -1302,10 +1308,11 @@
#define PCI_DEVICE_ID_VIA_8783_0 0x3208 #define PCI_DEVICE_ID_VIA_8783_0 0x3208
#define PCI_DEVICE_ID_VIA_8237 0x3227 #define PCI_DEVICE_ID_VIA_8237 0x3227
#define PCI_DEVICE_ID_VIA_8251 0x3287 #define PCI_DEVICE_ID_VIA_8251 0x3287
#define PCI_DEVICE_ID_VIA_3296_0 0x0296 #define PCI_DEVICE_ID_VIA_8237A 0x3337
#define PCI_DEVICE_ID_VIA_8231 0x8231 #define PCI_DEVICE_ID_VIA_8231 0x8231
#define PCI_DEVICE_ID_VIA_8231_4 0x8235 #define PCI_DEVICE_ID_VIA_8231_4 0x8235
#define PCI_DEVICE_ID_VIA_8365_1 0x8305 #define PCI_DEVICE_ID_VIA_8365_1 0x8305
#define PCI_DEVICE_ID_VIA_CX700 0x8324
#define PCI_DEVICE_ID_VIA_8371_1 0x8391 #define PCI_DEVICE_ID_VIA_8371_1 0x8391
#define PCI_DEVICE_ID_VIA_82C598_1 0x8598 #define PCI_DEVICE_ID_VIA_82C598_1 0x8598
#define PCI_DEVICE_ID_VIA_838X_1 0xB188 #define PCI_DEVICE_ID_VIA_838X_1 0xB188
......
...@@ -145,6 +145,7 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); ...@@ -145,6 +145,7 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
extern void scsi_put_command(struct scsi_cmnd *); extern void scsi_put_command(struct scsi_cmnd *);
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void scsi_finish_command(struct scsi_cmnd *cmd);
extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd);
extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
size_t *offset, size_t *len); size_t *offset, size_t *len);
......
...@@ -472,6 +472,7 @@ struct Scsi_Host { ...@@ -472,6 +472,7 @@ struct Scsi_Host {
*/ */
unsigned int host_busy; /* commands actually active on low-level */ unsigned int host_busy; /* commands actually active on low-level */
unsigned int host_failed; /* commands that failed. */ unsigned int host_failed; /* commands that failed. */
unsigned int host_eh_scheduled; /* EH scheduled without command */
unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
int resetting; /* if set, it means that last_reset is a valid value */ int resetting; /* if set, it means that last_reset is a valid value */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment