Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 97981 Details for
Bug 148423
app-laptop/hdapsd kernel patch doesn't apply to 2.6.18
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
hdaps_protect-2.6.18.patch
hdaps_protect-2.6.18.patch (text/plain), 21.46 KB, created by
Ed Catmur
on 2006-09-24 14:55:20 UTC
(
hide
)
Description:
hdaps_protect-2.6.18.patch
Filename:
MIME Type:
Creator:
Ed Catmur
Created:
2006-09-24 14:55:20 UTC
Size:
21.46 KB
patch
obsolete
>diff -Nur linux-2.6.17.1/block/ll_rw_blk.c linux-2.6.17.1.hdaps/block/ll_rw_blk.c >--- linux-2.6.17.1/block/ll_rw_blk.c 2006-06-24 23:49:02.169654000 +0200 >+++ linux-2.6.17.1.hdaps/block/ll_rw_blk.c 2006-06-25 00:27:27.281715250 +0200 >@@ -39,6 +39,8 @@ > static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); > static void init_request_from_bio(struct request *req, struct bio *bio); > static int __make_request(request_queue_t *q, struct bio *bio); >+static int blk_protect_register(request_queue_t *q); >+static void blk_protect_unregister(request_queue_t *q); > > /* > * For the allocated request tables >@@ -359,6 +361,18 @@ > > EXPORT_SYMBOL(blk_queue_issue_flush_fn); > >+void blk_queue_issue_protect_fn(request_queue_t *q, issue_protect_fn *ipf) >+{ >+ q->issue_protect_fn = ipf; >+} >+EXPORT_SYMBOL(blk_queue_issue_protect_fn); >+ >+void blk_queue_issue_unprotect_fn(request_queue_t *q, issue_unprotect_fn *iuf) >+{ >+ q->issue_unprotect_fn = iuf; >+} >+EXPORT_SYMBOL(blk_queue_issue_unprotect_fn); >+ > /* > * Cache flushing for ordered writes handling > */ >@@ -3928,6 +3942,7 @@ > return ret; > } > >+ blk_protect_register(q); > return 0; > } > >@@ -3936,6 +3951,7 @@ > request_queue_t *q = disk->queue; > > if (q && q->request_fn) { >+ blk_protect_unregister(q); > elv_unregister_queue(q); > > kobject_uevent(&q->kobj, KOBJ_REMOVE); >@@ -3943,3 +3959,112 @@ > kobject_put(&disk->kobj); > } > } >+ >+/* >+ * Restore the unplugging timer that we re-used >+ * to implement the queue freeze timeout... >+ */ >+static void blk_unfreeze_work(void *data) >+{ >+ request_queue_t *q = (request_queue_t *) data; >+ >+ INIT_WORK(&q->unplug_work, blk_unplug_work, q); >+ q->unplug_timer.function = blk_unplug_timeout; >+ >+ q->issue_unprotect_fn(q); >+} >+ >+/* >+ * Called when the queue freeze timeout expires... >+ */ >+static void blk_unfreeze_timeout(unsigned long data) >+{ >+ request_queue_t *q = (request_queue_t *) data; >+ kblockd_schedule_work(&q->unplug_work); >+} >+ >+/* >+ * The lower level driver parks and freezes the queue, and this block layer >+ * function sets up the freeze timeout timer on return. If the queue is >+ * already frozen then this is called to extend the timer... >+ */ >+void blk_freeze_queue(request_queue_t *q, int seconds) >+{ >+ /* set/reset the timer */ >+ mod_timer(&q->unplug_timer, msecs_to_jiffies(seconds*1000) + jiffies); >+ >+ /* we do this every iteration - is this sane? */ >+ INIT_WORK(&q->unplug_work, blk_unfreeze_work, q); >+ q->unplug_timer.function = blk_unfreeze_timeout; >+} >+ >+/* >+ * When reading the 'protect' attribute, we return boolean frozen or active >+ * todo: >+ * - maybe we should return seconds remaining instead? >+ */ >+static ssize_t queue_protect_show(struct request_queue *q, char *page) >+{ >+ return queue_var_show(blk_queue_stopped(q), (page)); >+} >+ >+/* >+ * When writing the 'protect' attribute, input is the number of seconds >+ * to freeze the queue for. We call a lower level helper function to >+ * park the heads and freeze/block the queue, then we make a block layer >+ * call to setup the thaw timeout. If input is 0, then we thaw the queue. >+ */ >+static ssize_t queue_protect_store(struct request_queue *q, const char *page, size_t count) >+{ >+ unsigned long freeze = 0; >+ queue_var_store(&freeze, page, count); >+ >+ if(freeze>0) { >+/* Park and freeze */ >+ if (!blk_queue_stopped(q)) >+ q->issue_protect_fn(q); >+/* set / reset the thaw timer */ >+ blk_freeze_queue(q, freeze); >+ } >+ else >+ blk_unfreeze_timeout((unsigned long) q); >+ >+ return count; >+} >+ >+static struct queue_sysfs_entry queue_protect_entry = { >+ .attr = {.name = "protect", .mode = S_IRUGO | S_IWUSR }, >+ .show = queue_protect_show, >+ .store = queue_protect_store, >+}; >+ >+static int blk_protect_register(request_queue_t *q) >+{ >+ int error = 0; >+ >+/* check that the lower level driver has a protect handler */ >+ if (!q->issue_protect_fn) >+ return 1; >+ >+/* create the attribute */ >+ error = sysfs_create_file(&q->kobj, &queue_protect_entry.attr); >+ if(error){ >+ printk(KERN_ERR >+ "blk_protect_register(): failed to create protect queue attribute!\n"); >+ return error; >+ } >+ >+ kobject_get(&q->kobj); >+ return 0; >+} >+ >+static void blk_protect_unregister(request_queue_t *q) >+{ >+/* check that the lower level driver has a protect handler */ >+ if (!q->issue_protect_fn) >+ return; >+ >+/* remove the attribute */ >+ sysfs_remove_file(&q->kobj,&queue_protect_entry.attr); >+ kobject_put(&q->kobj); >+} >diff -Nur linux-2.6.17.1/drivers/ide/ide-disk.c linux-2.6.17.1.hdaps/drivers/ide/ide-disk.c >--- linux-2.6.17.1/drivers/ide/ide-disk.c 2006-06-24 23:49:02.181655000 +0200 >+++ linux-2.6.17.1.hdaps/drivers/ide/ide-disk.c 2006-06-25 00:46:09.647858750 +0200 >@@ -72,6 +72,10 @@ > #include <asm/io.h> > #include <asm/div64.h> > >+int idedisk_protect_method = 0; >+module_param_named(protect_method, idedisk_protect_method, int, 0444); >+MODULE_PARM_DESC(protect_method, "hdaps disk protection method (0=autodetect, 1=unload, 2=standby)"); >+ > struct ide_disk_obj { > ide_drive_t *drive; > ide_driver_t *driver; >@@ -730,6 +734,154 @@ > } > > /* >+ * todo: >+ * - we freeze the queue regardless of success and rely on the >+ * ide_protect_queue function to thaw immediately if the command >+ * failed (to be consistent with the libata handler)... should >+ * we also inspect here? >+ */ >+void ide_end_protect_rq(struct request *rq, int error) >+{ >+ struct completion *waiting = rq->waiting; >+ >+ /* spin lock already accquired */ >+ if (!blk_queue_stopped(rq->q)) >+ blk_stop_queue(rq->q); >+ >+ complete(waiting); >+} >+ >+int ide_unprotect_queue(request_queue_t *q) >+{ >+ struct request rq; >+ unsigned long flags; >+ int pending = 0, rc = 0; >+ ide_drive_t *drive = q->queuedata; >+ u8 args[7], *argbuf = args; >+ >+ if (!blk_queue_stopped(q)) >+ return -EIO; >+ >+ /* Are there any pending jobs on the queue? */ >+ pending = ((q->rq.count[READ] > 0) || (q->rq.count[WRITE] > 0)) ? 1 : 0; >+ >+ spin_lock_irqsave(q->queue_lock, flags); >+ blk_start_queue(q); >+ spin_unlock_irqrestore(q->queue_lock, flags); >+ >+ /* The unload feature of the IDLE_IMMEDIATE command >+ temporarily disables HD power management from spinning down >+ the disk. Any other command will reenable HD pm, so, if >+ there are no pending jobs on the queue, another >+ CHECK_POWER_MODE1 command without the unload feature should do >+ just fine. */ >+ if (!pending) { >+ printk(KERN_DEBUG "ide_unprotect_queue(): No pending I/O, re-enabling power management..\n"); >+ memset(args, 0, sizeof(args)); >+ argbuf[0] = 0xe5; /* CHECK_POWER_MODE1 */ >+ ide_init_drive_cmd(&rq); >+ rq.flags = REQ_DRIVE_TASK; >+ rq.buffer = argbuf; >+ rc = ide_do_drive_cmd(drive, &rq, ide_head_wait); >+ } >+ >+ return rc; >+} >+ >+int ide_protect_queue(request_queue_t *q, int unload) >+{ >+ ide_drive_t *drive = q->queuedata; >+ struct request rq; >+ u8 args[7], *argbuf = args; >+ int ret = 0; >+ DECLARE_COMPLETION(wait); >+ >+ memset(&rq, 0, sizeof(rq)); >+ memset(args, 0, sizeof(args)); >+ >+ if (blk_queue_stopped(q)) >+ return -EIO; >+ >+ if (unload) { >+ argbuf[0] = 0xe1; >+ argbuf[1] = 0x44; >+ argbuf[3] = 0x4c; >+ argbuf[4] = 0x4e; >+ argbuf[5] = 0x55; >+ } else >+ argbuf[0] = 0xe0; >+ >+ /* Issue the park command & freeze */ >+ ide_init_drive_cmd(&rq); >+ >+ rq.flags = REQ_DRIVE_TASK; >+ rq.buffer = argbuf; >+ rq.waiting = &wait; >+ rq.end_io = ide_end_protect_rq; >+ >+ ret = ide_do_drive_cmd(drive, &rq, ide_next); >+ wait_for_completion(&wait); >+ rq.waiting = NULL; >+ >+ if (ret) >+ { >+ printk(KERN_DEBUG "ide_protect_queue(): Warning: head NOT parked!..\n"); >+ ide_unprotect_queue(q); >+ return ret; >+ } >+ >+ if (unload) { >+ if (args[3] == 0xc4) >+ printk(KERN_DEBUG "ide_protect_queue(): head parked..\n"); >+ else { >+ /* error parking the head */ >+ printk(KERN_DEBUG "ide_protect_queue(): head NOT parked!..\n"); >+ ret = -EIO; >+ ide_unprotect_queue(q); >+ } >+ } else >+ printk(KERN_DEBUG "ide_protect_queue(): head park not requested, used standby!..\n"); >+ >+ return ret; >+} >+ >+int idedisk_issue_protect_fn(request_queue_t *q) >+{ >+ ide_drive_t *drive = q->queuedata; >+ int unload; >+ >+ /* >+ * Check capability of the device - >+ * - if "idle immediate with unload" is supported we use that, else >+ * we use "standby immediate" and live with spinning down the drive.. >+ * (Word 84, bit 13 of IDENTIFY DEVICE data) >+ */ >+ if (idedisk_protect_method == 1) { >+ unload = 1; >+ printk(KERN_DEBUG "idedisk_issue_protect_fn(): unload method requested, overriding drive capability check..\n"); >+ } >+ else if (idedisk_protect_method == 2) { >+ unload = 0; >+ printk(KERN_DEBUG "idedisk_issue_protect_fn(): standby method requested, overriding drive capability check..\n"); >+ } >+ else if (drive->id->cfsse & (1 << 13)) { >+ unload = 1; >+ printk(KERN_DEBUG "idedisk_issue_protect_fn(): unload support reported by drive..\n"); >+ } >+ else { >+ unload = 0; >+ printk(KERN_DEBUG "idedisk_issue_protect_fn(): unload support NOT reported by drive!..\n"); >+ } >+ >+ return ide_protect_queue(q, unload); >+} >+ >+int idedisk_issue_unprotect_fn(request_queue_t *q) >+{ >+ return ide_unprotect_queue(q); >+} >+ >+/* > * This is tightly woven into the driver->do_special can not touch. > * DON'T do it again until a total personality rewrite is committed. > */ >@@ -985,6 +1137,9 @@ > drive->wcache = 1; > > write_cache(drive, 1); >+ >+ blk_queue_issue_protect_fn(drive->queue, idedisk_issue_protect_fn); >+ blk_queue_issue_unprotect_fn(drive->queue, idedisk_issue_unprotect_fn); > } > > static void ide_cacheflush_p(ide_drive_t *drive) >diff -Nur linux-2.6.17.1/drivers/ide/ide-io.c linux-2.6.17.1.hdaps/drivers/ide/ide-io.c >--- linux-2.6.17.1/drivers/ide/ide-io.c 2006-06-24 23:49:02.185655000 +0200 >+++ linux-2.6.17.1.hdaps/drivers/ide/ide-io.c 2006-06-25 00:46:09.651859000 +0200 >@@ -1249,6 +1249,17 @@ > } > > /* >+ * Don't accept a request when the queue is stopped (unless we >+ * are resuming from suspend). Prevents existing queue entries >+ * being processed after queue is stopped by the hard disk >+ * protection mechanism... >+ */ >+ if (test_bit(QUEUE_FLAG_STOPPED, &drive->queue->queue_flags) && !blk_pm_resume_request(rq)) { >+ hwgroup->busy = 0; >+ break; >+ } >+ >+ /* > * Sanity: don't accept a request that isn't a PM request > * if we are currently power managed. This is very important as > * blk_stop_queue() doesn't prevent the elv_next_request() >@@ -1729,6 +1740,9 @@ > where = ELEVATOR_INSERT_FRONT; > rq->flags |= REQ_PREEMPT; > } >+ if (action == ide_next) >+ where = ELEVATOR_INSERT_FRONT; >+ > __elv_add_request(drive->queue, rq, where, 0); > ide_do_request(hwgroup, IDE_NO_IRQ); > spin_unlock_irqrestore(&ide_lock, flags); >diff -Nur linux-2.6.17.1/drivers/scsi/libata-core.c linux-2.6.17.1.hdaps/drivers/scsi/libata-core.c >--- linux-2.6.17.1/drivers/scsi/libata-core.c 2006-06-24 23:49:02.197656000 +0200 >+++ linux-2.6.17.1.hdaps/drivers/scsi/libata-core.c 2006-06-25 00:31:42.889689750 +0200 >@@ -75,6 +75,10 @@ > > struct workqueue_struct *ata_aux_wq; > >+int libata_protect_method = 0; >+module_param_named(protect_method, libata_protect_method, int, 0444); >+MODULE_PARM_DESC(protect_method, "hdaps disk protection method (0=autodetect, 1=unload, 2=standby)"); >+ > int atapi_enabled = 1; > module_param(atapi_enabled, int, 0444); > MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)"); >diff -Nur linux-2.6.17.1/drivers/scsi/libata.h linux-2.6.17.1.hdaps/drivers/scsi/libata.h >--- linux-2.6.17.1/drivers/scsi/libata.h 2006-06-24 23:49:02.197656000 +0200 >+++ linux-2.6.17.1.hdaps/drivers/scsi/libata.h 2006-06-25 00:46:09.651859000 +0200 >@@ -40,6 +40,7 @@ > > /* libata-core.c */ > extern struct workqueue_struct *ata_aux_wq; >+extern int libata_protect_method; > extern int atapi_enabled; > extern int atapi_dmadir; > extern int libata_fua; >diff -Nur linux-2.6.17.1/drivers/scsi/libata-scsi.c linux-2.6.17.1.hdaps/drivers/scsi/libata-scsi.c >--- linux-2.6.17.1/drivers/scsi/libata-scsi.c 2006-06-24 23:49:02.205657000 +0200 >+++ linux-2.6.17.1.hdaps/drivers/scsi/libata-scsi.c 2006-06-25 00:46:09.663859750 +0200 >@@ -809,6 +809,44 @@ > } > } > >+#if 0 >+extern int scsi_protect_queue(request_queue_t *q, int unload); >+extern int scsi_unprotect_queue(request_queue_t *q); >+ >+static int ata_scsi_issue_protect_fn(request_queue_t *q) >+{ >+ struct scsi_device *sdev = q->queuedata; >+ struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; >+ struct ata_device *dev = &ap->device[sdev->id]; >+ int unload; >+ >+ if (libata_protect_method == 1) { >+ unload = 1; >+ printk(KERN_DEBUG "ata_scsi_issue_protect_fn(): unload method requested, overriding drive capability check..\n"); >+ } >+ else if (libata_protect_method == 2) { >+ unload = 0; >+ printk(KERN_DEBUG "ata_scsi_issue_protect_fn(): standby method requested, overriding drive capability check..\n"); >+ } >+ else if (ata_id_has_unload(dev->id)) { >+ unload = 1; >+ printk(KERN_DEBUG "ata_scsi_issue_protect_fn(): unload support reported by drive..\n"); >+ } >+ else { >+ unload = 0; >+ printk(KERN_DEBUG "ata_scsi_issue_protect_fn(): unload support NOT reported by drive!..\n"); >+ } >+ >+ /* call scsi_protect_queue, requesting either unload or standby */ >+ return scsi_protect_queue(q, unload); >+} >+ >+static int ata_scsi_issue_unprotect_fn(request_queue_t *q) >+{ >+ return scsi_unprotect_queue(q); >+} >+#endif >+ > /** > * ata_scsi_slave_config - Set SCSI device attributes > * @sdev: SCSI device to examine >@@ -832,6 +868,10 @@ > > if (dev) > ata_scsi_dev_config(sdev, dev); >+#if 0 >+ blk_queue_issue_protect_fn(sdev->request_queue, ata_scsi_issue_protect_fn); >+ blk_queue_issue_unprotect_fn(sdev->request_queue, ata_scsi_issue_unprotect_fn); >+#endif > > return 0; /* scsi layer doesn't check return value, sigh */ > } >diff -Nur linux-2.6.17.1/drivers/scsi/scsi_lib.c linux-2.6.17.1.hdaps/drivers/scsi/scsi_lib.c >--- linux-2.6.17.1/drivers/scsi/scsi_lib.c 2006-06-24 23:49:02.209657000 +0200 >+++ linux-2.6.17.1.hdaps/drivers/scsi/scsi_lib.c 2006-06-25 00:40:40.743303500 +0200 >@@ -2191,6 +2191,194 @@ > device_for_each_child(dev, NULL, target_unblock); > } > EXPORT_SYMBOL_GPL(scsi_target_unblock); >+ >+#if 0 >+/* >+ * As per scsi_wait_req_end_io(), which was removed in 2.6.15 >+ */ >+static void scsi_protect_wait_req_end_io(struct request *req, int error) >+{ >+ BUG_ON(!req->waiting); >+ >+ complete(req->waiting); >+} >+ >+/* >+ * As per scsi_wait_done(), except calls scsi_device_block >+ * to block the queue at command completion. Only called by >+ * scsi_protect_wait(). >+ * todo: >+ * - we block the queue regardless of success and rely on the >+ * scsi_protect_queue function to unblock if the command >+ * failed... should we also inspect here? >+ */ >+static void scsi_protect_wait_done(struct scsi_cmnd *cmd) >+{ >+ struct request *req = cmd->request; >+ struct request_queue *q = cmd->device->request_queue; >+ struct scsi_device *sdev = cmd->device; >+ unsigned long flags; >+ >+ req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ >+ >+ spin_lock_irqsave(q->queue_lock, flags); >+ if (blk_rq_tagged(req)) >+ blk_queue_end_tag(q, req); >+ spin_unlock_irqrestore(q->queue_lock, flags); >+ >+ scsi_internal_device_block(sdev); >+ >+ if (req->waiting) >+ complete(req->waiting); >+} >+ >+/* >+ * As per scsi_wait_req(), except sets the completion function >+ * as scsi_protect_wait_done(). >+ */ >+void scsi_protect_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, >+ unsigned bufflen, int timeout, int retries) >+{ >+ DECLARE_COMPLETION(wait); >+ >+ sreq->sr_request->waiting = &wait; >+ sreq->sr_request->rq_status = RQ_SCSI_BUSY; >+ sreq->sr_request->end_io = scsi_protect_wait_req_end_io; >+ scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_protect_wait_done, >+ timeout, retries); >+ wait_for_completion(&wait); >+ sreq->sr_request->waiting = NULL; >+ if (sreq->sr_request->rq_status != RQ_SCSI_DONE) >+ sreq->sr_result |= (DRIVER_ERROR << 24); >+ >+ __scsi_release_request(sreq); >+} >+ >+/* >+ * scsi_unprotect_queue() >+ * - release the queue that was previously blocked >+ */ >+int scsi_unprotect_queue(request_queue_t *q){ >+ >+ struct scsi_device *sdev = q->queuedata; >+ int rc = 0, pending = 0; >+ u8 scsi_cmd[MAX_COMMAND_SIZE]; >+ struct scsi_sense_hdr sshdr; >+ >+ if (sdev->sdev_state != SDEV_BLOCK) >+ return -ENXIO; >+ >+ /* Are there any pending jobs on the queue? */ >+ pending = ((q->rq.count[READ] > 0) || (q->rq.count[WRITE] > 0)) ? 1 : 0; >+ >+ rc = scsi_internal_device_unblock(sdev); >+ if (rc) >+ return rc; >+ >+ if (!pending) { >+printk(KERN_DEBUG "scsi_unprotect_queue(): No pending I/O, re-enabling power management..\n"); >+ >+memset(scsi_cmd, 0, sizeof(scsi_cmd)); >+scsi_cmd[0] = ATA_16; >+scsi_cmd[1] = (3 << 1); /* Non-data */ >+/* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */ >+scsi_cmd[14] = 0xe5; /* CHECK_POWER_MODE1 */ >+ >+/* Good values for timeout and retries? Values below >+ from scsi_ioctl_send_command() for default case... */ >+if (scsi_execute_req(sdev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr, >+ (10*HZ), 5)) >+ rc = -EIO; >+ } >+ return rc; >+} >+EXPORT_SYMBOL_GPL(scsi_unprotect_queue); >+ >+/* >+ * scsi_protect_queue() >+ * - build and issue the park/standby command.. >+ * - queue is blocked during command completion handler >+ */ >+int scsi_protect_queue(request_queue_t *q, int unload) >+{ >+ struct scsi_device *sdev = q->queuedata; >+ int rc = 0; >+ u8 scsi_cmd[MAX_COMMAND_SIZE]; >+ u8 args[7]; >+ struct scsi_request *sreq; >+ unsigned char *sb, *desc; >+ >+ if (sdev->sdev_state != SDEV_RUNNING) >+ return -ENXIO; >+ >+ memset(args, 0, sizeof(args)); >+ >+ if (unload) { >+ args[0] = 0xe1; >+ args[1] = 0x44; >+ args[3] = 0x4c; >+ args[4] = 0x4e; >+ args[5] = 0x55; >+ } else >+ args[0] = 0xe0; >+ >+ memset(scsi_cmd, 0, sizeof(scsi_cmd)); >+ scsi_cmd[0] = ATA_16; >+ scsi_cmd[1] = (3 << 1); /* Non-data */ >+ scsi_cmd[2] = 0x20; /* no off.line, or data xfer, request cc */ >+ scsi_cmd[4] = args[1]; >+ scsi_cmd[6] = args[2]; >+ scsi_cmd[8] = args[3]; >+ scsi_cmd[10] = args[4]; >+ scsi_cmd[12] = args[5]; >+ scsi_cmd[14] = args[0]; >+ >+ sreq = scsi_allocate_request(sdev, GFP_KERNEL); >+ if (!sreq) { >+ rc = -EINTR; >+ goto error; >+ } >+ >+ sreq->sr_data_direction = DMA_NONE; >+ >+ scsi_protect_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5); >+ >+ if (!sreq->sr_result == ((DRIVER_SENSE << 24) + SAM_STAT_CHECK_CONDITION)) { >+ printk(KERN_DEBUG "scsi_protect_queue(): head NOT parked!..\n"); >+ scsi_unprotect_queue(q); /* just in case we still managed to block */ >+ rc = -EIO; >+ goto error; >+ } >+ >+ sb = sreq->sr_sense_buffer; >+ desc = sb + 8; >+ >+/* Retrieve data from check condition */ >+ args[1] = desc[3]; >+ args[2] = desc[5]; >+ args[3] = desc[7]; >+ args[4] = desc[9]; >+ args[5] = desc[11]; >+ args[0] = desc[13]; >+ >+ if (unload) { >+ if (args[3] == 0xc4) >+ printk(KERN_DEBUG "scsi_protect_queue(): head parked..\n"); >+ else { >+/* error parking the head */ >+ printk(KERN_DEBUG "scsi_protect_queue(): head NOT parked!..\n"); >+ rc = -EIO; >+ scsi_unprotect_queue(q); >+ } >+ } else >+ printk(KERN_DEBUG "scsi_protect_queue(): head park not requested, used standby!..\n"); >+ >+error: >+ scsi_release_request(sreq); >+ return rc; >+} >+EXPORT_SYMBOL_GPL(scsi_protect_queue); >+#endif > > /** > * scsi_kmap_atomic_sg - find and atomically map an sg-elemnt >diff -Nur linux-2.6.17.1/include/linux/ata.h linux-2.6.17.1.hdaps/include/linux/ata.h >--- linux-2.6.17.1/include/linux/ata.h 2006-06-24 23:49:02.221658000 +0200 >+++ linux-2.6.17.1.hdaps/include/linux/ata.h 2006-06-25 00:42:42.258897750 +0200 >@@ -277,6 +277,7 @@ > #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) > #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) > #define ata_id_hpa_enabled(id) ((id)[85] & (1 << 10)) >+#define ata_id_has_unload(id) ((id)[84] & (1 << 13)) > #define ata_id_has_fua(id) ((id)[84] & (1 << 6)) > #define ata_id_has_flush(id) ((id)[83] & (1 << 12)) > #define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13)) >diff -Nur linux-2.6.17.1/include/linux/blkdev.h linux-2.6.17.1.hdaps/include/linux/blkdev.h >--- linux-2.6.17.1/include/linux/blkdev.h 2006-06-24 23:49:02.233658000 +0200 >+++ linux-2.6.17.1.hdaps/include/linux/blkdev.h 2006-06-25 00:46:09.675860500 +0200 >@@ -297,6 +297,8 @@ > typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *); > typedef void (prepare_flush_fn) (request_queue_t *, struct request *); > typedef void (softirq_done_fn)(struct request *); >+typedef int (issue_protect_fn) (request_queue_t *); >+typedef int (issue_unprotect_fn) (request_queue_t *); > > enum blk_queue_state { > Queue_down, >@@ -339,6 +341,8 @@ > issue_flush_fn *issue_flush_fn; > prepare_flush_fn *prepare_flush_fn; > softirq_done_fn *softirq_done_fn; >+ issue_protect_fn *issue_protect_fn; >+ issue_unprotect_fn *issue_unprotect_fn; > > /* > * Dispatch queue sorting >@@ -720,6 +724,8 @@ > extern unsigned blk_ordered_cur_seq(request_queue_t *); > extern unsigned blk_ordered_req_seq(struct request *); > extern void blk_ordered_complete_seq(request_queue_t *, unsigned, int); >+extern void blk_queue_issue_protect_fn(request_queue_t *, issue_protect_fn *); >+extern void blk_queue_issue_unprotect_fn(request_queue_t *, issue_unprotect_fn *); > > extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *); > extern void blk_dump_rq_flags(struct request *, char *); >diff -Nur linux-2.6.17.1/include/linux/ide.h linux-2.6.17.1.hdaps/include/linux/ide.h >--- linux-2.6.17.1/include/linux/ide.h 2006-06-24 23:49:02.237659000 +0200 >+++ linux-2.6.17.1.hdaps/include/linux/ide.h 2006-06-25 00:46:09.679860750 +0200 >@@ -1085,6 +1085,7 @@ > */ > typedef enum { > ide_wait, /* insert rq at end of list, and wait for it */ >+ ide_next, /* insert rq immediately after current request */ > ide_preempt, /* insert rq in front of current request */ > ide_head_wait, /* insert rq in front of current request and wait for it */ > ide_end /* insert rq at end of list, but don't wait for it */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 148423
:
97581
| 97981