diff options
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r-- | drivers/ata/libata-scsi.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6e15c5ddae6d..dd41b1a1b304 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -826,17 +826,56 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) | |||
826 | sdev->max_device_blocked = 1; | 826 | sdev->max_device_blocked = 1; |
827 | } | 827 | } |
828 | 828 | ||
829 | static void ata_scsi_dev_config(struct scsi_device *sdev, | 829 | /** |
830 | struct ata_device *dev) | 830 | * atapi_drain_needed - Check whether data transfer may overflow |
831 | * @request: request to be checked | ||
832 | * | ||
833 | * ATAPI commands which transfer variable length data to host | ||
834 | * might overflow due to application error or hardare bug. This | ||
835 | * function checks whether overflow should be drained and ignored | ||
836 | * for @request. | ||
837 | * | ||
838 | * LOCKING: | ||
839 | * None. | ||
840 | * | ||
841 | * RETURNS: | ||
842 | * 1 if ; otherwise, 0. | ||
843 | */ | ||
844 | static int atapi_drain_needed(struct request *rq) | ||
845 | { | ||
846 | if (likely(!blk_pc_request(rq))) | ||
847 | return 0; | ||
848 | |||
849 | if (!rq->data_len || (rq->cmd_flags & REQ_RW)) | ||
850 | return 0; | ||
851 | |||
852 | return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC; | ||
853 | } | ||
854 | |||
855 | static int ata_scsi_dev_config(struct scsi_device *sdev, | ||
856 | struct ata_device *dev) | ||
831 | { | 857 | { |
832 | /* configure max sectors */ | 858 | /* configure max sectors */ |
833 | blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); | 859 | blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); |
834 | 860 | ||
835 | if (dev->class == ATA_DEV_ATAPI) | 861 | if (dev->class == ATA_DEV_ATAPI) { |
862 | struct request_queue *q = sdev->request_queue; | ||
863 | void *buf; | ||
864 | |||
836 | /* set the min alignment */ | 865 | /* set the min alignment */ |
837 | blk_queue_update_dma_alignment(sdev->request_queue, | 866 | blk_queue_update_dma_alignment(sdev->request_queue, |
838 | ATA_DMA_PAD_SZ - 1); | 867 | ATA_DMA_PAD_SZ - 1); |
839 | else { | 868 | |
869 | /* configure draining */ | ||
870 | buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL); | ||
871 | if (!buf) { | ||
872 | ata_dev_printk(dev, KERN_ERR, | ||
873 | "drain buffer allocation failed\n"); | ||
874 | return -ENOMEM; | ||
875 | } | ||
876 | |||
877 | blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); | ||
878 | } else { | ||
840 | /* ATA devices must be sector aligned */ | 879 | /* ATA devices must be sector aligned */ |
841 | blk_queue_update_dma_alignment(sdev->request_queue, | 880 | blk_queue_update_dma_alignment(sdev->request_queue, |
842 | ATA_SECT_SIZE - 1); | 881 | ATA_SECT_SIZE - 1); |
@@ -853,6 +892,8 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, | |||
853 | depth = min(ATA_MAX_QUEUE - 1, depth); | 892 | depth = min(ATA_MAX_QUEUE - 1, depth); |
854 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); | 893 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); |
855 | } | 894 | } |
895 | |||
896 | return 0; | ||
856 | } | 897 | } |
857 | 898 | ||
858 | /** | 899 | /** |
@@ -871,13 +912,14 @@ int ata_scsi_slave_config(struct scsi_device *sdev) | |||
871 | { | 912 | { |
872 | struct ata_port *ap = ata_shost_to_port(sdev->host); | 913 | struct ata_port *ap = ata_shost_to_port(sdev->host); |
873 | struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); | 914 | struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); |
915 | int rc = 0; | ||
874 | 916 | ||
875 | ata_scsi_sdev_config(sdev); | 917 | ata_scsi_sdev_config(sdev); |
876 | 918 | ||
877 | if (dev) | 919 | if (dev) |
878 | ata_scsi_dev_config(sdev, dev); | 920 | rc = ata_scsi_dev_config(sdev, dev); |
879 | 921 | ||
880 | return 0; | 922 | return rc; |
881 | } | 923 | } |
882 | 924 | ||
883 | /** | 925 | /** |
@@ -897,6 +939,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev) | |||
897 | void ata_scsi_slave_destroy(struct scsi_device *sdev) | 939 | void ata_scsi_slave_destroy(struct scsi_device *sdev) |
898 | { | 940 | { |
899 | struct ata_port *ap = ata_shost_to_port(sdev->host); | 941 | struct ata_port *ap = ata_shost_to_port(sdev->host); |
942 | struct request_queue *q = sdev->request_queue; | ||
900 | unsigned long flags; | 943 | unsigned long flags; |
901 | struct ata_device *dev; | 944 | struct ata_device *dev; |
902 | 945 | ||
@@ -912,6 +955,10 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) | |||
912 | ata_port_schedule_eh(ap); | 955 | ata_port_schedule_eh(ap); |
913 | } | 956 | } |
914 | spin_unlock_irqrestore(ap->lock, flags); | 957 | spin_unlock_irqrestore(ap->lock, flags); |
958 | |||
959 | kfree(q->dma_drain_buffer); | ||
960 | q->dma_drain_buffer = NULL; | ||
961 | q->dma_drain_size = 0; | ||
915 | } | 962 | } |
916 | 963 | ||
917 | /** | 964 | /** |