Am Dienstag, 15. Januar 2008 16:30:34 schrieb Alan Stern:
> On Tue, 15 Jan 2008, Oliver Neukum wrote:
> 
> > Hi Alan,
> > 
> > here's a simple implementation to handle ioctl() by blocking
> > autosuspend until the device is closed again.
> > 
> > It is relative to your patch set.
> 
> A few comments are below.

OK, here's an improved version. sr support is still under development.

Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>

        Regards
                Oliver

----

--- linux-2.6.22/drivers/scsi/sd.c      2008-01-18 21:57:49.000000000 +0100
+++ linux-2.6.24-scsi-pm/drivers/scsi/sd.c      2008-01-18 16:32:25.000000000 
+0100
@@ -103,6 +103,10 @@ static void sd_print_result(struct scsi_
 static DEFINE_IDR(sd_index_idr);
 static DEFINE_SPINLOCK(sd_index_lock);
 
+#ifdef CONFIG_SCSI_DYNAMIC_PM
+static DEFINE_MUTEX(sd_ioctl_mutex);
+#endif
+
 /* This semaphore is used to mediate the 0->1 reference get in the
  * face of object destruction (i.e. we can't allow a get on an
  * object after last put) */
@@ -633,6 +637,13 @@ static int sd_release(struct inode *inod
                        scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW);
        }
 
+#ifdef CONFIG_SCSI_DYNAMIC_PM
+       if (sdev->autosuspend_ioctl_blocked) {
+               sdev->autosuspend_ioctl_blocked = 0;
+               scsi_autosuspend_device(sdev);
+       }
+#endif
+
        /*
         * XXX and what if there are packets in flight and this close()
         * XXX is followed by a "rmmod sd_mod"?
@@ -711,6 +722,18 @@ static int sd_ioctl(struct inode * inode
                case SCSI_IOCTL_GET_BUS_NUMBER:
                        return scsi_ioctl(sdp, cmd, p);
                default:
+                       /* closer filtering should go here */
+#ifdef CONFIG_SCSI_DYNAMIC_PM
+                       mutex_lock(&sd_ioctl_mutex);
+                       if (!sdp->autosuspend_ioctl_blocked) {
+                               error = scsi_autoresume_device(sdp);
+                               if (error >= 0)
+                                       sdp->autosuspend_ioctl_blocked = 1;
+                       }
+                       mutex_unlock(&sd_ioctl_mutex);
+                       if (error < 0)
+                               return error;
+#endif
                        error = scsi_cmd_ioctl(filp, disk->queue, disk, cmd, p);
                        if (error != -ENOTTY)
                                return error;
--- linux-2.6.22/drivers/scsi/st.c      2008-01-18 21:56:58.000000000 +0100
+++ linux-2.6.24-scsi-pm/drivers/scsi/st.c      2008-01-18 17:11:06.000000000 
+0100
@@ -52,6 +52,7 @@ static const char *verstr = "20070203";
 #include <scsi/scsi_ioctl.h>
 #include <scsi/sg.h>
 
+#include "scsi_priv.h"
 
 /* The driver prints some debugging information on the console if DEBUG
    is defined and non-zero. */
@@ -1115,7 +1116,7 @@ static int check_tape(struct scsi_tape *
    module count. */
 static int st_open(struct inode *inode, struct file *filp)
 {
-       int i, retval = (-EIO);
+       int i, retval = (-EIO), err;
        struct scsi_tape *STp;
        struct st_partstat *STps;
        int dev = TAPE_NR(inode);
@@ -1142,6 +1143,14 @@ static int st_open(struct inode *inode, 
                return (-EBUSY);
        }
 
+       err = scsi_autoresume_device(STp->device);
+       if (err < 0) {
+               write_unlock(&st_dev_arr_lock);
+               scsi_tape_put(STp);
+               DEB( printk(ST_DEB_MSG "%s: Device refuses to resume.\n", 
name); )
+               return err;
+       }
+
        STp->in_use = 1;
        write_unlock(&st_dev_arr_lock);
        STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
@@ -1190,6 +1199,7 @@ static int st_open(struct inode *inode, 
  err_out:
        normalize_buffer(STp->buffer);
        STp->in_use = 0;
+       scsi_autosuspend_device(STp->device);
        scsi_tape_put(STp);
        return retval;
 
@@ -1322,6 +1332,7 @@ static int st_release(struct inode *inod
        write_lock(&st_dev_arr_lock);
        STp->in_use = 0;
        write_unlock(&st_dev_arr_lock);
+       scsi_autosuspend_device(STp->device);
        scsi_tape_put(STp);
 
        return result;
--- linux-2.6.22/drivers/scsi/osst.c    2008-01-18 21:56:58.000000000 +0100
+++ linux-2.6.24-scsi-pm/drivers/scsi/osst.c    2008-01-18 17:20:25.000000000 
+0100
@@ -78,6 +78,8 @@ static const char * osst_version = "0.99
 #include "osst_options.h"
 #include "osst_detect.h"
 
+#include "scsi_priv.h"
+
 static int max_dev = 0;
 static int write_threshold_kbs = 0;
 static int max_sg_segs = 0;
@@ -4362,7 +4364,7 @@ os_bypass:
 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
 {
        unsigned short        flags;
-       int                   i, b_size, new_session = 0, retval = 0;
+       int                   i, err, b_size, new_session = 0, retval = 0;
        unsigned char         cmd[MAX_COMMAND_SIZE];
        struct osst_request * SRpnt = NULL;
        struct osst_tape    * STp;
@@ -4402,6 +4404,15 @@ static int os_scsi_tape_open(struct inod
 #endif
                return (-ENXIO);
        }
+
+       err = scsi_autoresume_device(STp->device);
+       if (err < 0) {
+               write_unlock(&os_scsi_tapes_lock);
+               scsi_device_put(STp->device);
+               printk(OSST_DEB_MSG "%s:D: Device refuses to resume.\n", name);
+               return err;
+       }
+
        filp->private_data = STp;
        STp->in_use = 1;
        write_unlock(&os_scsi_tapes_lock);
@@ -4720,6 +4731,7 @@ err_out:
        normalize_buffer(STp->buffer);
        STp->header_ok = 0;
        STp->in_use = 0;
+       scsi_autosuspend_device(STp->device);
        scsi_device_put(STp->device);
 
        return retval;
@@ -4836,6 +4848,7 @@ static int os_scsi_tape_close(struct ino
        STp->in_use = 0;
        write_unlock(&os_scsi_tapes_lock);
 
+       scsi_autosuspend_device(STp->device);
        scsi_device_put(STp->device);
 
        return result;
--- linux-2.6.22/include/scsi/scsi_device.h     2008-01-18 21:57:49.000000000 
+0100
+++ linux-2.6.24-scsi-pm/include/scsi/scsi_device.h     2008-01-14 
12:45:12.000000000 +0100
@@ -177,6 +177,7 @@ struct scsi_device {
        unsigned auto_pm:1;             /* doing autosuspend or autoresume */
        unsigned autosuspend_disabled:1;        /* autosuspend & autoresume */
        unsigned autoresume_disabled:1;         /*  disabled by the user */
+       unsigned autosuspend_ioctl_blocked:1;   /* disabled due to ioctl use */
        unsigned skip_sys_resume:1;     /* skip the next system resume */
        unsigned use_ULD_pm:1;          /* call the Upper-Level Driver's
                                         *   suspend/resume methods */

-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to