Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 85887
b: refs/heads/master
c: 56c819d
h: refs/heads/master
i:
  85885: 1427bde
  85883: 44cee89
  85879: fd38390
  85871: 87d3e1c
  85855: 4078436
  85823: fe80c8b
  85759: 71053cf
v: v3
  • Loading branch information
Tejun Heo authored and Jens Axboe committed Feb 19, 2008
1 parent efadcbc commit 7b88cee
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 44 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e164094964e6e20fe7fce418e06a9dce952bb7a4
refs/heads/master: 56c819df77f96c3fc0c2a979e12b478403728790
76 changes: 33 additions & 43 deletions trunk/drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4675,24 +4675,9 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
*/
static int atapi_qc_may_overflow(struct ata_queued_cmd *qc)
{
if (qc->tf.protocol != ATAPI_PROT_PIO &&
qc->tf.protocol != ATAPI_PROT_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;
return ata_is_atapi(qc->tf.protocol) && ata_is_data(qc->tf.protocol) &&
atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC &&
!(qc->tf.flags & ATA_TFLAG_WRITE);
}

/**
Expand Down Expand Up @@ -5146,13 +5131,14 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
*/
static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
{
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
int rw = (qc->tf.flags & ATA_TFLAG_WRITE) ? WRITE : READ;
struct ata_port *ap = qc->ap;
struct ata_eh_info *ehi = &qc->dev->link->eh_info;
struct ata_device *dev = qc->dev;
struct ata_eh_info *ehi = &dev->link->eh_info;
struct scatterlist *sg;
struct page *page;
unsigned char *buf;
unsigned int offset, count;
unsigned int offset, count, consumed;

next_sg:
sg = qc->cursg;
Expand All @@ -5165,26 +5151,27 @@ static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
* - for write case, padding zero data to the device
*/
u16 pad_buf[1] = { 0 };
unsigned int i;

if (bytes > qc->curbytes - qc->nbytes + ATAPI_MAX_DRAIN) {
if (qc->curbytes + bytes > 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);
/* allow overflow only for misc ATAPI commands */
if (!atapi_qc_may_overflow(qc)) {
ata_ehi_push_desc(ehi, "unexpected trailing data "
"%u bytes", bytes);
return -1;
}

for (i = 0; i < (bytes + 1) / 2; i++)
ap->ops->data_xfer(qc->dev, (unsigned char *)pad_buf, 2, do_write);
consumed = 0;
while (consumed < bytes)
consumed += ap->ops->data_xfer(dev,
(unsigned char *)pad_buf, 2, rw);

qc->curbytes += bytes;

return 0;
}

Expand All @@ -5211,18 +5198,16 @@ static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
buf = kmap_atomic(page, KM_IRQ0);

/* do the actual data transfer */
ap->ops->data_xfer(qc->dev, buf + offset, count, do_write);
consumed = ap->ops->data_xfer(dev, buf + offset, count, rw);

kunmap_atomic(buf, KM_IRQ0);
local_irq_restore(flags);
} else {
buf = page_address(page);
ap->ops->data_xfer(qc->dev, buf + offset, count, do_write);
consumed = ap->ops->data_xfer(dev, buf + offset, count, rw);
}

bytes -= count;
if ((count & 1) && bytes)
bytes--;
bytes -= min(bytes, consumed);
qc->curbytes += count;
qc->cursg_ofs += count;

Expand All @@ -5231,9 +5216,11 @@ static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
qc->cursg_ofs = 0;
}

/* consumed can be larger than count only for the last transfer */
WARN_ON(qc->cursg && count != consumed);

if (bytes)
goto next_sg;

return 0;
}

Expand All @@ -5251,6 +5238,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_device *dev = qc->dev;
struct ata_eh_info *ehi = &dev->link->eh_info;
unsigned int ireason, bc_lo, bc_hi, bytes;
int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;

Expand All @@ -5268,26 +5256,28 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)

/* shall be cleared to zero, indicating xfer of data */
if (unlikely(ireason & (1 << 0)))
goto err_out;
goto atapi_check;

/* make sure transfer direction matches expected */
i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
if (unlikely(do_write != i_write))
goto err_out;
goto atapi_check;

if (unlikely(!bytes))
goto err_out;
goto atapi_check;

VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);

if (__atapi_pio_bytes(qc, bytes))
if (unlikely(__atapi_pio_bytes(qc, bytes)))
goto err_out;
ata_altstatus(ap); /* flush */

return;

err_out:
ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n");
atapi_check:
ata_ehi_push_desc(ehi, "ATAPI check failed (ireason=0x%x bytes=%u)",
ireason, bytes);
err_out:
qc->err_mask |= AC_ERR_HSM;
ap->hsm_task_state = HSM_ST_ERR;
}
Expand Down

0 comments on commit 7b88cee

Please sign in to comment.