+static int sd_sync_cache(struct scsi_device *sdp)
+{
+ struct scsi_request *sreq;
+ int retries, res;
+
+ if (!scsi_device_online(sdp))
+ return -ENODEV;
+
+ sreq = scsi_allocate_request(sdp, GFP_KERNEL);
+ if (!sreq) {
+ printk("FAILED\n No memory for request\n");
+ return -ENOMEM;
+ }
+
+ sreq->sr_data_direction = DMA_NONE;
+ for (retries = 3; retries > 0; --retries) {
+ unsigned char cmd[10] = { 0 };
+
+ cmd[0] = SYNCHRONIZE_CACHE;
+ /*
+ * Leave the rest of the command zero to indicate
+ * flush everything.
+ */
+ scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
+ if (sreq->sr_result == 0)
+ break;
+ }
+
+ res = sreq->sr_result;
+ if (res) {
+ printk(KERN_WARNING "FAILED\n status = %x, message = %02x, "
+ "host = %d, driver = %02x\n ",
+ status_byte(res), msg_byte(res),
+ host_byte(res), driver_byte(res));
+ if (driver_byte(res) & DRIVER_SENSE)
+ scsi_print_req_sense("sd", sreq);
+ }
+
+ scsi_release_request(sreq);
+ return res;
+}
+
+static int sd_issue_flush(struct device *dev, sector_t *error_sector)
+{
+ struct scsi_device *sdp = to_scsi_device(dev);
+ struct scsi_disk *sdkp = dev_get_drvdata(dev);
+
+ if (!sdkp)
+ return -ENODEV;
+
+ if (!sdkp->WCE)
+ return 0;
+
+ return sd_sync_cache(sdp);
+}
+