|
|
|
[PATCH 07/15] libata-ncq: implement ata_eh_read_log_10h() | |
| [Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] | |
Implement ata_eh_read_log_10h(). This will be used by NCQ EH.
Signed-off-by: Tejun Heo <htejun@xxxxxxxxx>
---
drivers/scsi/libata-eh.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 107 insertions(+), 0 deletions(-)
ad48d9c5999b24b4ed71e6a2dd9cf1ff20aa90d9
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 0d8a9cb..795f580 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -560,6 +560,113 @@ static unsigned int atapi_eh_request_sen
}
/**
+ * ata_read_log_page - read a specific log page
+ * @ap: port on which device we wish to probe resides
+ * @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_port *ap,
+ 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(ap, &tf, dev->devno);
+ 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(ap, 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
+ * @ap: Port associated with device @dev
+ * @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_port *ap, struct ata_device *dev,
+ unsigned int *tag, struct ata_taskfile *tf)
+{
+ u8 *buf, csum;
+ unsigned int err_mask;
+ int i, rc;
+
+ buf = kmalloc(ATA_SECT_SIZE, GFP_KERNEL);
+ if (buf == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ err_mask = ata_read_log_page(ap, dev, ATA_LOG_SATA_NCQ, buf, 1);
+ if (err_mask) {
+ rc = -EIO;
+ goto out;
+ }
+
+ csum = 0;
+ for (i = 0; i < ATA_SECT_SIZE; i++)
+ csum += buf[i];
+ if (csum)
+ printk(KERN_WARNING "ata%u: dev %u invalid checksum 0x%x on "
+ "log page 10h\n", ap->id, dev->devno, csum);
+
+ if (buf[0] & 0x80) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ *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];
+
+ rc = 0;
+ out:
+ kfree(buf);
+ return rc;
+}
+
+/**
* ata_eh_determine_qc - Determine which qc caused error
* @ap: port which failed
* @tf: resulting taskfile registers of the failed command
--
1.2.4
-
: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
[Site Home] [Git] [Kernel Newbies] [Linux Newbie] [Share Photos] [Security] [Netfilter] [Bugtraq] [Linux Filesystems] [Photo] [Yosemite] [Yosemite News] [MIPS Linux] [ARM Linux] [Linux Security] [Linux SCSI] [Linux RAID] [Samba] [Video 4 Linux] [Device Mapper] [Linux Resources]
![]() |