Commit 72f60acb authored by Linus Torvalds's avatar Linus Torvalds

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

* 'linus-plus-plus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  libata: limit post SRST nsect/lbal wait to ~100ms
  libata: force PIO on IOMEGA ZIP 250 ATAPI
  libata passthru: update cached device paramters
  libata passthru: always enforce correct DEV bit
  libata passthru: map UDMA protocols
  libata passthru: support PIO multi commands
  libata passthru: update protocol numbers
  libata: Correct abuse of language
  libata-core/sff: Fix multiple assumptions about DMA
  ahci: Add MCP73/MCP77 support to AHCI driver
  libata: fix hw_sata_spd_limit initialization
  libata: print device model and firmware revision for ATAPI devices
  libata: fix probe time irq printouts
  libata: disable NCQ for HITACHI HTS541680J9SA00/SB21C7EP
  remove unused variable in pata_isapnp
parents b44c0267 e141d999
......@@ -426,6 +426,30 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
/* SiS */
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
......
......@@ -1727,7 +1727,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
/* sanity check */
rc = -EINVAL;
reason = "device reports illegal type";
reason = "device reports invalid type";
if (class == ATA_DEV_ATA) {
if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
......@@ -1900,6 +1900,13 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_msg_probe(ap))
ata_dump_id(id);
/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
sizeof(fwrevbuf));
ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
sizeof(modelbuf));
/* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) {
if (ata_id_is_cfa(id)) {
......@@ -1914,13 +1921,6 @@ int ata_dev_configure(struct ata_device *dev)
dev->n_sectors = ata_id_n_sectors(id);
/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
sizeof(fwrevbuf));
ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
sizeof(modelbuf));
if (dev->id[59] & 0x100)
dev->multi_count = dev->id[59] & 0xff;
......@@ -2009,7 +2009,9 @@ int ata_dev_configure(struct ata_device *dev)
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
ata_dev_printk(dev, KERN_INFO,
"ATAPI: %s, %s, max %s%s\n",
modelbuf, fwrevbuf,
ata_mode_string(xfer_mask),
cdb_intr_string);
}
......@@ -3059,22 +3061,28 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
}
}
/* if device 1 was found in ata_devchk, wait for
* register access, then wait for BSY to clear
/* if device 1 was found in ata_devchk, wait for register
* access briefly, then wait for BSY to clear.
*/
while (dev1) {
u8 nsect, lbal;
if (dev1) {
int i;
ap->ops->dev_select(ap, 1);
/* Wait for register access. Some ATAPI devices fail
* to set nsect/lbal after reset, so don't waste too
* much time on it. We're gonna wait for !BSY anyway.
*/
for (i = 0; i < 2; i++) {
u8 nsect, lbal;
nsect = ioread8(ioaddr->nsect_addr);
lbal = ioread8(ioaddr->lbal_addr);
if ((nsect == 1) && (lbal == 1))
break;
if (time_after(jiffies, deadline))
return -EBUSY;
msleep(50); /* give drive a breather */
}
if (dev1) {
rc = ata_wait_ready(ap, deadline);
if (rc) {
if (rc != -ENODEV)
......@@ -3769,6 +3777,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
{ "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */
/* Weird ATAPI devices */
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 |
......@@ -3791,6 +3800,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, },
/* Drives which do spurious command completion */
{ "HTS541680J9SA00", "SB2IC7EP", ATA_HORKAGE_NONCQ, },
/* Devices with NCQ limits */
......@@ -6313,6 +6324,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
/* init sata_spd_limit to the current value */
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
int spd = (scontrol >> 4) & 0xf;
if (spd)
ap->hw_sata_spd_limit &= (1 << spd) - 1;
}
ap->sata_spd_limit = ap->hw_sata_spd_limit;
......@@ -6433,6 +6445,9 @@ int ata_host_activate(struct ata_host *host, int irq,
if (rc)
devm_free_irq(host->dev, irq, host);
/* Used to print device info at probe */
host->irq = irq;
return rc;
}
......@@ -6818,6 +6833,7 @@ EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_altstatus);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_sff_port_start);
EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_do_set_mode);
EXPORT_SYMBOL_GPL(ata_data_xfer);
......
......@@ -1363,13 +1363,23 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
* cache
*/
if (ap->ops->error_handler &&
!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
((qc->tf.feature == SETFEATURES_WC_ON) ||
(qc->tf.feature == SETFEATURES_WC_OFF))) {
if (ap->ops->error_handler && !need_sense) {
switch (qc->tf.command) {
case ATA_CMD_SET_FEATURES:
if ((qc->tf.feature == SETFEATURES_WC_ON) ||
(qc->tf.feature == SETFEATURES_WC_OFF)) {
ap->eh_info.action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(ap);
}
break;
case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
case ATA_CMD_SET_MULTI: /* multi_count changed */
ap->eh_info.action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(ap);
break;
}
}
/* For ATA pass thru (SAT) commands, generate a sense block if
* user mandated it or if there's an error. Note that if we
......@@ -2506,22 +2516,21 @@ ata_scsi_map_proto(u8 byte1)
return ATA_PROT_NODATA;
case 6: /* DMA */
case 10: /* UDMA Data-in */
case 11: /* UDMA Data-Out */
return ATA_PROT_DMA;
case 4: /* PIO Data-in */
case 5: /* PIO Data-out */
return ATA_PROT_PIO;
case 10: /* Device Reset */
case 0: /* Hard Reset */
case 1: /* SRST */
case 2: /* Bus Idle */
case 7: /* Packet */
case 8: /* DMA Queued */
case 9: /* Device Diagnostic */
case 11: /* UDMA Data-in */
case 12: /* UDMA Data-Out */
case 13: /* FPDMA */
case 8: /* Device Diagnostic */
case 9: /* Device Reset */
case 7: /* DMA Queued */
case 12: /* FPDMA */
case 15: /* Return Response Info */
default: /* Reserved */
break;
}
......@@ -2552,10 +2561,6 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
goto invalid_fld;
if (cdb[1] & 0xe0)
/* PIO multi not supported yet */
goto invalid_fld;
/*
* 12 and 16 byte CDBs use different offsets to
* provide the various register values.
......@@ -2600,13 +2605,27 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->device = cdb[8];
tf->command = cdb[9];
}
/*
* If slave is possible, enforce correct master/slave bit
*/
if (qc->ap->flags & ATA_FLAG_SLAVE_POSS)
tf->device = qc->dev->devno ?
/* enforce correct master/slave bit */
tf->device = dev->devno ?
tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
/* sanity check for pio multi commands */
if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf))
goto invalid_fld;
if (is_multi_taskfile(tf)) {
unsigned int multi_count = 1 << (cdb[1] >> 5);
/* compare the passed through multi_count
* with the cached multi_count of libata
*/
if (multi_count != dev->multi_count)
ata_dev_printk(dev, KERN_WARNING,
"invalid multi_count %u ignored\n",
multi_count);
}
/* READ/WRITE LONG use a non-standard sect_size */
qc->sect_size = ATA_SECT_SIZE;
switch (tf->command) {
......
......@@ -80,25 +80,25 @@ u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; }
u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
{
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
u8 host_stat, post_stat, status;
u8 host_stat = 0, post_stat = 0, status;
status = ata_busy_wait(ap, bits, 1000);
if (status & bits)
if (ata_msg_err(ap))
printk(KERN_ERR "abnormal status 0x%X\n", status);
if (ap->ioaddr.bmdma_addr) {
/* get controller status; clear intr, err bits */
host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
}
if (ata_msg_intr(ap))
printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
__FUNCTION__,
host_stat, post_stat, status);
return status;
}
......@@ -516,6 +516,27 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
ata_bmdma_stop(qc);
}
/**
* ata_sff_port_start - Set port up for dma.
* @ap: Port to initialize
*
* Called just after data structures for each port are
* initialized. Allocates space for PRD table if the device
* is DMA capable SFF.
*
* May be used as the port_start() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
int ata_sff_port_start(struct ata_port *ap)
{
if (ap->ioaddr.bmdma_addr)
return ata_port_start(ap);
return 0;
}
#ifdef CONFIG_PCI
static int ata_resources_present(struct pci_dev *pdev, int port)
......
......@@ -77,7 +77,6 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
struct ata_host *host;
struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr;
int rc;
if (pnp_port_valid(idev, 0) == 0)
return -ENODEV;
......
......@@ -151,6 +151,7 @@ enum {
ATA_CMD_WRITE_MULTI_EXT = 0x39,
ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
ATA_CMD_SET_FEATURES = 0xEF,
ATA_CMD_SET_MULTI = 0xC6,
ATA_CMD_PACKET = 0xA0,
ATA_CMD_VERIFY = 0x40,
ATA_CMD_VERIFY_EXT = 0x42,
......@@ -249,7 +250,7 @@ enum ata_tf_protocols {
/* ATA taskfile protocols */
ATA_PROT_UNKNOWN, /* unknown/invalid */
ATA_PROT_NODATA, /* no data */
ATA_PROT_PIO, /* PIO single sector */
ATA_PROT_PIO, /* PIO data xfer */
ATA_PROT_DMA, /* DMA */
ATA_PROT_NCQ, /* NCQ */
ATA_PROT_ATAPI, /* packet command, PIO data xfer*/
......
......@@ -753,6 +753,7 @@ extern u8 ata_check_status(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 int ata_port_start (struct ata_port *ap);
extern int ata_sff_port_start (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data);
......
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