aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libata-core.c1
-rw-r--r--drivers/scsi/libata-eh.c3
-rw-r--r--drivers/scsi/libata-scsi.c36
-rw-r--r--drivers/scsi/libata.h1
-rw-r--r--include/linux/ata.h3
5 files changed, 44 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 51b3a0ddb238..ddaad1a4f1f1 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5194,6 +5194,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
5194 5194
5195 INIT_WORK(&ap->port_task, NULL, NULL); 5195 INIT_WORK(&ap->port_task, NULL, NULL);
5196 INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); 5196 INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap);
5197 INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap);
5197 INIT_LIST_HEAD(&ap->eh_done_q); 5198 INIT_LIST_HEAD(&ap->eh_done_q);
5198 init_waitqueue_head(&ap->eh_wait_q); 5199 init_waitqueue_head(&ap->eh_wait_q);
5199 5200
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 6285257a890d..f82799e22588 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -1554,6 +1554,9 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
1554 if (rc) 1554 if (rc)
1555 break; 1555 break;
1556 1556
1557 /* schedule the scsi_rescan_device() here */
1558 queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
1559
1557 ehc->i.action &= ~ATA_EH_REVALIDATE; 1560 ehc->i.action &= ~ATA_EH_REVALIDATE;
1558 } else if (dev->class == ATA_DEV_UNKNOWN && 1561 } else if (dev->class == ATA_DEV_UNKNOWN &&
1559 ehc->tries[dev->devno] && 1562 ehc->tries[dev->devno] &&
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 5f90d8e33546..45a49be65042 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1306,6 +1306,17 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
1306 u8 *cdb = cmd->cmnd; 1306 u8 *cdb = cmd->cmnd;
1307 int need_sense = (qc->err_mask != 0); 1307 int need_sense = (qc->err_mask != 0);
1308 1308
1309 /* We snoop the SET_FEATURES - Write Cache ON/OFF command, and
1310 * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
1311 * cache
1312 */
1313 if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
1314 ((qc->tf.feature == SETFEATURES_WC_ON) ||
1315 (qc->tf.feature == SETFEATURES_WC_OFF))) {
1316 qc->ap->eh_info.action |= ATA_EH_REVALIDATE;
1317 ata_port_schedule_eh(qc->ap);
1318 }
1319
1309 /* For ATA pass thru (SAT) commands, generate a sense block if 1320 /* For ATA pass thru (SAT) commands, generate a sense block if
1310 * user mandated it or if there's an error. Note that if we 1321 * user mandated it or if there's an error. Note that if we
1311 * generate because the user forced us to, a check condition 1322 * generate because the user forced us to, a check condition
@@ -2992,3 +3003,28 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
2992 3003
2993 return rc; 3004 return rc;
2994} 3005}
3006
3007/**
3008 * ata_scsi_dev_rescan - initiate scsi_rescan_device()
3009 * @data: Pointer to ATA port to perform scsi_rescan_device()
3010 *
3011 * After ATA pass thru (SAT) commands are executed successfully,
3012 * libata need to propagate the changes to SCSI layer.
3013 *
3014 * LOCKING:
3015 * Kernel thread context (may sleep).
3016 */
3017void ata_scsi_dev_rescan(void *data)
3018{
3019 struct ata_port *ap = data;
3020 struct ata_device *dev;
3021 unsigned int i;
3022
3023 for (i = 0; i < ATA_MAX_DEVICES; i++) {
3024 dev = &ap->device[i];
3025
3026 if (ata_dev_enabled(dev))
3027 scsi_rescan_device(&(dev->sdev->sdev_gendev));
3028 }
3029}
3030
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 1dd496f1f7ac..bdd488897096 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -104,6 +104,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
104 unsigned int (*actor) (struct ata_scsi_args *args, 104 unsigned int (*actor) (struct ata_scsi_args *args,
105 u8 *rbuf, unsigned int buflen)); 105 u8 *rbuf, unsigned int buflen));
106extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); 106extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
107extern void ata_scsi_dev_rescan(void *data);
107 108
108/* libata-eh.c */ 109/* libata-eh.c */
109extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); 110extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
diff --git a/include/linux/ata.h b/include/linux/ata.h
index c494e1c0531e..3671af869696 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -181,6 +181,9 @@ enum {
181 XFER_PIO_0 = 0x08, 181 XFER_PIO_0 = 0x08,
182 XFER_PIO_SLOW = 0x00, 182 XFER_PIO_SLOW = 0x00,
183 183
184 SETFEATURES_WC_ON = 0x02, /* Enable write cache */
185 SETFEATURES_WC_OFF = 0x82, /* Disable write cache */
186
184 /* ATAPI stuff */ 187 /* ATAPI stuff */
185 ATAPI_PKT_DMA = (1 << 0), 188 ATAPI_PKT_DMA = (1 << 0),
186 ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: 189 ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: