diff options
author | zhao, forrest <forrest.zhao@intel.com> | 2006-06-12 00:01:34 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-06-12 00:18:35 -0400 |
commit | 3057ac3c1a992ee135cbb7b7d1a12e58d81f0739 (patch) | |
tree | 38d83a88ee949b9db8f6655f90f98d88f8a5f2fd /drivers/scsi | |
parent | 39b07ce6d9f7cd4da8567baed844801e0aaa7b1a (diff) |
[PATCH] Snoop SET FEATURES - WRITE CACHE ENABLE/DISABLE command(v5)
This patch makes libata snoop 'SET FEATURES - WRITE CACHE
ENABLE/DISABLE' command, executing requisite revalidation processes
to update cached data.
Signed-off-by: Forrest Zhao <forrest.zhao@intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libata-core.c | 1 | ||||
-rw-r--r-- | drivers/scsi/libata-eh.c | 3 | ||||
-rw-r--r-- | drivers/scsi/libata-scsi.c | 36 | ||||
-rw-r--r-- | drivers/scsi/libata.h | 1 |
4 files changed, 41 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 | */ | ||
3017 | void 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)); |
106 | extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); | 106 | extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); |
107 | extern void ata_scsi_dev_rescan(void *data); | ||
107 | 108 | ||
108 | /* libata-eh.c */ | 109 | /* libata-eh.c */ |
109 | extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); | 110 | extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); |