head = tf->device & 0xf;
sect = tf->lbal;
- block = (cyl * dev->heads + head) * dev->sectors + sect;
+ if (!sect) {
+ ata_dev_printk(dev, KERN_WARNING, "device reported "
+ "invalid CHS sector 0\n");
+ sect = 1; /* oh well */
+ }
+
+ block = (cyl * dev->heads + head) * dev->sectors + sect - 1;
}
return block;
return rc;
}
+ dev->n_native_sectors = native_sectors;
/* nothing to do? */
if (native_sectors <= sectors || !ata_ignore_hpa) {
* Check if the current speed of the device requires IORDY. Used
* by various controllers for chip configuration.
*/
-
unsigned int ata_pio_need_iordy(const struct ata_device *adev)
{
- /* Controller doesn't support IORDY. Probably a pointless check
- as the caller should know this */
+ /* Don't set IORDY if we're preparing for reset. IORDY may
+ * lead to controller lock up on certain controllers if the
+ * port is not occupied. See bko#11703 for details.
+ */
+ if (adev->link->ap->pflags & ATA_PFLAG_RESETTING)
+ return 0;
+ /* Controller doesn't support IORDY. Probably a pointless
+ * check as the caller should know this.
+ */
if (adev->link->ap->flags & ATA_FLAG_NO_IORDY)
return 0;
/* CF spec. r4.1 Table 22 says no iordy on PIO5 and PIO6. */
* Compute the highest mode possible if we are not using iordy. Return
* -1 if no iordy mode is available.
*/
-
static u32 ata_pio_mask_no_iordy(const struct ata_device *adev)
{
/* If we have no drive specific rule, then PIO 2 is non IORDY */
return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
}
-static void ata_dev_config_ncq(struct ata_device *dev,
+static int ata_dev_config_ncq(struct ata_device *dev,
char *desc, size_t desc_sz)
{
struct ata_port *ap = dev->link->ap;
int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);
+ unsigned int err_mask;
+ char *aa_desc = "";
if (!ata_id_has_ncq(dev->id)) {
desc[0] = '\0';
- return;
+ return 0;
}
if (dev->horkage & ATA_HORKAGE_NONCQ) {
snprintf(desc, desc_sz, "NCQ (not used)");
- return;
+ return 0;
}
if (ap->flags & ATA_FLAG_NCQ) {
hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1);
dev->flags |= ATA_DFLAG_NCQ;
}
+ if (!(dev->horkage & ATA_HORKAGE_BROKEN_FPDMA_AA) &&
+ (ap->flags & ATA_FLAG_FPDMA_AA) &&
+ ata_id_has_fpdma_aa(dev->id)) {
+ err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE,
+ SATA_FPDMA_AA);
+ if (err_mask) {
+ ata_dev_printk(dev, KERN_ERR, "failed to enable AA"
+ "(error_mask=0x%x)\n", err_mask);
+ if (err_mask != AC_ERR_DEV) {
+ dev->horkage |= ATA_HORKAGE_BROKEN_FPDMA_AA;
+ return -EIO;
+ }
+ } else
+ aa_desc = ", AA";
+ }
+
if (hdepth >= ddepth)
- snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth);
+ snprintf(desc, desc_sz, "NCQ (depth %d)%s", ddepth, aa_desc);
else
- snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
+ snprintf(desc, desc_sz, "NCQ (depth %d/%d)%s", hdepth,
+ ddepth, aa_desc);
+ return 0;
}
/**
if (ata_id_has_lba(id)) {
const char *lba_desc;
- char ncq_desc[20];
+ char ncq_desc[24];
lba_desc = "LBA";
dev->flags |= ATA_DFLAG_LBA;
}
/* config NCQ */
- ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
+ rc = ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
+ if (rc)
+ return rc;
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info) {
static int ata_dev_set_mode(struct ata_device *dev)
{
+ struct ata_port *ap = dev->link->ap;
struct ata_eh_context *ehc = &dev->link->eh_context;
+ const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER;
const char *dev_err_whine = "";
int ign_dev_err = 0;
- unsigned int err_mask;
+ unsigned int err_mask = 0;
int rc;
dev->flags &= ~ATA_DFLAG_PIO;
if (dev->xfer_shift == ATA_SHIFT_PIO)
dev->flags |= ATA_DFLAG_PIO;
- err_mask = ata_dev_set_xfermode(dev);
+ if (nosetxfer && ap->flags & ATA_FLAG_SATA && ata_id_is_sata(dev->id))
+ dev_err_whine = " (SET_XFERMODE skipped)";
+ else {
+ if (nosetxfer)
+ ata_dev_printk(dev, KERN_WARNING,
+ "NOSETXFER but PATA detected - can't "
+ "skip SETXFER, might malfunction\n");
+ err_mask = ata_dev_set_xfermode(dev);
+ }
if (err_mask & ~AC_ERR_DEV)
goto fail;
unsigned int readid_flags)
{
u64 n_sectors = dev->n_sectors;
+ u64 n_native_sectors = dev->n_native_sectors;
int rc;
if (!ata_dev_enabled(dev))
/* verify n_sectors hasn't changed */
if (dev->class == ATA_DEV_ATA && n_sectors &&
dev->n_sectors != n_sectors) {
- ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
+ ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch "
"%llu != %llu\n",
(unsigned long long)n_sectors,
(unsigned long long)dev->n_sectors);
-
- /* restore original n_sectors */
- dev->n_sectors = n_sectors;
-
- rc = -ENODEV;
- goto fail;
+ /*
+ * Something could have caused HPA to be unlocked
+ * involuntarily. If n_native_sectors hasn't changed
+ * and the new size matches it, keep the device.
+ */
+ if (dev->n_native_sectors == n_native_sectors &&
+ dev->n_sectors > n_sectors &&
+ dev->n_sectors == n_native_sectors) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "new n_sectors matches native, probably "
+ "late HPA unlock, continuing\n");
+ /* keep using the old n_sectors */
+ dev->n_sectors = n_sectors;
+ } else {
+ /* restore original n_[native]_sectors and fail */
+ dev->n_native_sectors = n_native_sectors;
+ dev->n_sectors = n_sectors;
+ rc = -ENODEV;
+ goto fail;
+ }
}
return 0;
{ "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_HORKAGE_BROKEN_HPA },
{ "MAXTOR 6L080L4", "A93.0500", ATA_HORKAGE_BROKEN_HPA },
+ /* this one allows HPA unlocking but fails IOs on the area */
+ { "OCZ-VERTEX", "1.30", ATA_HORKAGE_BROKEN_HPA },
+
/* Devices which report 1 sector over size HPA */
{ "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE, },
{ "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE, },
/* Devices which aren't very happy with higher link speeds */
{ "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },
+ /*
+ * Devices which choke on SETXFER. Applies only if both the
+ * device and controller are SATA.
+ */
+ { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER },
+
/* End Marker */
{ }
};
*/
void ata_qc_free(struct ata_queued_cmd *qc)
{
- struct ata_port *ap = qc->ap;
+ struct ata_port *ap;
unsigned int tag;
WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
+ ap = qc->ap;
qc->flags = 0;
tag = qc->tag;
void __ata_qc_complete(struct ata_queued_cmd *qc)
{
- struct ata_port *ap = qc->ap;
- struct ata_link *link = qc->dev->link;
+ struct ata_port *ap;
+ struct ata_link *link;
WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE));
+ ap = qc->ap;
+ link = qc->dev->link;
if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
ata_sg_clean(qc);
struct ata_device *dev = qc->dev;
struct ata_eh_info *ehi = &dev->link->eh_info;
- WARN_ON_ONCE(ap->pflags & ATA_PFLAG_FROZEN);
-
if (unlikely(qc->err_mask))
qc->flags |= ATA_QCFLAG_FAILED;
if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
- if (!ata_tag_internal(qc->tag)) {
- /* always fill result TF for failed qc */
- fill_result_tf(qc);
+ /* always fill result TF for failed qc */
+ fill_result_tf(qc);
+
+ if (!ata_tag_internal(qc->tag))
ata_qc_schedule_eh(qc);
- return;
- }
+ else
+ __ata_qc_complete(qc);
+ return;
}
+ WARN_ON_ONCE(ap->pflags & ATA_PFLAG_FROZEN);
+
/* read result TF if requested */
if (qc->flags & ATA_QCFLAG_RESULT_TF)
fill_result_tf(qc);
dev->link = link;
dev->devno = dev - link->device;
+#ifdef CONFIG_ATA_ACPI
+ dev->gtf_filter = ata_acpi_gtf_filter;
+#endif
ata_dev_init(dev);
}
}