|
@@ -64,6 +64,7 @@
|
|
#include <linux/libata.h>
|
|
#include <linux/libata.h>
|
|
#include <asm/semaphore.h>
|
|
#include <asm/semaphore.h>
|
|
#include <asm/byteorder.h>
|
|
#include <asm/byteorder.h>
|
|
|
|
+#include <linux/cdrom.h>
|
|
|
|
|
|
#include "libata.h"
|
|
#include "libata.h"
|
|
|
|
|
|
@@ -4651,6 +4652,43 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * atapi_qc_may_overflow - Check whether data transfer may overflow
|
|
|
|
+ * @qc: ATA command in question
|
|
|
|
+ *
|
|
|
|
+ * ATAPI commands which transfer variable length data to host
|
|
|
|
+ * might overflow due to application error or hardare bug. This
|
|
|
|
+ * function checks whether overflow should be drained and ignored
|
|
|
|
+ * for @qc.
|
|
|
|
+ *
|
|
|
|
+ * LOCKING:
|
|
|
|
+ * None.
|
|
|
|
+ *
|
|
|
|
+ * RETURNS:
|
|
|
|
+ * 1 if @qc may overflow; otherwise, 0.
|
|
|
|
+ */
|
|
|
|
+static int atapi_qc_may_overflow(struct ata_queued_cmd *qc)
|
|
|
|
+{
|
|
|
|
+ if (qc->tf.protocol != ATA_PROT_ATAPI &&
|
|
|
|
+ qc->tf.protocol != ATA_PROT_ATAPI_DMA)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (qc->tf.flags & ATA_TFLAG_WRITE)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ switch (qc->cdb[0]) {
|
|
|
|
+ case READ_10:
|
|
|
|
+ case READ_12:
|
|
|
|
+ case WRITE_10:
|
|
|
|
+ case WRITE_12:
|
|
|
|
+ case GPCMD_READ_CD:
|
|
|
|
+ case GPCMD_READ_CD_MSF:
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* ata_std_qc_defer - Check whether a qc needs to be deferred
|
|
* ata_std_qc_defer - Check whether a qc needs to be deferred
|
|
* @qc: ATA command in question
|
|
* @qc: ATA command in question
|
|
@@ -5139,23 +5177,19 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
|
|
* Inherited from caller.
|
|
* Inherited from caller.
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
-
|
|
|
|
-static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
|
|
|
|
|
|
+static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
|
|
{
|
|
{
|
|
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
|
|
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
|
|
- struct scatterlist *sg = qc->__sg;
|
|
|
|
- struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem);
|
|
|
|
struct ata_port *ap = qc->ap;
|
|
struct ata_port *ap = qc->ap;
|
|
|
|
+ struct ata_eh_info *ehi = &qc->dev->link->eh_info;
|
|
|
|
+ struct scatterlist *sg;
|
|
struct page *page;
|
|
struct page *page;
|
|
unsigned char *buf;
|
|
unsigned char *buf;
|
|
unsigned int offset, count;
|
|
unsigned int offset, count;
|
|
- int no_more_sg = 0;
|
|
|
|
-
|
|
|
|
- if (qc->curbytes + bytes >= qc->nbytes)
|
|
|
|
- ap->hsm_task_state = HSM_ST_LAST;
|
|
|
|
|
|
|
|
next_sg:
|
|
next_sg:
|
|
- if (unlikely(no_more_sg)) {
|
|
|
|
|
|
+ sg = qc->cursg;
|
|
|
|
+ if (unlikely(!sg)) {
|
|
/*
|
|
/*
|
|
* The end of qc->sg is reached and the device expects
|
|
* The end of qc->sg is reached and the device expects
|
|
* more data to transfer. In order not to overrun qc->sg
|
|
* more data to transfer. In order not to overrun qc->sg
|
|
@@ -5164,21 +5198,28 @@ next_sg:
|
|
* - for write case, padding zero data to the device
|
|
* - for write case, padding zero data to the device
|
|
*/
|
|
*/
|
|
u16 pad_buf[1] = { 0 };
|
|
u16 pad_buf[1] = { 0 };
|
|
- unsigned int words = bytes >> 1;
|
|
|
|
unsigned int i;
|
|
unsigned int i;
|
|
|
|
|
|
- if (words) /* warning if bytes > 1 */
|
|
|
|
- ata_dev_printk(qc->dev, KERN_WARNING,
|
|
|
|
- "%u bytes trailing data\n", bytes);
|
|
|
|
|
|
+ if (bytes > qc->curbytes - qc->nbytes + ATAPI_MAX_DRAIN) {
|
|
|
|
+ ata_ehi_push_desc(ehi, "too much trailing data "
|
|
|
|
+ "buf=%u cur=%u bytes=%u",
|
|
|
|
+ qc->nbytes, qc->curbytes, bytes);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* overflow is exptected for misc ATAPI commands */
|
|
|
|
+ if (bytes && !atapi_qc_may_overflow(qc))
|
|
|
|
+ ata_dev_printk(qc->dev, KERN_WARNING, "ATAPI %u bytes "
|
|
|
|
+ "trailing data (cdb=%02x nbytes=%u)\n",
|
|
|
|
+ bytes, qc->cdb[0], qc->nbytes);
|
|
|
|
|
|
- for (i = 0; i < words; i++)
|
|
|
|
|
|
+ for (i = 0; i < (bytes + 1) / 2; i++)
|
|
ap->ops->data_xfer(qc->dev, (unsigned char *)pad_buf, 2, do_write);
|
|
ap->ops->data_xfer(qc->dev, (unsigned char *)pad_buf, 2, do_write);
|
|
|
|
|
|
- ap->hsm_task_state = HSM_ST_LAST;
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ qc->curbytes += bytes;
|
|
|
|
|
|
- sg = qc->cursg;
|
|
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
page = sg_page(sg);
|
|
page = sg_page(sg);
|
|
offset = sg->offset + qc->cursg_ofs;
|
|
offset = sg->offset + qc->cursg_ofs;
|
|
@@ -5213,19 +5254,20 @@ next_sg:
|
|
}
|
|
}
|
|
|
|
|
|
bytes -= count;
|
|
bytes -= count;
|
|
|
|
+ if ((count & 1) && bytes)
|
|
|
|
+ bytes--;
|
|
qc->curbytes += count;
|
|
qc->curbytes += count;
|
|
qc->cursg_ofs += count;
|
|
qc->cursg_ofs += count;
|
|
|
|
|
|
if (qc->cursg_ofs == sg->length) {
|
|
if (qc->cursg_ofs == sg->length) {
|
|
- if (qc->cursg == lsg)
|
|
|
|
- no_more_sg = 1;
|
|
|
|
-
|
|
|
|
qc->cursg = sg_next(qc->cursg);
|
|
qc->cursg = sg_next(qc->cursg);
|
|
qc->cursg_ofs = 0;
|
|
qc->cursg_ofs = 0;
|
|
}
|
|
}
|
|
|
|
|
|
if (bytes)
|
|
if (bytes)
|
|
goto next_sg;
|
|
goto next_sg;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -5268,7 +5310,8 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
|
|
|
|
|
|
VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
|
|
VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
|
|
|
|
|
|
- __atapi_pio_bytes(qc, bytes);
|
|
|
|
|
|
+ if (__atapi_pio_bytes(qc, bytes))
|
|
|
|
+ goto err_out;
|
|
ata_altstatus(ap); /* flush */
|
|
ata_altstatus(ap); /* flush */
|
|
|
|
|
|
return;
|
|
return;
|