[PATCH v3 0/5] Migrate SCSI drivers to use dev_pm_ops
v3: Only patch 4 is modified: Remove the special case for system freeze in scsi_bus_suspend_common as pointed out by Alan Stern; Updated some comments; Removed the use of typedef (*pm_callback_t)(struct device *). v2: Change the runtime suspend behaviour of sd driver by putting the device into stopped power state. Revert 2 patches which are no longer needed as pointed out by Alan Stern. Find out device callbacks in bus callbacks as suggested by Alan Stern. Due to these changes, patch number grows from 2 - 5. v1: The 2 patches will migrate SCSI drivers to use the pm callbacks defined in dev_pm_ops as pm_message is deprecated and should not be used by driver. Bus level callback is changed to use callbacks defined in dev_pm_ops when needed and sd's pm callback is updated to use what are defined in dev_pm_ops. Aaron Lu (5): sd: put to stopped power state when runtime suspend Revert [SCSI] scsi_pm: set device runtime state before parent suspended Revert [SCSI] runtime resume parent for child's system-resume pm: use callbacks from dev_pm_ops for scsi devices sd: update sd to use the new pm callbacks drivers/scsi/scsi_pm.c | 97 +++--- drivers/scsi/sd.c | 18 +++--- 2 files changed, 66 insertions(+), 49 deletions(-) -- 1.7.12.21.g871e293 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/5] sd: put to stopped power state when runtime suspend
When device is runtime suspended, put it to stopped power state to save some power. This will also make the behaviour consistent with what the scsi_pm.c thinks about sd as the comment says: sd treats runtime suspend, system suspend and system hibernate identical. With this patch, it is now identical. And sd_shutdown will also do nothing when it finds the device has been runtime suspended, if we do not spin down the disk in runtime suspend by putting it into stopped power state, the disk will be shut down incorrectly. And the the same problem can be solved for runtime power off after runtime suspended case by this change. With the current runtime scheme for disk, it will only be runtime suspended when no process opens the disk, so this shouldn't happen a lot, which makes it acceptable to spin down the disk when runtime suspended. If some day a more aggressive runtime scheme is used, like the 'request based runtime pm for disk' that Alan Stern and Lin Ming has been working, we can introduce some policy to control this. But for now, make it simple and correct by spinning down the disk. Signed-off-by: Aaron Lu aaron...@intel.com --- drivers/scsi/sd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 12f6fdf..8b6e004 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2911,7 +2911,8 @@ static int sd_suspend(struct device *dev, pm_message_t mesg) goto done; } - if ((mesg.event PM_EVENT_SLEEP) sdkp-device-manage_start_stop) { + if (((mesg.event PM_EVENT_SLEEP) || PMSG_IS_AUTO(mesg)) + sdkp-device-manage_start_stop) { sd_printk(KERN_NOTICE, sdkp, Stopping disk\n); ret = sd_start_stop_device(sdkp, 0); } -- 1.7.12.21.g871e293 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 3/5] Revert [SCSI] runtime resume parent for child's system-resume
This reverts commit 28fd00d42cca178638f51c08efa986a777c24a4b. With commit 88d26136a256576e444db312179e17af6dd0ea87 (PM: Prevent runtime suspend during system resume), this patch is no longer needed. Signed-off-by: Aaron Lu aaron...@intel.com --- drivers/scsi/scsi_pm.c | 11 +-- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index d4201de..9923b26 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -76,17 +76,8 @@ static int scsi_bus_resume_common(struct device *dev) { int err = 0; - if (scsi_is_sdev_device(dev)) { - /* -* Parent device may have runtime suspended as soon as -* it is woken up during the system resume. -* -* Resume it on behalf of child. -*/ - pm_runtime_get_sync(dev-parent); + if (scsi_is_sdev_device(dev)) err = scsi_dev_type_resume(dev); - pm_runtime_put_sync(dev-parent); - } if (err == 0) { pm_runtime_disable(dev); -- 1.7.12.21.g871e293 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 5/5] sd: update sd to use the new pm callbacks
Update sd driver to use the callbacks defined in dev_pm_ops. sd_freeze is NULL, the bus level callback has taken care of quiescing the device so there should be nothing needs to be done here. Consequently, sd_thaw is not needed here either. suspend, poweroff and runtime suspend share the same routine sd_suspend, which will sync flush and then stop the drive, this is the same as before. resume, restore and runtime resume share the same routine sd_resume, which will start the drive by putting it into active power state, this is also the same as before. Signed-off-by: Aaron Lu aaron...@intel.com --- drivers/scsi/sd.c | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8b6e004..6564305 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -104,7 +104,7 @@ static void sd_unlock_native_capacity(struct gendisk *disk); static int sd_probe(struct device *); static int sd_remove(struct device *); static void sd_shutdown(struct device *); -static int sd_suspend(struct device *, pm_message_t state); +static int sd_suspend(struct device *); static int sd_resume(struct device *); static void sd_rescan(struct device *); static int sd_done(struct scsi_cmnd *); @@ -423,15 +423,23 @@ static struct class sd_disk_class = { .dev_attrs = sd_disk_attrs, }; +static const struct dev_pm_ops sd_pm_ops = { + .suspend= sd_suspend, + .resume = sd_resume, + .poweroff = sd_suspend, + .restore= sd_resume, + .runtime_suspend= sd_suspend, + .runtime_resume = sd_resume, +}; + static struct scsi_driver sd_template = { .owner = THIS_MODULE, .gendrv = { .name = sd, .probe = sd_probe, .remove = sd_remove, - .suspend= sd_suspend, - .resume = sd_resume, .shutdown = sd_shutdown, + .pm = sd_pm_ops, }, .rescan = sd_rescan, .done = sd_done, @@ -2896,7 +2904,7 @@ exit: scsi_disk_put(sdkp); } -static int sd_suspend(struct device *dev, pm_message_t mesg) +static int sd_suspend(struct device *dev) { struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); int ret = 0; @@ -2911,8 +2919,7 @@ static int sd_suspend(struct device *dev, pm_message_t mesg) goto done; } - if (((mesg.event PM_EVENT_SLEEP) || PMSG_IS_AUTO(mesg)) - sdkp-device-manage_start_stop) { + if (sdkp-device-manage_start_stop) { sd_printk(KERN_NOTICE, sdkp, Stopping disk\n); ret = sd_start_stop_device(sdkp, 0); } -- 1.7.12.21.g871e293 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 4/5] pm: use callbacks from dev_pm_ops for scsi devices
Use of pm_message_t is deprecated and device driver is not supposed to use that. This patch tries to migrate the SCSI bus level pm callbacks to call device's pm callbacks defined in its driver's dev_pm_ops. This is achieved by finding out which device pm callback should be used in bus callback function, and then pass that callback function pointer as a param to the scsi_bus_{suspend,resume}_common routine, which will further pass that callback to scsi_dev_type_{suspend,resume} after proper handling. The special case for freeze in scsi_bus_suspend_common is not necessary since there is no high level SCSI driver has implemented freeze, so no need to runtime resume the device if it is in runtime suspended state for system freeze, just return like the system suspend/hibernate case. Since only sd has implemented drv-suspend/drv-resume, and I'll update sd driver to use the new callbacks in the following patch, there is no need to fallback to call drv-suspend/drv-resume if dev_pm_ops is NULL. Signed-off-by: Aaron Lu aaron...@intel.com --- drivers/scsi/scsi_pm.c | 85 ++ 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 9923b26..6e70a16 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -16,16 +16,14 @@ #include scsi_priv.h -static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg) +static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *)) { - struct device_driver *drv; int err; err = scsi_device_quiesce(to_scsi_device(dev)); if (err == 0) { - drv = dev-driver; - if (drv drv-suspend) { - err = drv-suspend(dev, msg); + if (cb) { + err = cb(dev); if (err) scsi_device_resume(to_scsi_device(dev)); } @@ -34,14 +32,12 @@ static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg) return err; } -static int scsi_dev_type_resume(struct device *dev) +static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *)) { - struct device_driver *drv; int err = 0; - drv = dev-driver; - if (drv drv-resume) - err = drv-resume(dev); + if (cb) + err = cb(dev); scsi_device_resume(to_scsi_device(dev)); dev_dbg(dev, scsi resume: %d\n, err); return err; @@ -49,35 +45,33 @@ static int scsi_dev_type_resume(struct device *dev) #ifdef CONFIG_PM_SLEEP -static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg) +static int +scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *)) { int err = 0; if (scsi_is_sdev_device(dev)) { /* -* sd is the only high-level SCSI driver to implement runtime -* PM, and sd treats runtime suspend, system suspend, and -* system hibernate identically (but not system freeze). +* All the high-level SCSI drivers that implement runtime +* PM treat runtime suspend, system suspend, and system +* hibernate identically. */ - if (pm_runtime_suspended(dev)) { - if (msg.event == PM_EVENT_SUSPEND || - msg.event == PM_EVENT_HIBERNATE) - return 0; /* already suspended */ + if (pm_runtime_suspended(dev)) + return 0; - /* wake up device so that FREEZE will succeed */ - pm_runtime_resume(dev); - } - err = scsi_dev_type_suspend(dev, msg); + err = scsi_dev_type_suspend(dev, cb); } + return err; } -static int scsi_bus_resume_common(struct device *dev) +static int +scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *)) { int err = 0; if (scsi_is_sdev_device(dev)) - err = scsi_dev_type_resume(dev); + err = scsi_dev_type_resume(dev, cb); if (err == 0) { pm_runtime_disable(dev); @@ -102,26 +96,49 @@ static int scsi_bus_prepare(struct device *dev) static int scsi_bus_suspend(struct device *dev) { - return scsi_bus_suspend_common(dev, PMSG_SUSPEND); + const struct dev_pm_ops *pm = dev-driver ? dev-driver-pm : NULL; + return scsi_bus_suspend_common(dev, pm ? pm-suspend : NULL); +} + +static int scsi_bus_resume(struct device *dev) +{ + const struct dev_pm_ops *pm = dev-driver ? dev-driver-pm : NULL; + return scsi_bus_resume_common(dev, pm ? pm-resume : NULL); } static int scsi_bus_freeze(struct device *dev) { - return scsi_bus_suspend_common(dev, PMSG_FREEZE); + const struct dev_pm_ops *pm = dev-driver
[PATCH 00/10] scsi: avoid linebreaks in syslog output
This patchset updates the SCSI midlayer to use dev_printk() instead of the simple printk(). The main objective here is to avoid line-breaks in syslog output; with the current state it's nearly impossible to match the output to the occurring device; under high load even the CDB will be split off into individual bytes, spread randomly across the lines. Which makes debugging via scsi_logging_level _really_ hard. In addition we'll be getting the syslog messages nicely prefixed with the device, which will make userspace logging daemons happy. Before: [ 297.300605] sd 2:0:3:2: Send: [ 297.300607] 0x8802348b0980 [ 297.300610] sd 2:0:3:2: CDB: [ 297.300615] Test Unit Ready: 00 00 00 00 00 00 [ 297.300747] sd 2:0:3:2: Done: [ 297.300750] 0x8802348b0980 SUCCESS [ 297.300753] sd 2:0:3:2: [ 297.300755] Result: hostbyte=DID_OK driverbyte=DRIVER_OK [ 297.300758] sd 2:0:3:2: CDB: [ 297.300764] Test Unit Ready: 00 00 00 00 00 00 [ 297.300766] sd 2:0:3:2: [ 297.300769] Sense Key : Unit Attention [current] [ 297.300771] Info fld=0x0 [ 297.300772] sd 2:0:3:2: [ 297.300776] Add. Sense: Capacity data has changed After: [ 636.683556] sd 2:0:3:2: Send: 0x88043145eec0 [ 636.727856] sd 2:0:3:2: CDB: Test Unit Ready: 00 00 00 00 00 00 [ 636.785330] sd 2:0:3:2: Done: 0x88043145eec0 SUCCESS [ 636.838228] sd 2:0:3:2: Result: hostbyte=DID_OK driverbyte=DRIVER_OK [ 636.899099] sd 2:0:3:2: CDB: Test Unit Ready: 00 00 00 00 00 00 [ 636.955905] sd 2:0:3:2: Sense Key : Unit Attention [current] [ 637.069179] sd 2:0:3:2: Add. Sense: Capacity data has changed Hannes Reinecke (10): sg: Use dev_printk sr: Use dev_printk() scsi: Avoid linebreaks in syslog output scsi: Use sdev_printk() for logging scsi: use buffer for print_opcode_name() scsi: use single printk call in scsi_print_command() scsi: use buffer for scsi_show_result() scsi: open-code scsi_decode_sense_buffer() scsi: decode descriptor sense scsi: use local buffer for decoding sense data drivers/scsi/constants.c | 406 + drivers/scsi/scsi.c | 54 --- drivers/scsi/scsi_error.c | 190 ++--- drivers/scsi/scsi_lib.c | 13 +- drivers/scsi/scsi_scan.c | 68 drivers/scsi/sd.c | 16 +- drivers/scsi/sg.c | 187 - drivers/scsi/sr.c | 47 +++--- drivers/scsi/sr.h |4 + include/scsi/scsi_dbg.h |6 +- include/scsi/scsi_eh.h|8 +- 11 files changed, 588 insertions(+), 411 deletions(-) -- 1.7.4.2 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/10] sg: Use dev_printk
Every sg device has a reference to the underlying scsi device, so this patch adds dev_printk() macros to have the messages prefixed with the correct device. Before: [772330.437378] sg_open: dev=2, flags=0x8800 [772330.475425] sg_add_sfp: sfp=0x880429d3e000 After: [ 409.399888] sr 2:0:0:0: [sg2] sg_open: flags=0x8800 [ 409.446029] sr 2:0:0:0: [sg2] sg_add_sfp: sfp=0x880425856000 Cc: Kay Sievers k...@vrfy.org Cc: Doug Gilbert dgilb...@interlog.com Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/sg.c | 187 +++-- 1 files changed, 109 insertions(+), 78 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9c5c5f2..2e6056f 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -101,6 +101,13 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ; #define SG_SECTOR_SZ 512 +#define sgdev_printk(prefix, sgdev, fmt, a...) \ + dev_printk(prefix, (sgdev)-device-sdev_gendev, [%s] fmt, \ + (sgdev)-disk-disk_name, ##a) + +#define sgfp_printk(prefix, sgfp, fmt, a...) \ + sgdev_printk(prefix, (sgfp)-parentdp, fmt, ##a) + static int sg_add(struct device *, struct class_interface *); static void sg_remove(struct device *, struct class_interface *); @@ -196,7 +203,7 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer); -static void sg_remove_scat(Sg_scatter_hold * schp); +static void sg_remove_scat(Sg_scatter_hold * schp, Sg_fd * sfp); static void sg_build_reserve(Sg_fd * sfp, int req_size); static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size); static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp); @@ -268,13 +275,14 @@ sg_open(struct inode *inode, struct file *filp) int retval; nonseekable_open(inode, filp); - SCSI_LOG_TIMEOUT(3, printk(sg_open: dev=%d, flags=0x%x\n, dev, flags)); sdp = sg_get_dev(dev); if (IS_ERR(sdp)) { retval = PTR_ERR(sdp); sdp = NULL; goto sg_put; } + SCSI_LOG_TIMEOUT(3, sgdev_printk(KERN_INFO, sdp, +sg_open: flags=0x%x\n, flags)); /* This driver's module count bumped by fops_get in linux/fs.h */ /* Prevent the device driver from vanishing while we sleep */ @@ -360,7 +368,7 @@ sg_release(struct inode *inode, struct file *filp) if ((!(sfp = (Sg_fd *) filp-private_data)) || (!(sdp = sfp-parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk(sg_release: %s\n, sdp-disk-disk_name)); + SCSI_LOG_TIMEOUT(3, sgdev_printk(KERN_INFO, sdp, sg_release)); set_exclude(sdp, 0); wake_up_interruptible(sdp-o_excl_wait); @@ -383,8 +391,8 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) if ((!(sfp = (Sg_fd *) filp-private_data)) || (!(sdp = sfp-parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk(sg_read: %s, count=%d\n, - sdp-disk-disk_name, (int) count)); + SCSI_LOG_TIMEOUT(3, sgdev_printk(KERN_INFO, sdp, sg_read: count=%d, +(int) count)); if (!access_ok(VERIFY_WRITE, buf, count)) return -EFAULT; @@ -569,8 +577,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if ((!(sfp = (Sg_fd *) filp-private_data)) || (!(sdp = sfp-parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk(sg_write: %s, count=%d\n, - sdp-disk-disk_name, (int) count)); + SCSI_LOG_TIMEOUT(3, sgdev_printk(KERN_INFO, sdp, sg_write: count=%d, +(int) count)); if (sdp-detached) return -ENODEV; if (!((filp-f_flags O_NONBLOCK) || @@ -591,14 +599,17 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) return -EIO;/* The minimum scsi command length is 6 bytes. */ if (!(srp = sg_add_request(sfp))) { - SCSI_LOG_TIMEOUT(1, printk(sg_write: queue full\n)); + SCSI_LOG_TIMEOUT(1, sgdev_printk(KERN_INFO, sdp, +sg_write: queue full)); return -EDOM; } buf += SZ_SG_HEADER; __get_user(opcode, buf); if (sfp-next_cmd_len 0) { if (sfp-next_cmd_len MAX_COMMAND_SIZE) { - SCSI_LOG_TIMEOUT(1, printk(sg_write: command length too long\n)); + SCSI_LOG_TIMEOUT(1, sgdev_printk(KERN_INFO, sdp, +sg_write: command +
[PATCH 03/10] scsi: Avoid linebreaks in syslog output
sdev_printk() is adding a linebreak automatically, causing the syslog output to be garbled: [ 542.494393] sr 2:0:0:0: Send: [ 542.494394] 0x8804291e5dc0 which will make debuggging painful. So reshuffle sdev_printk invokation to have it printed on the same line. Cc: Kay Sievers k...@vrfy.org Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/scsi.c | 38 ++ 1 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 2936b44..28b294b 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -551,14 +551,15 @@ void scsi_log_send(struct scsi_cmnd *cmd) level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS); if (level 1) { - scmd_printk(KERN_INFO, cmd, Send: ); if (level 2) - printk(0x%p , cmd); - printk(\n); + scmd_printk(KERN_INFO, cmd, Send: 0x%p, cmd); + else + scmd_printk(KERN_INFO, cmd, Send:); scsi_print_command(cmd); if (level 3) { - printk(KERN_INFO buffer = 0x%p, bufflen = %d, - queuecommand 0x%p\n, + scmd_printk(KERN_INFO, cmd, + buffer = 0x%p, bufflen = %d, + queuecommand 0x%p, scsi_sglist(cmd), scsi_bufflen(cmd), cmd-device-host-hostt-queuecommand); @@ -588,42 +589,47 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) SCSI_LOG_MLCOMPLETE_BITS); if (((level 0) (cmd-result || disposition != SUCCESS)) || (level 1)) { - scmd_printk(KERN_INFO, cmd, Done: ); - if (level 2) - printk(0x%p , cmd); + const char *disp_str; + /* * Dump truncated values, so we usually fit within * 80 chars. */ switch (disposition) { case SUCCESS: - printk(SUCCESS\n); + disp_str = SUCCESS; break; case NEEDS_RETRY: - printk(RETRY\n); + disp_str = RETRY; break; case ADD_TO_MLQUEUE: - printk(MLQUEUE\n); + disp_str = MLQUEUE; break; case FAILED: - printk(FAILED\n); + disp_str = FAILED; break; case TIMEOUT_ERROR: - /* + /* * If called via scsi_times_out. */ - printk(TIMEOUT\n); + disp_str = TIMEOUT; break; default: - printk(UNKNOWN\n); + disp_str = UNKNOWN; } + if (level 2) + scmd_printk(KERN_INFO, cmd, Done: 0x%p %s, + cmd, disp_str); + else + scmd_printk(KERN_INFO, cmd, Done: %s, + disp_str); scsi_print_result(cmd); scsi_print_command(cmd); if (status_byte(cmd-result) CHECK_CONDITION) scsi_print_sense(, cmd); if (level 3) scmd_printk(KERN_INFO, cmd, - scsi host busy %d failed %d\n, + scsi host busy %d failed %d, cmd-device-host-host_busy, cmd-device-host-host_failed); } -- 1.7.4.2 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/10] sr: Use dev_printk()
Convert sr to use dev_printk() to avoid linebreaks in kernel messages. Cc: Kay Sievers k...@vrfy.org Cc: Jens Axboe ax...@kernel.dk Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/sr.c | 47 ++- drivers/scsi/sr.h |4 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 5fc97d2..26404ca 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -276,8 +276,8 @@ do_tur: if (!cd-tur_changed) { if (cd-get_event_changed) { if (cd-tur_mismatch++ 8) { - sdev_printk(KERN_WARNING, cd-device, - GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n); + sr_printk(KERN_WARNING, cd, + GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n); cd-ignore_get_event = true; } } else { @@ -306,7 +306,7 @@ static int sr_done(struct scsi_cmnd *SCpnt) struct scsi_cd *cd = scsi_cd(SCpnt-request-rq_disk); #ifdef DEBUG - printk(sr.c done: %x\n, result); + sr_printk(KERN_INFO, cd, sr.c done: %x\n, result); #endif /* @@ -389,13 +389,16 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) * is used for a killable error condition */ ret = BLKPREP_KILL; - SCSI_LOG_HLQUEUE(1, printk(Doing sr request, dev = %s, block = %d\n, - cd-disk-disk_name, block)); + SCSI_LOG_HLQUEUE(1, + scmd_printk(KERN_INFO, SCpnt, + Doing sr request, block = %d\n, block)); if (!cd-device || !scsi_device_online(cd-device)) { - SCSI_LOG_HLQUEUE(2, printk(Finishing %u sectors\n, - blk_rq_sectors(rq))); - SCSI_LOG_HLQUEUE(2, printk(Retry with 0x%p\n, SCpnt)); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + Finishing %u sectors\n, + blk_rq_sectors(rq))); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + Retry with 0x%p\n, SCpnt)); goto out; } @@ -416,7 +419,8 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) if (!in_interrupt()) sr_set_blocklength(cd, 2048); else - printk(sr: can't switch blocksize: in interrupt\n); + scmd_printk(KERN_INFO, SCpnt, + sr: can't switch blocksize: in interrupt\n); } if (s_size != 512 s_size != 1024 s_size != 2048) { @@ -429,7 +433,7 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) goto out; SCpnt-cmnd[0] = WRITE_10; SCpnt-sc_data_direction = DMA_TO_DEVICE; - cd-cdi.media_written = 1; + cd-cdi.media_written = 1; } else if (rq_data_dir(rq) == READ) { SCpnt-cmnd[0] = READ_10; SCpnt-sc_data_direction = DMA_FROM_DEVICE; @@ -447,8 +451,8 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) if (size != scsi_bufflen(SCpnt)) { scmd_printk(KERN_ERR, SCpnt, - mismatch count %d, bytes %d\n, - size, scsi_bufflen(SCpnt)); + mismatch count %d, bytes %d\n, + size, scsi_bufflen(SCpnt)); if (scsi_bufflen(SCpnt) size) SCpnt-sdb.length = size; } @@ -466,11 +470,11 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) this_count = (scsi_bufflen(SCpnt) 9) / (s_size 9); - SCSI_LOG_HLQUEUE(2, printk(%s : %s %d/%u 512 byte blocks.\n, - cd-cdi.name, - (rq_data_dir(rq) == WRITE) ? - writing : reading, - this_count, blk_rq_sectors(rq))); + SCSI_LOG_HLQUEUE(2, sr_printk(KERN_INFO, cd, + %s %d/%u 512 byte blocks.\n, + (rq_data_dir(rq) == WRITE) ? + writing : reading, + this_count, blk_rq_sectors(rq))); SCpnt-cmnd[1] = 0; block = (unsigned int)blk_rq_pos(rq) / (s_size 9); @@ -790,8 +794,9 @@ static void get_sectorsize(struct scsi_cd *cd) case 512: break; default: -
[PATCH 05/10] scsi: use buffer for print_opcode_name()
Instead of printing directly to syslog print_opcode_name() should be using a private buffer to avoid linebreaks during printout. Cc: Kay Sievers k...@vrfy.org Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/constants.c | 98 +++-- 1 files changed, 59 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 76e4c03..b469798 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -204,9 +204,10 @@ static const char * get_sa_name(const struct value_name_pair * arr, } /* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */ -static void print_opcode_name(unsigned char * cdbp, int cdb_len) +static int print_opcode_name(char *buf, int buf_len, + unsigned char *cdbp, int cdb_len) { - int sa, len, cdb0; + int sa, len, cdb0, sz = 0; const char * name; cdb0 = cdbp[0]; @@ -214,101 +215,119 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) case VARIABLE_LENGTH_CMD: len = scsi_varlen_cdb_length(cdbp); if (len 10) { - printk(short variable length command, - len=%d ext_len=%d, len, cdb_len); - break; + sz = snprintf(buf, buf_len, + short variable length command, + len=%d ext_len=%d, len, cdb_len); + return sz; } sa = (cdbp[8] 8) + cdbp[9]; name = get_sa_name(variable_length_arr, VARIABLE_LENGTH_SZ, sa); if (name) - printk(%s, name); + sz = snprintf(buf, buf_len, %s, name); else - printk(cdb[0]=0x%x, sa=0x%x, cdb0, sa); + sz = snprintf(buf, buf_len, cdb[0]=0x%x, sa=0x%x, + cdb0, sa); if ((cdb_len 0) (len != cdb_len)) - printk(, in_cdb_len=%d, ext_len=%d, len, cdb_len); + sz = snprintf(buf + sz, buf_len - sz, + , in_cdb_len=%d, ext_len=%d, + len, cdb_len); break; case MAINTENANCE_IN: sa = cdbp[1] 0x1f; name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa); if (name) - printk(%s, name); + sz = snprintf(buf, buf_len, %s, name); else - printk(cdb[0]=0x%x, sa=0x%x, cdb0, sa); + sz = snprintf(buf, buf_len, cdb[0]=0x%x, sa=0x%x, + cdb0, sa); break; case MAINTENANCE_OUT: sa = cdbp[1] 0x1f; name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa); if (name) - printk(%s, name); + sz = snprintf(buf, buf_len, %s, name); else - printk(cdb[0]=0x%x, sa=0x%x, cdb0, sa); + sz = snprintf(buf, buf_len, cdb[0]=0x%x, sa=0x%x, + cdb0, sa); break; case SERVICE_ACTION_IN_12: sa = cdbp[1] 0x1f; name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa); if (name) - printk(%s, name); + sz = snprintf(buf, buf_len, %s, name); else - printk(cdb[0]=0x%x, sa=0x%x, cdb0, sa); + sz = snprintf(buf, buf_len, cdb[0]=0x%x, sa=0x%x, + cdb0, sa); break; case SERVICE_ACTION_OUT_12: sa = cdbp[1] 0x1f; name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa); if (name) - printk(%s, name); + sz = snprintf(buf, buf_len, %s, name); else - printk(cdb[0]=0x%x, sa=0x%x, cdb0, sa); + sz = snprintf(buf, buf_len, cdb[0]=0x%x, sa=0x%x, + cdb0, sa); break; case SERVICE_ACTION_IN_16: sa = cdbp[1] 0x1f; name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa); if (name) - printk(%s, name); + sz = snprintf(buf, buf_len, %s, name); else - printk(cdb[0]=0x%x, sa=0x%x, cdb0, sa); + sz = snprintf(buf, buf_len, cdb[0]=0x%x, sa=0x%x, + cdb0, sa); break; case SERVICE_ACTION_OUT_16: sa = cdbp[1] 0x1f; name =
[PATCH 07/10] scsi: use buffer for scsi_show_result()
scsi_show_result() should be printing the message into a supplied buffer to avoid linebreaks during output. Cc: Kay Sievers k...@vrfy.org Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/constants.c | 23 +-- drivers/scsi/sd.c|6 -- include/scsi/scsi_dbg.h |2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 65367e8..ded16d9 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1502,32 +1502,35 @@ static const char * const driverbyte_table[]={ DRIVER_INVALID, DRIVER_TIMEOUT, DRIVER_HARD, DRIVER_SENSE}; #define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table) -void scsi_show_result(int result) +void scsi_show_result(char *buf, int buf_size, int result) { int hb = host_byte(result); int db = driver_byte(result); - printk(Result: hostbyte=%s driverbyte=%s\n, - (hb NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : invalid), - (db NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : invalid)); + snprintf(buf, buf_size, + Result: hostbyte=%s driverbyte=%s\n, + (hb NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : invalid), + (db NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : invalid)); } #else -void scsi_show_result(int result) +void scsi_show_result(char *buf, int buf_size, int result) { - printk(Result: hostbyte=0x%02x driverbyte=0x%02x\n, - host_byte(result), driver_byte(result)); + snprintf(buf, buf_size, +Result: hostbyte=0x%02x driverbyte=0x%02x\n, +host_byte(result), driver_byte(result)); } #endif EXPORT_SYMBOL(scsi_show_result); - void scsi_print_result(struct scsi_cmnd *cmd) { - scmd_printk(KERN_INFO, cmd, ); - scsi_show_result(cmd-result); + char result_buf[70]; + + scsi_show_result(result_buf, 70, cmd-result); + scmd_printk(KERN_INFO, cmd, %s, result_buf); } EXPORT_SYMBOL(scsi_print_result); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 12f6fdf..f6165e6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3025,7 +3025,9 @@ static void sd_print_sense_hdr(struct scsi_disk *sdkp, static void sd_print_result(struct scsi_disk *sdkp, int result) { - sd_printk(KERN_INFO, sdkp, ); - scsi_show_result(result); + char result_buf[70]; + + scsi_show_result(result_buf, 70, result); + sd_printk(KERN_INFO, sdkp, %s, result_buf); } diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index e89844c..cc6abb4 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -15,7 +15,7 @@ extern void scsi_print_sense(char *, struct scsi_cmnd *); extern void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, int sense_len); -extern void scsi_show_result(int); +extern void scsi_show_result(char *, int, int); extern void scsi_print_result(struct scsi_cmnd *); extern void scsi_print_status(unsigned char); extern const char *scsi_sense_key_string(unsigned char); -- 1.7.4.2 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/10] scsi: open-code scsi_decode_sense_buffer()
Pointless, and actually wrong as there is no point in trying to decode invalid sense data. Cc: Kay Sievers k...@vrfy.org Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/constants.c | 43 +-- 1 files changed, 17 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index ded16d9..8bf2616 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1373,29 +1373,6 @@ scsi_cmd_print_sense_hdr(struct scsi_cmnd *scmd, const char *desc, EXPORT_SYMBOL(scsi_cmd_print_sense_hdr); static void -scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len, - struct scsi_sense_hdr *sshdr) -{ - int k, num, res; - - res = scsi_normalize_sense(sense_buffer, sense_len, sshdr); - if (0 == res) { - /* this may be SCSI-1 sense data */ - num = (sense_len 32) ? sense_len : 32; - printk(Unrecognized sense data (in hex):); - for (k = 0; k num; ++k) { - if (0 == (k % 16)) { - printk(\n); - printk(KERN_INFO ); - } - printk(%02x , sense_buffer[k]); - } - printk(\n); - return; - } -} - -static void scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len, struct scsi_sense_hdr *sshdr) { @@ -1462,8 +1439,15 @@ void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, { struct scsi_sense_hdr sshdr; + if (!scsi_normalize_sense(sense_buffer, sense_len, sshdr)) { + /* this may be SCSI-1 sense data */ + int num = (sense_len 32) ? sense_len : 32; + pr_info(%s: Unrecognized sense data (in hex):, name); + print_hex_dump(KERN_INFO, , DUMP_PREFIX_OFFSET, + 16, 1, sense_buffer, num, false); + return; + } printk(KERN_INFO %s: , name); - scsi_decode_sense_buffer(sense_buffer, sense_len, sshdr); scsi_show_sense_hdr(sshdr); scsi_decode_sense_extras(sense_buffer, sense_len, sshdr); printk(KERN_INFO %s: , name); @@ -1476,9 +1460,16 @@ void scsi_print_sense(char *name, struct scsi_cmnd *cmd) { struct scsi_sense_hdr sshdr; + if (!scsi_normalize_sense(cmd-sense_buffer, SCSI_SENSE_BUFFERSIZE, + sshdr)) { + scmd_printk(KERN_INFO, cmd, + Unrecognized sense data (in hex):); + print_hex_dump(KERN_INFO, , DUMP_PREFIX_OFFSET, + 16, 1, cmd-sense_buffer, SCSI_SENSE_BUFFERSIZE, + false); + return; + } scmd_printk(KERN_INFO, cmd, ); - scsi_decode_sense_buffer(cmd-sense_buffer, SCSI_SENSE_BUFFERSIZE, -sshdr); scsi_show_sense_hdr(sshdr); scsi_decode_sense_extras(cmd-sense_buffer, SCSI_SENSE_BUFFERSIZE, sshdr); -- 1.7.4.2 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/10] scsi: decode descriptor sense
Decode descriptor sense buffer to provide the same information as we are already getting from fixed format sense. Cc: Kay Sievers k...@vrfy.org Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/constants.c | 79 +++-- drivers/scsi/scsi_error.c | 43 +++- include/scsi/scsi_eh.h|8 +++- 3 files changed, 73 insertions(+), 57 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 8bf2616..df69ba3 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1376,61 +1376,34 @@ static void scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len, struct scsi_sense_hdr *sshdr) { - int k, num, res; - - if (sshdr-response_code 0x72) - { - /* only decode extras for fixed format now */ - char buff[80]; - int blen, fixed_valid; - unsigned int info; - - fixed_valid = sense_buffer[0] 0x80; - info = ((sense_buffer[3] 24) | (sense_buffer[4] 16) | - (sense_buffer[5] 8) | sense_buffer[6]); - res = 0; - memset(buff, 0, sizeof(buff)); - blen = sizeof(buff) - 1; - if (fixed_valid) - res += snprintf(buff + res, blen - res, - Info fld=0x%x, info); - if (sense_buffer[2] 0x80) { - /* current command has read a filemark */ - if (res 0) - res += snprintf(buff + res, blen - res, , ); - res += snprintf(buff + res, blen - res, FMK); - } - if (sense_buffer[2] 0x40) { - /* end-of-medium condition exists */ - if (res 0) - res += snprintf(buff + res, blen - res, , ); - res += snprintf(buff + res, blen - res, EOM); - } - if (sense_buffer[2] 0x20) { - /* incorrect block length requested */ - if (res 0) - res += snprintf(buff + res, blen - res, , ); - res += snprintf(buff + res, blen - res, ILI); - } - if (res 0) - printk(%s\n, buff); - } else if (sshdr-additional_length 0) { - /* descriptor format with sense descriptors */ - num = 8 + sshdr-additional_length; - num = (sense_len num) ? sense_len : num; - printk(Descriptor sense data with sense descriptors - (in hex):); - for (k = 0; k num; ++k) { - if (0 == (k % 16)) { - printk(\n); - printk(KERN_INFO ); - } - printk(%02x , sense_buffer[k]); - } + int res = 0; + char buff[80]; + int blen = sense_len; - printk(\n); - } + if (sshdr-info) + res += snprintf(buff + res, blen - res, + Info fld=0x%llx, sshdr-info); + if (sshdr-flags SCSI_SENSE_FLAG_FMK) { + /* current command has read a filemark */ + if (res 0) + res += snprintf(buff + res, blen - res, , ); + res += snprintf(buff + res, blen - res, FMK); + } + if (sshdr-flags SCSI_SENSE_FLAG_EOM) { + /* end-of-medium condition exists */ + if (res 0) + res += snprintf(buff + res, blen - res, , ); + res += snprintf(buff + res, blen - res, EOM); + } + if (sshdr-flags SCSI_SENSE_FLAG_ILI) { + /* incorrect block length requested */ + if (res 0) + res += snprintf(buff + res, blen - res, , ); + res += snprintf(buff + res, blen - res, ILI); + } + if (res 0) + pr_info(%s\n, buff); } /* Normalize and print sense buffer with name prefix */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index f8d51c5..e8ff276 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2086,7 +2086,7 @@ EXPORT_SYMBOL(scsi_reset_provider); * 1 if valid sense data information found, else 0; */ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, - struct scsi_sense_hdr *sshdr) +struct scsi_sense_hdr *sshdr) { if (!sense_buffer || !sb_len) return 0; @@ -2099,6 +2099,9 @@ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, return 0; if (sshdr-response_code = 0x72) { + int i; + const char
[PATCH 06/10] scsi: use single printk call in scsi_print_command()
scsi_print_command is using several calls to printk(), causing the output to be garbled. Modify it to use a single call to printk(). Cc: Kay Sievers k...@vrfy.org Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/constants.c | 71 +++-- 1 files changed, 61 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index b469798..65367e8 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -349,34 +349,85 @@ static int print_opcode_name(char *buf, int buf_len, void __scsi_print_command(unsigned char *cdb) { - int k, len; + int k, len, rem, linelen; char cdb_str[64]; + char line[16 * 3 + 1]; print_opcode_name(cdb_str, 64, cdb, 0); - pr_info(%s, cdb_str); len = scsi_command_size(cdb); /* print out all bytes in cdb */ - for (k = 0; k len; ++k) - printk( %02x, cdb[k]); - printk(\n); + switch (len) { + case 6: + pr_info(%s %6ph\n, cdb_str, cdb); + break; + case 10: + pr_info(%s %10ph\n, cdb_str, cdb); + break; + case 12: + pr_info(%s %12ph\n, cdb_str, cdb); + break; + case 16: + pr_info(%s %16ph\n, cdb_str, cdb); + break; + default: + pr_info(%s\n, cdb_str); + rem = len; + for (k = 0; k len; k += 16) { + linelen = min(rem, 16); + rem -= 16; + + hex_dump_to_buffer(cdb + k, linelen, 16, 1, + line, sizeof(line), false); + pr_info(%s\n, line); + } + break; + } } EXPORT_SYMBOL(__scsi_print_command); void scsi_print_command(struct scsi_cmnd *cmd) { - int k; + int k, rem, linelen; char cdb_str[64]; + char line[16 * 3 + 1]; if (cmd-cmnd == NULL) return; print_opcode_name(cdb_str, 64, cmd-cmnd, cmd-cmd_len); - scmd_printk(KERN_INFO, cmd, CDB: %s:, cdb_str); /* print out all bytes in cdb */ - for (k = 0; k cmd-cmd_len; ++k) - printk( %02x, cmd-cmnd[k]); - printk(\n); + switch (cmd-cmd_len) { + case 6: + scmd_printk(KERN_INFO, cmd, CDB: %s: %6ph\n, + cdb_str, cmd-cmnd); + break; + case 10: + scmd_printk(KERN_INFO, cmd, CDB: %s: %10ph\n, + cdb_str, cmd-cmnd); + break; + case 12: + scmd_printk(KERN_INFO, cmd, CDB: %s: %12ph\n, + cdb_str, cmd-cmnd); + break; + case 16: + scmd_printk(KERN_INFO, cmd, CDB: %s: %16ph\n, + cdb_str, cmd-cmnd); + break; + default: + scmd_printk(KERN_INFO, cmd, CDB: %s\n, cdb_str); + rem = cmd-cmd_len; + for (k = 0; k cmd-cmd_len; k += 16) { + linelen = min(rem, 16); + rem -= 16; + + hex_dump_to_buffer(cmd-cmnd + k, linelen, 16, 1, + line, sizeof(line), false); + scmd_printk(KERN_INFO, cmd, %d: %s\n, + k, line); + } + break; + } } EXPORT_SYMBOL(scsi_print_command); -- 1.7.4.2 -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/10] scsi: use local buffer for decoding sense data
Instead of printing directly to console we should be using a local buffer for formatting sense data. This will avoid garbled output. Cc: Kay Sievers k...@vrfy.org Signed-off-by: Hannes Reinecke h...@suse.de --- drivers/scsi/constants.c | 102 + drivers/scsi/sd.c| 10 +++-- include/scsi/scsi_dbg.h |4 +- 3 files changed, 65 insertions(+), 51 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index df69ba3..9115233 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1299,49 +1299,52 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq) { EXPORT_SYMBOL(scsi_extd_sense_format); void -scsi_show_extd_sense(unsigned char asc, unsigned char ascq) +scsi_show_extd_sense(char *buf, int buf_len, +unsigned char asc, unsigned char ascq) { -const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq); + const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq); + int sz = 0; if (extd_sense_fmt) { if (strstr(extd_sense_fmt, %x)) { - printk(Add. Sense: ); - printk(extd_sense_fmt, ascq); + sz = snprintf(buf, buf_len, Add. Sense: ); + sz += snprintf(buf + sz, buf_len - sz, + extd_sense_fmt, ascq); } else - printk(Add. Sense: %s, extd_sense_fmt); + sz = snprintf(buf, buf_len, Add. Sense: %s, + extd_sense_fmt); } else { if (asc = 0x80) - printk(vendor ASC=0x%x ASCQ=0x%x, asc, - ascq); - if (ascq = 0x80) - printk(ASC=0x%x vendor ASCQ=0x%x, asc, - ascq); + snprintf(buf, buf_len, vendor ASC=0x%x ASCQ=0x%x, +asc, ascq); + else if (ascq = 0x80) + snprintf(buf, buf_len, ASC=0x%x vendor ASCQ=0x%x, +asc, ascq); else - printk(ASC=0x%x ASCQ=0x%x, asc, ascq); + snprintf(buf, buf_len, ASC=0x%x ASCQ=0x%x, asc, ascq); } - - printk(\n); } EXPORT_SYMBOL(scsi_show_extd_sense); void -scsi_show_sense_hdr(struct scsi_sense_hdr *sshdr) +scsi_show_sense_hdr(char *buf, int buf_len, struct scsi_sense_hdr *sshdr) { const char *sense_txt; + int sz; sense_txt = scsi_sense_key_string(sshdr-sense_key); if (sense_txt) - printk(Sense Key : %s , sense_txt); + sz = snprintf(buf, buf_len, Sense Key : %s , sense_txt); else - printk(Sense Key : 0x%x , sshdr-sense_key); + sz = snprintf(buf, buf_len, Sense Key : 0x%x , + sshdr-sense_key); - printk(%s, scsi_sense_is_deferred(sshdr) ? [deferred] : - [current] ); + sz += snprintf(buf + sz, buf_len - sz, %s, + scsi_sense_is_deferred(sshdr) ? + [deferred] : [current] ); if (sshdr-response_code = 0x72) - printk([descriptor]); - - printk(\n); + sz += snprintf(buf + sz, buf_len - sz, [descriptor]); } EXPORT_SYMBOL(scsi_show_sense_hdr); @@ -1351,10 +1354,12 @@ EXPORT_SYMBOL(scsi_show_sense_hdr); void scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) { - printk(KERN_INFO %s: , name); - scsi_show_sense_hdr(sshdr); - printk(KERN_INFO %s: , name); - scsi_show_extd_sense(sshdr-asc, sshdr-ascq); + char sense_buf[128]; + + scsi_show_sense_hdr(sense_buf, 128, sshdr); + pr_info(%s: %s, name, sense_buf); + scsi_show_extd_sense(sense_buf, 128, sshdr-asc, sshdr-ascq); + pr_info(%s: %s, name, sense_buf); } EXPORT_SYMBOL(scsi_print_sense_hdr); @@ -1365,20 +1370,21 @@ void scsi_cmd_print_sense_hdr(struct scsi_cmnd *scmd, const char *desc, struct scsi_sense_hdr *sshdr) { - scmd_printk(KERN_INFO, scmd, %s: , desc); - scsi_show_sense_hdr(sshdr); - scmd_printk(KERN_INFO, scmd, %s: , desc); - scsi_show_extd_sense(sshdr-asc, sshdr-ascq); + char sense_buf[128]; + + scsi_show_sense_hdr(sense_buf, 128, sshdr); + scmd_printk(KERN_INFO, scmd, %s: %s, desc, sense_buf); + scsi_show_extd_sense(sense_buf, 128, sshdr-asc, sshdr-ascq); + scmd_printk(KERN_INFO, scmd, %s: %s, desc, sense_buf); } EXPORT_SYMBOL(scsi_cmd_print_sense_hdr); -static void -scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len, +static int +scsi_decode_sense_extras(char *buff, int buff_len, struct scsi_sense_hdr *sshdr) { int res = 0; - char buff[80]; - int blen =
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN a//drivers/scsi/arcmsr/arcmsr.h b//drivers/scsi/arcmsr/arcmsr.h --- a//drivers/scsi/arcmsr/arcmsr.h 2012-10-12 16:28:42.175958900 +0800 +++ b//drivers/scsi/arcmsr/arcmsr.h 2012-10-12 16:29:10.215958628 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN0x26000 -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #ifndef PCI_DEVICE_ID_ARECA_1880 #define PCI_DEVICE_ID_ARECA_18800x1880 #endif @@ -511,6 +512,7 @@ struct AdapterControlBlock struct pci_dev *pdev; struct Scsi_Host *host; unsigned long vir2phy_offset; + struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; /* Offset is used in making arc cdb physical to virtual calculations */ uint32_t outbound_int_enable; uint32_t cdb_phyaddr_hi32; @@ -547,6 +549,8 @@ struct AdapterControlBlock /* iop init */ #define ACB_F_ABORT 0x0200 #define ACB_F_FIRMWARE_TRAP 0x0400 + #define ACB_F_MSI_ENABLED 0x1000 + #define ACB_F_MSIX_ENABLED 0x2000 struct CommandControlBlock *pccb_pool[ARCMSR_MAX_FREECCB_NUM]; /* used for memory free */ struct list_head ccb_free_list; diff -uprN a//drivers/scsi/arcmsr/arcmsr_hba.c b//drivers/scsi/arcmsr/arcmsr_hba.c --- a//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:28:42.175958900 +0800 +++ b//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:29:10.239958629 +0800 @@ -89,11 +89,18 @@ static int arcmsr_bios_param(struct scsi static int arcmsr_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd); static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id); +#ifdef CONFIG_PM + static int arcmsr_suspend(struct pci_dev *pdev, + pm_message_t state); + static int arcmsr_resume(struct pci_dev *pdev); +#endif static void arcmsr_remove(struct pci_dev *pdev); static void arcmsr_shutdown(struct pci_dev *pdev); static void arcmsr_iop_init(struct AdapterControlBlock *acb); static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); +static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, + u32 orig_mask); static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -166,6 +173,10 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + #ifdef CONFIG_PM + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, + #endif .shutdown = arcmsr_shutdown, }; /* @@ -662,6 +673,134 @@ arcmsr_message_isr_bh_fn(struct work_str } } +#ifdef CONFIG_PM + static int + arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) + { + int i; + uint32_t intmask_org; + struct Scsi_Host *host = pci_get_drvdata(pdev); + struct AdapterControlBlock *acb = + (struct AdapterControlBlock *)host-hostdata; + + intmask_org = arcmsr_disable_outbound_ints(acb); + if (acb-acb_flags ACB_F_MSI_ENABLED) { + free_irq(pdev-irq, acb); + pci_disable_msi(pdev); + } else if (acb-acb_flags ACB_F_MSIX_ENABLED) { + for (i = 0; i ARCMST_NUM_MSIX_VECTORS; i++) { + free_irq(acb-entries[i].vector, acb); + } + pci_disable_msix(pdev); + } else { + free_irq(pdev-irq, acb); + } + del_timer_sync(acb-eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + pci_set_drvdata(pdev, host); + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; + } + + static int + arcmsr_resume(struct pci_dev *pdev) + { + int error, i,
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN a//drivers/scsi/arcmsr/arcmsr_hba.c b//drivers/scsi/arcmsr/arcmsr_hba.c --- a//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:34:58.219955247 +0800 +++ b//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:35:16.267955072 +0800 @@ -805,8 +805,9 @@ static int arcmsr_probe(struct pci_dev * { struct Scsi_Host *host; struct AdapterControlBlock *acb; - uint8_t bus,dev_fun; - int error; + uint8_t bus, dev_fun; + struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; + int error, i, j; error = pci_enable_device(pdev); if (error) { return -ENODEV; @@ -871,10 +872,46 @@ static int arcmsr_probe(struct pci_dev * if (error) { goto RAID_controller_stop; } - error = request_irq(pdev-irq, arcmsr_do_interrupt, - IRQF_SHARED, arcmsr, acb); - if (error) { - goto scsi_host_remove; + if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { + if (!pci_enable_msix(pdev, entries, ARCMST_NUM_MSIX_VECTORS)) { + for (i = 0; i ARCMST_NUM_MSIX_VECTORS; i++) { + entries[i].entry = i; + if (request_irq(entries[i].vector, + arcmsr_do_interrupt, 0, arcmsr, + acb)) { + for (j = 0 ; j i ; j++) + free_irq(entries[i].vector, + acb); + goto scsi_host_remove; + } + acb-entries[i] = entries[i]; + } + acb-acb_flags |= ACB_F_MSIX_ENABLED; + } else { + if (request_irq(pdev-irq, arcmsr_do_interrupt, + IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, + acb-host-host_no, pdev-irq); + goto scsi_host_remove; + } + } + } else if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { + if (!pci_enable_msi(pdev)) { + acb-acb_flags |= ACB_F_MSI_ENABLED; + } + if (request_irq(pdev-irq, arcmsr_do_interrupt, + IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, + acb-host-host_no, pdev-irq); + goto scsi_host_remove; + } + } else { + if (request_irq(pdev-irq, arcmsr_do_interrupt, + IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, + acb-host-host_no, pdev-irq); + goto scsi_host_remove; + } } host-irq = pdev-irq; scsi_scan_host(host); @@ -895,6 +932,11 @@ static int arcmsr_probe(struct pci_dev * return 0; out_free_sysfs: scsi_host_remove: + if (acb-acb_flags ACB_F_MSI_ENABLED) { + pci_disable_msi(pdev); + } else if (acb-acb_flags ACB_F_MSIX_ENABLED) { + pci_disable_msix(pdev); + } scsi_remove_host(host); RAID_controller_stop: arcmsr_stop_adapter_bgrb(acb); -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 01/10] sg: Use dev_printk
On 12-10-12 04:33 AM, Hannes Reinecke wrote: Every sg device has a reference to the underlying scsi device, so this patch adds dev_printk() macros to have the messages prefixed with the correct device. Before: [772330.437378] sg_open: dev=2, flags=0x8800 [772330.475425] sg_add_sfp: sfp=0x880429d3e000 After: [ 409.399888] sr 2:0:0:0: [sg2] sg_open: flags=0x8800 [ 409.446029] sr 2:0:0:0: [sg2] sg_add_sfp: sfp=0x880425856000 Cc: Kay Sievers k...@vrfy.org Cc: Doug Gilbert dgilb...@interlog.com Signed-off-by: Hannes Reinecke h...@suse.de Acked-by: Douglas Gilbert dgilb...@interlog.com -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 0/5] Migrate SCSI drivers to use dev_pm_ops
On Fri, 12 Oct 2012, Aaron Lu wrote: v3: Only patch 4 is modified: Remove the special case for system freeze in scsi_bus_suspend_common as pointed out by Alan Stern; Updated some comments; Removed the use of typedef (*pm_callback_t)(struct device *). v2: Change the runtime suspend behaviour of sd driver by putting the device into stopped power state. Revert 2 patches which are no longer needed as pointed out by Alan Stern. Find out device callbacks in bus callbacks as suggested by Alan Stern. Due to these changes, patch number grows from 2 - 5. v1: The 2 patches will migrate SCSI drivers to use the pm callbacks defined in dev_pm_ops as pm_message is deprecated and should not be used by driver. Bus level callback is changed to use callbacks defined in dev_pm_ops when needed and sd's pm callback is updated to use what are defined in dev_pm_ops. Aaron Lu (5): sd: put to stopped power state when runtime suspend Revert [SCSI] scsi_pm: set device runtime state before parent suspended Revert [SCSI] runtime resume parent for child's system-resume pm: use callbacks from dev_pm_ops for scsi devices sd: update sd to use the new pm callbacks drivers/scsi/scsi_pm.c | 97 +++--- drivers/scsi/sd.c | 18 +++--- 2 files changed, 66 insertions(+), 49 deletions(-) Remember to run all the patches through checkpatch.pl before submitting them. Aside from that, for the whole series: Acked-by: Alan Stern st...@rowland.harvard.edu -- To unsubscribe from this list: send the line unsubscribe linux-scsi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html