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