diff options
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ab6b53349d6f..b007bb409382 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -151,7 +151,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
151 | struct scsi_sense_hdr sshdr; | 151 | struct scsi_sense_hdr sshdr; |
152 | enum dma_data_direction data_dir; | 152 | enum dma_data_direction data_dir; |
153 | 153 | ||
154 | if (NULL == (void *)arg) | 154 | if (arg == NULL) |
155 | return -EINVAL; | 155 | return -EINVAL; |
156 | 156 | ||
157 | if (copy_from_user(args, arg, sizeof(args))) | 157 | if (copy_from_user(args, arg, sizeof(args))) |
@@ -201,7 +201,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
201 | /* Need code to retrieve data from check condition? */ | 201 | /* Need code to retrieve data from check condition? */ |
202 | 202 | ||
203 | if ((argbuf) | 203 | if ((argbuf) |
204 | && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize)) | 204 | && copy_to_user(arg + sizeof(args), argbuf, argsize)) |
205 | rc = -EFAULT; | 205 | rc = -EFAULT; |
206 | error: | 206 | error: |
207 | if (argbuf) | 207 | if (argbuf) |
@@ -228,7 +228,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
228 | u8 args[7]; | 228 | u8 args[7]; |
229 | struct scsi_sense_hdr sshdr; | 229 | struct scsi_sense_hdr sshdr; |
230 | 230 | ||
231 | if (NULL == (void *)arg) | 231 | if (arg == NULL) |
232 | return -EINVAL; | 232 | return -EINVAL; |
233 | 233 | ||
234 | if (copy_from_user(args, arg, sizeof(args))) | 234 | if (copy_from_user(args, arg, sizeof(args))) |
@@ -732,16 +732,27 @@ int ata_scsi_slave_config(struct scsi_device *sdev) | |||
732 | int ata_scsi_error(struct Scsi_Host *host) | 732 | int ata_scsi_error(struct Scsi_Host *host) |
733 | { | 733 | { |
734 | struct ata_port *ap; | 734 | struct ata_port *ap; |
735 | unsigned long flags; | ||
735 | 736 | ||
736 | DPRINTK("ENTER\n"); | 737 | DPRINTK("ENTER\n"); |
737 | 738 | ||
738 | ap = (struct ata_port *) &host->hostdata[0]; | 739 | ap = (struct ata_port *) &host->hostdata[0]; |
740 | |||
741 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
742 | assert(!(ap->flags & ATA_FLAG_IN_EH)); | ||
743 | ap->flags |= ATA_FLAG_IN_EH; | ||
744 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
745 | |||
739 | ap->ops->eng_timeout(ap); | 746 | ap->ops->eng_timeout(ap); |
740 | 747 | ||
741 | assert(host->host_failed == 0 && list_empty(&host->eh_cmd_q)); | 748 | assert(host->host_failed == 0 && list_empty(&host->eh_cmd_q)); |
742 | 749 | ||
743 | scsi_eh_flush_done_q(&ap->eh_done_q); | 750 | scsi_eh_flush_done_q(&ap->eh_done_q); |
744 | 751 | ||
752 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
753 | ap->flags &= ~ATA_FLAG_IN_EH; | ||
754 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
755 | |||
745 | DPRINTK("EXIT\n"); | 756 | DPRINTK("EXIT\n"); |
746 | return 0; | 757 | return 0; |
747 | } | 758 | } |
@@ -1742,6 +1753,31 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) | |||
1742 | return sizeof(def_rw_recovery_mpage); | 1753 | return sizeof(def_rw_recovery_mpage); |
1743 | } | 1754 | } |
1744 | 1755 | ||
1756 | /* | ||
1757 | * We can turn this into a real blacklist if it's needed, for now just | ||
1758 | * blacklist any Maxtor BANC1G10 revision firmware | ||
1759 | */ | ||
1760 | static int ata_dev_supports_fua(u16 *id) | ||
1761 | { | ||
1762 | unsigned char model[41], fw[9]; | ||
1763 | |||
1764 | if (!ata_id_has_fua(id)) | ||
1765 | return 0; | ||
1766 | |||
1767 | model[40] = '\0'; | ||
1768 | fw[8] = '\0'; | ||
1769 | |||
1770 | ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1); | ||
1771 | ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1); | ||
1772 | |||
1773 | if (strncmp(model, "Maxtor", 6)) | ||
1774 | return 1; | ||
1775 | if (strncmp(fw, "BANC1G10", 8)) | ||
1776 | return 1; | ||
1777 | |||
1778 | return 0; /* blacklisted */ | ||
1779 | } | ||
1780 | |||
1745 | /** | 1781 | /** |
1746 | * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands | 1782 | * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands |
1747 | * @args: device IDENTIFY data / SCSI command of interest. | 1783 | * @args: device IDENTIFY data / SCSI command of interest. |
@@ -1839,7 +1875,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
1839 | return 0; | 1875 | return 0; |
1840 | 1876 | ||
1841 | dpofua = 0; | 1877 | dpofua = 0; |
1842 | if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && | 1878 | if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && |
1843 | (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) | 1879 | (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) |
1844 | dpofua = 1 << 4; | 1880 | dpofua = 1 << 4; |
1845 | 1881 | ||
@@ -2533,7 +2569,8 @@ out_unlock: | |||
2533 | 2569 | ||
2534 | /** | 2570 | /** |
2535 | * ata_scsi_simulate - simulate SCSI command on ATA device | 2571 | * ata_scsi_simulate - simulate SCSI command on ATA device |
2536 | * @id: current IDENTIFY data for target device. | 2572 | * @ap: port the device is connected to |
2573 | * @dev: the target device | ||
2537 | * @cmd: SCSI command being sent to device. | 2574 | * @cmd: SCSI command being sent to device. |
2538 | * @done: SCSI command completion function. | 2575 | * @done: SCSI command completion function. |
2539 | * | 2576 | * |