forked from Minki/linux
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: libata: track spindown status and skip spindown_compat if possible libata: fix shutdown warning message printing libata-acpi: add ATA_FLAG_ACPI_SATA port flag libata: during revalidation, check n_sectors after device is configured libata: separate out ata_dev_reread_id() pata_scc had been missed by ata_std_prereset() switch
This commit is contained in:
commit
b2cd64153b
@ -173,7 +173,8 @@ enum {
|
||||
|
||||
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
ATA_FLAG_SKIP_D2H_BSY,
|
||||
ATA_FLAG_SKIP_D2H_BSY |
|
||||
ATA_FLAG_ACPI_SATA,
|
||||
};
|
||||
|
||||
struct ahci_cmd_hdr {
|
||||
|
@ -321,7 +321,7 @@ static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
|
||||
|
||||
/* Don't continue if device has no _ADR method.
|
||||
* _GTF is intended for known motherboard devices. */
|
||||
if (!(ap->cbl == ATA_CBL_SATA)) {
|
||||
if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
|
||||
err = pata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
|
||||
if (err < 0) {
|
||||
if (ata_msg_probe(ap))
|
||||
@ -343,7 +343,7 @@ static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
|
||||
|
||||
/* Get this drive's _ADR info. if not already known. */
|
||||
if (!dev->obj_handle) {
|
||||
if (!(ap->cbl == ATA_CBL_SATA)) {
|
||||
if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
|
||||
/* get child objects of dev_handle == channel objects,
|
||||
* + _their_ children == drive objects */
|
||||
/* channel is ap->port_no */
|
||||
@ -528,7 +528,7 @@ static int do_drive_set_taskfiles(struct ata_device *dev,
|
||||
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
|
||||
__FUNCTION__, ap->port_no);
|
||||
|
||||
if (libata_noacpi || !(ap->cbl == ATA_CBL_SATA))
|
||||
if (libata_noacpi || !(ap->flags & ATA_FLAG_ACPI_SATA))
|
||||
return 0;
|
||||
|
||||
if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED))
|
||||
@ -578,7 +578,7 @@ int ata_acpi_exec_tfs(struct ata_port *ap)
|
||||
* we should not run GTF on PATA devices since some
|
||||
* PATA require execution of GTM/STM before GTF.
|
||||
*/
|
||||
if (!(ap->cbl == ATA_CBL_SATA))
|
||||
if (!(ap->flags & ATA_FLAG_ACPI_SATA))
|
||||
return 0;
|
||||
|
||||
for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
|
||||
@ -641,7 +641,7 @@ int ata_acpi_push_id(struct ata_device *dev)
|
||||
__FUNCTION__, dev->devno, ap->port_no);
|
||||
|
||||
/* Don't continue if not a SATA device. */
|
||||
if (!(ap->cbl == ATA_CBL_SATA)) {
|
||||
if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
|
||||
if (ata_msg_probe(ap))
|
||||
ata_dev_printk(dev, KERN_DEBUG,
|
||||
"%s: Not a SATA device\n", __FUNCTION__);
|
||||
|
@ -1919,7 +1919,6 @@ int ata_dev_configure(struct ata_device *dev)
|
||||
snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
|
||||
|
||||
dev->n_sectors = ata_id_n_sectors(id);
|
||||
dev->n_sectors_boot = dev->n_sectors;
|
||||
|
||||
/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
|
||||
ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
|
||||
@ -3632,7 +3631,6 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
|
||||
const u16 *old_id = dev->id;
|
||||
unsigned char model[2][ATA_ID_PROD_LEN + 1];
|
||||
unsigned char serial[2][ATA_ID_SERNO_LEN + 1];
|
||||
u64 new_n_sectors;
|
||||
|
||||
if (dev->class != new_class) {
|
||||
ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
|
||||
@ -3644,7 +3642,6 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
|
||||
ata_id_c_string(new_id, model[1], ATA_ID_PROD, sizeof(model[1]));
|
||||
ata_id_c_string(old_id, serial[0], ATA_ID_SERNO, sizeof(serial[0]));
|
||||
ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1]));
|
||||
new_n_sectors = ata_id_n_sectors(new_id);
|
||||
|
||||
if (strcmp(model[0], model[1])) {
|
||||
ata_dev_printk(dev, KERN_INFO, "model number mismatch "
|
||||
@ -3658,25 +3655,12 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
|
||||
ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
|
||||
"%llu != %llu\n",
|
||||
(unsigned long long)dev->n_sectors,
|
||||
(unsigned long long)new_n_sectors);
|
||||
/* Are we the boot time size - if so we appear to be the
|
||||
same disk at this point and our HPA got reapplied */
|
||||
if (ata_ignore_hpa && dev->n_sectors_boot == new_n_sectors
|
||||
&& ata_id_hpa_enabled(new_id))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_revalidate - Revalidate ATA device
|
||||
* @dev: device to revalidate
|
||||
* ata_dev_reread_id - Re-read IDENTIFY data
|
||||
* @adev: target ATA device
|
||||
* @readid_flags: read ID flags
|
||||
*
|
||||
* Re-read IDENTIFY page and make sure @dev is still attached to
|
||||
@ -3688,34 +3672,68 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
|
||||
* RETURNS:
|
||||
* 0 on success, negative errno otherwise
|
||||
*/
|
||||
int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
|
||||
int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags)
|
||||
{
|
||||
unsigned int class = dev->class;
|
||||
u16 *id = (void *)dev->ap->sector_buf;
|
||||
int rc;
|
||||
|
||||
if (!ata_dev_enabled(dev)) {
|
||||
rc = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* read ID data */
|
||||
rc = ata_dev_read_id(dev, &class, readid_flags, id);
|
||||
if (rc)
|
||||
goto fail;
|
||||
return rc;
|
||||
|
||||
/* is the device still there? */
|
||||
if (!ata_dev_same_device(dev, class, id)) {
|
||||
if (!ata_dev_same_device(dev, class, id))
|
||||
return -ENODEV;
|
||||
|
||||
memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_revalidate - Revalidate ATA device
|
||||
* @dev: device to revalidate
|
||||
* @readid_flags: read ID flags
|
||||
*
|
||||
* Re-read IDENTIFY page, make sure @dev is still attached to the
|
||||
* port and reconfigure it according to the new IDENTIFY page.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep)
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, negative errno otherwise
|
||||
*/
|
||||
int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
|
||||
{
|
||||
u64 n_sectors = dev->n_sectors;
|
||||
int rc;
|
||||
|
||||
if (!ata_dev_enabled(dev))
|
||||
return -ENODEV;
|
||||
|
||||
/* re-read ID */
|
||||
rc = ata_dev_reread_id(dev, readid_flags);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
/* configure device according to the new ID */
|
||||
rc = ata_dev_configure(dev);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
/* verify n_sectors hasn't changed */
|
||||
if (dev->class == ATA_DEV_ATA && dev->n_sectors != n_sectors) {
|
||||
ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
|
||||
"%llu != %llu\n",
|
||||
(unsigned long long)n_sectors,
|
||||
(unsigned long long)dev->n_sectors);
|
||||
rc = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
|
||||
|
||||
/* configure device according to the new ID */
|
||||
rc = ata_dev_configure(dev);
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
|
||||
|
@ -893,6 +893,23 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
|
||||
return queue_depth;
|
||||
}
|
||||
|
||||
/* XXX: for ata_spindown_compat */
|
||||
static void ata_delayed_done_timerfn(unsigned long arg)
|
||||
{
|
||||
struct scsi_cmnd *scmd = (void *)arg;
|
||||
|
||||
scmd->scsi_done(scmd);
|
||||
}
|
||||
|
||||
/* XXX: for ata_spindown_compat */
|
||||
static void ata_delayed_done(struct scsi_cmnd *scmd)
|
||||
{
|
||||
static struct timer_list timer;
|
||||
|
||||
setup_timer(&timer, ata_delayed_done_timerfn, (unsigned long)scmd);
|
||||
mod_timer(&timer, jiffies + 5 * HZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
|
||||
* @qc: Storage for translated ATA taskfile
|
||||
@ -950,21 +967,24 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
|
||||
* for more info.
|
||||
*/
|
||||
if (ata_spindown_compat &&
|
||||
(qc->dev->flags & ATA_DFLAG_SPUNDOWN) &&
|
||||
(system_state == SYSTEM_HALT ||
|
||||
system_state == SYSTEM_POWER_OFF)) {
|
||||
static int warned = 0;
|
||||
static unsigned long warned = 0;
|
||||
|
||||
if (!warned) {
|
||||
spin_unlock_irq(qc->ap->lock);
|
||||
if (!test_and_set_bit(0, &warned)) {
|
||||
ata_dev_printk(qc->dev, KERN_WARNING,
|
||||
"DISK MIGHT NOT BE SPUN DOWN PROPERLY. "
|
||||
"UPDATE SHUTDOWN UTILITY\n");
|
||||
ata_dev_printk(qc->dev, KERN_WARNING,
|
||||
"For more info, visit "
|
||||
"http://linux-ata.org/shutdown.html\n");
|
||||
warned = 1;
|
||||
ssleep(5);
|
||||
spin_lock_irq(qc->ap->lock);
|
||||
|
||||
/* ->scsi_done is not used, use it for
|
||||
* delayed completion.
|
||||
*/
|
||||
scmd->scsi_done = qc->scsidone;
|
||||
qc->scsidone = ata_delayed_done;
|
||||
}
|
||||
scmd->result = SAM_STAT_GOOD;
|
||||
return 1;
|
||||
@ -1375,6 +1395,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: track spindown state for spindown_compat */
|
||||
if (unlikely(qc->tf.command == ATA_CMD_STANDBY ||
|
||||
qc->tf.command == ATA_CMD_STANDBYNOW1))
|
||||
qc->dev->flags |= ATA_DFLAG_SPUNDOWN;
|
||||
else if (likely(system_state != SYSTEM_HALT &&
|
||||
system_state != SYSTEM_POWER_OFF))
|
||||
qc->dev->flags &= ~ATA_DFLAG_SPUNDOWN;
|
||||
|
||||
if (need_sense && !ap->ops->error_handler)
|
||||
ata_dump_status(ap->print_id, &qc->result_tf);
|
||||
|
||||
@ -1488,14 +1516,14 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
|
||||
|
||||
early_finish:
|
||||
ata_qc_free(qc);
|
||||
done(cmd);
|
||||
qc->scsidone(cmd);
|
||||
DPRINTK("EXIT - early finish (good or error)\n");
|
||||
return 0;
|
||||
|
||||
err_did:
|
||||
ata_qc_free(qc);
|
||||
cmd->result = (DID_ERROR << 16);
|
||||
done(cmd);
|
||||
qc->scsidone(cmd);
|
||||
err_mem:
|
||||
DPRINTK("EXIT - internal\n");
|
||||
return 0;
|
||||
|
@ -76,7 +76,8 @@ extern unsigned ata_exec_internal_sg(struct ata_device *dev,
|
||||
extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
|
||||
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
|
||||
unsigned int flags, u16 *id);
|
||||
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int flags);
|
||||
extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
|
||||
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags);
|
||||
extern int ata_dev_configure(struct ata_device *dev);
|
||||
extern int sata_down_spd_limit(struct ata_port *ap);
|
||||
extern int sata_set_spd_needed(struct ata_port *ap);
|
||||
|
@ -864,10 +864,10 @@ static void scc_bmdma_freeze (struct ata_port *ap)
|
||||
* @ap: ATA port to be reset
|
||||
*/
|
||||
|
||||
static int scc_pata_prereset (struct ata_port *ap)
|
||||
static int scc_pata_prereset (struct ata_port *ap, unsigned long deadline)
|
||||
{
|
||||
ap->cbl = ATA_CBL_PATA80;
|
||||
return ata_std_prereset(ap);
|
||||
return ata_std_prereset(ap, deadline);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,7 +237,8 @@ enum {
|
||||
/* 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,
|
||||
ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY |
|
||||
ATA_FLAG_ACPI_SATA,
|
||||
SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
|
||||
|
||||
IRQ_STAT_4PORTS = 0xf,
|
||||
|
@ -140,6 +140,7 @@ enum {
|
||||
|
||||
ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */
|
||||
ATA_DFLAG_NCQ_OFF = (1 << 9), /* device limited to non-NCQ mode */
|
||||
ATA_DFLAG_SPUNDOWN = (1 << 10), /* XXX: for spindown_compat */
|
||||
ATA_DFLAG_INIT_MASK = (1 << 16) - 1,
|
||||
|
||||
ATA_DFLAG_DETACH = (1 << 16),
|
||||
@ -173,6 +174,7 @@ enum {
|
||||
ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
|
||||
ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
|
||||
ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
|
||||
ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
|
||||
|
||||
/* The following flag belongs to ap->pflags but is kept in
|
||||
* ap->flags because it's referenced in many LLDs and will be
|
||||
@ -431,7 +433,6 @@ struct ata_device {
|
||||
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 */
|
||||
u64 n_sectors_boot; /* size of ATA device at startup */
|
||||
unsigned int class; /* ATA_DEV_xxx */
|
||||
u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
|
||||
u8 pio_mode;
|
||||
|
Loading…
Reference in New Issue
Block a user