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