Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 85893
b: refs/heads/master
c: fa2fc7f
h: refs/heads/master
i:
  85891: c912a63
v: v3
  • Loading branch information
James Bottomley authored and Jens Axboe committed Feb 19, 2008
1 parent b583b8a commit 64fd45e
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 59 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: dde2020754aeb14e17052d61784dcb37f252aac2
refs/heads/master: fa2fc7f4813bfec1ae3232d49e3befbd601e8a6f
56 changes: 4 additions & 52 deletions trunk/drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4641,28 +4641,6 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
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)
{
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);
}

/**
* ata_std_qc_defer - Check whether a qc needs to be deferred
* @qc: ATA command in question
Expand Down Expand Up @@ -5026,36 +5004,10 @@ static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
next_sg:
sg = qc->cursg;
if (unlikely(!sg)) {
/*
* The end of qc->sg is reached and the device expects
* more data to transfer. In order not to overrun qc->sg
* and fulfill length specified in the byte count register,
* - for read case, discard trailing data from the device
* - for write case, padding zero data to the device
*/
u16 pad_buf[1] = { 0 };

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;
}

/* 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;
}

consumed = 0;
while (consumed < bytes)
consumed += ap->ops->data_xfer(dev,
(unsigned char *)pad_buf, 2, rw);

qc->curbytes += bytes;
return 0;
ata_ehi_push_desc(ehi, "unexpected or too much trailing data "
"buf=%u cur=%u bytes=%u",
qc->nbytes, qc->curbytes, bytes);
return -1;
}

page = sg_page(sg);
Expand Down
59 changes: 53 additions & 6 deletions trunk/drivers/ata/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -826,17 +826,56 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
sdev->max_device_blocked = 1;
}

static void ata_scsi_dev_config(struct scsi_device *sdev,
struct ata_device *dev)
/**
* atapi_drain_needed - Check whether data transfer may overflow
* @request: request to be checked
*
* 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 @request.
*
* LOCKING:
* None.
*
* RETURNS:
* 1 if ; otherwise, 0.
*/
static int atapi_drain_needed(struct request *rq)
{
if (likely(!blk_pc_request(rq)))
return 0;

if (!rq->data_len || (rq->cmd_flags & REQ_RW))
return 0;

return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC;
}

static int ata_scsi_dev_config(struct scsi_device *sdev,
struct ata_device *dev)
{
/* configure max sectors */
blk_queue_max_sectors(sdev->request_queue, dev->max_sectors);

if (dev->class == ATA_DEV_ATAPI)
if (dev->class == ATA_DEV_ATAPI) {
struct request_queue *q = sdev->request_queue;
void *buf;

/* set the min alignment */
blk_queue_update_dma_alignment(sdev->request_queue,
ATA_DMA_PAD_SZ - 1);
else {

/* configure draining */
buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL);
if (!buf) {
ata_dev_printk(dev, KERN_ERR,
"drain buffer allocation failed\n");
return -ENOMEM;
}

blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
} else {
/* ATA devices must be sector aligned */
blk_queue_update_dma_alignment(sdev->request_queue,
ATA_SECT_SIZE - 1);
Expand All @@ -853,6 +892,8 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
depth = min(ATA_MAX_QUEUE - 1, depth);
scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
}

return 0;
}

/**
Expand All @@ -871,13 +912,14 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
int rc = 0;

ata_scsi_sdev_config(sdev);

if (dev)
ata_scsi_dev_config(sdev, dev);
rc = ata_scsi_dev_config(sdev, dev);

return 0;
return rc;
}

/**
Expand All @@ -897,6 +939,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
void ata_scsi_slave_destroy(struct scsi_device *sdev)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
struct request_queue *q = sdev->request_queue;
unsigned long flags;
struct ata_device *dev;

Expand All @@ -912,6 +955,10 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
ata_port_schedule_eh(ap);
}
spin_unlock_irqrestore(ap->lock, flags);

kfree(q->dma_drain_buffer);
q->dma_drain_buffer = NULL;
q->dma_drain_size = 0;
}

/**
Expand Down

0 comments on commit 64fd45e

Please sign in to comment.