From: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> Date: Thu, 10 Jan 2008 11:42:50 -0600 Subject: libata: implement drain buffers This just updates the libata slave configure routine to take advantage of the block layer drain buffers. I suspect I should also be checking for AHCI as well as ATA_DEV_ATAPI, but I couldn't see how to do that easily. Signed-off-by: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> --- drivers/ata/libata-scsi.c | 26 ++++++++++++++++++++++---- 1 files changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8ffff44..a28351c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -826,8 +826,8 @@ 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) +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); @@ -839,6 +839,16 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, sdev->manage_start_stop = 1; } + if (dev->class == ATA_DEV_ATAPI) { + struct request_queue *q = sdev->request_queue; + void *buf = kmalloc(ATAPI_MAX_DRAIN, GFP_KERNEL); + if (!buf) { + sdev_printk(KERN_ERR, sdev, "drain buffer allocation failed\n"); + return -ENOMEM; + } + blk_queue_dma_drain(q, buf, ATAPI_MAX_DRAIN); + } + if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); @@ -849,6 +859,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; } /** @@ -867,13 +879,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; } /** @@ -895,6 +908,7 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) struct ata_port *ap = ata_shost_to_port(sdev->host); unsigned long flags; struct ata_device *dev; + struct request_queue *q = sdev->request_queue; if (!ap->ops->error_handler) return; @@ -908,6 +922,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; } /** -- 1.5.3.8 - To unsubscribe from this list: 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