static int scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *, const struct dev_pm_ops *)) { async_func_t fn; if (!scsi_is_sdev_device(dev)) fn = NULL; else if (cb == do_scsi_resume) fn = async_sdev_resume; else if (cb == do_scsi_thaw) fn = async_sdev_thaw; else if (cb == do_scsi_restore) fn = async_sdev_restore; else fn = NULL; if (fn) { async_schedule_domain(fn, dev, &scsi_sd_pm_domain); /* * If a user has disabled async probing a likely reason * is due to a storage enclosure that does not inject * staggered spin-ups. For safety, make resume * synchronous as well in that case. */ if (strncmp(scsi_scan_type, "async", 5) != 0) async_synchronize_full_domain(&scsi_sd_pm_domain); } else { pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); } return 0; }
static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg) { int err = 0; if (scsi_is_sdev_device(dev)) err = scsi_dev_type_suspend(dev, msg); return err; }
static int scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *, const struct dev_pm_ops *)) { async_func_t fn; if (!scsi_is_sdev_device(dev)) fn = NULL; else if (cb == do_scsi_resume) fn = async_sdev_resume; else if (cb == do_scsi_thaw) fn = async_sdev_thaw; else if (cb == do_scsi_restore) fn = async_sdev_restore; else fn = NULL; /* * Forcibly set runtime PM status of request queue to "active" to * make sure we can again get requests from the queue (see also * blk_pm_peek_request()). * * The resume hook will correct runtime PM status of the disk. */ if (scsi_is_sdev_device(dev) && pm_runtime_suspended(dev)) blk_set_runtime_active(to_scsi_device(dev)->request_queue); if (fn) { async_schedule_domain(fn, dev, &scsi_sd_pm_domain); /* * If a user has disabled async probing a likely reason * is due to a storage enclosure that does not inject * staggered spin-ups. For safety, make resume * synchronous as well in that case. */ if (strncmp(scsi_scan_type, "async", 5) != 0) async_synchronize_full_domain(&scsi_sd_pm_domain); } else { pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); } return 0; }
static int scsi_runtime_resume(struct device *dev) { int err = 0; dev_dbg(dev, "scsi_runtime_resume\n"); if (scsi_is_sdev_device(dev)) err = scsi_dev_type_resume(dev); /* Insert hooks here for targets, hosts, and transport classes */ return err; }
static int scsi_bus_prepare(struct device *dev) { if (scsi_is_sdev_device(dev)) { async_synchronize_full(); } else if (scsi_is_host_device(dev)) { scsi_complete_async_scans(); } return 0; }
static int scsi_runtime_resume(struct device *dev) { int err = 0; dev_dbg(dev, "scsi_runtime_resume\n"); if (scsi_is_sdev_device(dev)) err = scsi_dev_type_resume(dev); return err; }
static int scsi_bus_prepare(struct device *dev) { if (scsi_is_sdev_device(dev)) { /* sd probing uses async_schedule. Wait until it finishes. */ async_synchronize_full(); } else if (scsi_is_host_device(dev)) { /* Wait until async scanning is finished */ scsi_complete_async_scans(); } return 0; }
static int scsi_runtime_idle(struct device *dev) { int err; dev_dbg(dev, "scsi_runtime_idle\n"); /* Insert hooks here for targets, hosts, and transport classes */ if (scsi_is_sdev_device(dev)) err = pm_schedule_suspend(dev, 100); else err = pm_runtime_suspend(dev); return err; }
static int scsi_runtime_idle(struct device *dev) { int err; dev_dbg(dev, "scsi_runtime_idle\n"); if (scsi_is_sdev_device(dev)) err = pm_schedule_suspend(dev, 100); else err = pm_runtime_suspend(dev); return err; }
static int scsi_bus_resume_common(struct device *dev) { int err = 0; if (scsi_is_sdev_device(dev)) err = scsi_dev_type_resume(dev); if (err == 0) { pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); } return err; }
static int scsi_runtime_idle(struct device *dev) { dev_dbg(dev, "scsi_runtime_idle\n"); /* Insert hooks here for targets, hosts, and transport classes */ if (scsi_is_sdev_device(dev)) { pm_runtime_mark_last_busy(dev); pm_runtime_autosuspend(dev); return -EBUSY; } return 0; }
/** * proc_print_scsidevice - return data about this host * @dev: A scsi device * @data: &struct seq_file to output to. * * Description: prints Host, Channel, Id, Lun, Vendor, Model, Rev, Type, * and revision. */ static int proc_print_scsidevice(struct device *dev, void *data) { struct scsi_device *sdev; struct seq_file *s = data; int i; if (!scsi_is_sdev_device(dev)) goto out; sdev = to_scsi_device(dev); seq_printf(s, "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); for (i = 0; i < 8; i++) { if (sdev->vendor[i] >= 0x20) seq_printf(s, "%c", sdev->vendor[i]); else seq_printf(s, " "); } seq_printf(s, " Model: "); for (i = 0; i < 16; i++) { if (sdev->model[i] >= 0x20) seq_printf(s, "%c", sdev->model[i]); else seq_printf(s, " "); } seq_printf(s, " Rev: "); for (i = 0; i < 4; i++) { if (sdev->rev[i] >= 0x20) seq_printf(s, "%c", sdev->rev[i]); else seq_printf(s, " "); } seq_printf(s, "\n"); seq_printf(s, " Type: %s ", scsi_device_type(sdev->type)); seq_printf(s, " ANSI SCSI revision: %02x", sdev->scsi_level - (sdev->scsi_level > 1)); if (sdev->scsi_level == 2) seq_printf(s, " CCS\n"); else seq_printf(s, "\n"); out: return 0; }
static int scsi_runtime_suspend(struct device *dev) { int err = 0; dev_dbg(dev, "scsi_runtime_suspend\n"); if (scsi_is_sdev_device(dev)) { err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND); if (err == -EAGAIN) pm_schedule_suspend(dev, jiffies_to_msecs( round_jiffies_up_relative(HZ/10))); } return err; }
static int scsi_runtime_suspend(struct device *dev) { int err = 0; dev_dbg(dev, "scsi_runtime_suspend\n"); if (scsi_is_sdev_device(dev)) { err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND); if (err == -EAGAIN) pm_schedule_suspend(dev, jiffies_to_msecs( round_jiffies_up_relative(HZ/10))); } /* Insert hooks here for targets, hosts, and transport classes */ return err; }
static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg) { int err = 0; if (scsi_is_sdev_device(dev)) { if (pm_runtime_suspended(dev)) { if (msg.event == PM_EVENT_SUSPEND || msg.event == PM_EVENT_HIBERNATE) return 0; pm_runtime_resume(dev); } err = scsi_dev_type_suspend(dev, msg); } return err; }
static int scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *)) { int err = 0; if (scsi_is_sdev_device(dev)) { /* * All the high-level SCSI drivers that implement runtime * PM treat runtime suspend, system suspend, and system * hibernate identically. */ if (pm_runtime_suspended(dev)) return 0; err = scsi_dev_type_suspend(dev, cb); } return err; }
static int scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *, const struct dev_pm_ops *)) { int err = 0; if (scsi_is_sdev_device(dev)) { /* * All the high-level SCSI drivers that implement runtime * PM treat runtime suspend, system suspend, and system * hibernate nearly identically. In all cases the requirements * for runtime suspension are stricter. */ if (pm_runtime_suspended(dev)) return 0; err = scsi_dev_type_suspend(dev, cb); } return err; }
static int scsi_runtime_idle(struct device *dev) { int err; dev_dbg(dev, "scsi_runtime_idle\n"); /* Insert hooks here for targets, hosts, and transport classes */ if (scsi_is_sdev_device(dev)) { struct scsi_device *sdev = to_scsi_device(dev); if (sdev->request_queue->dev) { pm_runtime_mark_last_busy(dev); err = pm_runtime_autosuspend(dev); } else { err = pm_runtime_suspend(dev); } } else { err = pm_runtime_suspend(dev); } return err; }
static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg) { 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). */ if (pm_runtime_suspended(dev)) { if (msg.event == PM_EVENT_SUSPEND || msg.event == PM_EVENT_HIBERNATE) return 0; /* already suspended */ /* wake up device so that FREEZE will succeed */ pm_runtime_resume(dev); } err = scsi_dev_type_suspend(dev, msg); } return err; }
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); err = scsi_dev_type_resume(dev); pm_runtime_put_sync(dev->parent); } if (err == 0) { pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); } return err; }
/* * TODO: need some interface so we can set trespass values */ static int clariion_bus_notify(struct notifier_block *nb, unsigned long action, void *data) { struct device *dev = data; struct scsi_device *sdev; struct scsi_dh_data *scsi_dh_data; struct clariion_dh_data *h; int i, found = 0; unsigned long flags; if (!scsi_is_sdev_device(dev)) return 0; sdev = to_scsi_device(dev); if (action == BUS_NOTIFY_ADD_DEVICE) { for (i = 0; clariion_dev_list[i].vendor; i++) { if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor, strlen(clariion_dev_list[i].vendor)) && !strncmp(sdev->model, clariion_dev_list[i].model, strlen(clariion_dev_list[i].model))) { found = 1; break; } } if (!found) goto out; scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) + sizeof(*h) , GFP_KERNEL); if (!scsi_dh_data) { sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n", CLARIION_NAME); goto out; } scsi_dh_data->scsi_dh = &clariion_dh; h = (struct clariion_dh_data *) scsi_dh_data->buf; h->default_sp = CLARIION_UNBOUND_LU; h->current_sp = CLARIION_UNBOUND_LU; spin_lock_irqsave(sdev->request_queue->queue_lock, flags); sdev->scsi_dh_data = scsi_dh_data; spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME); try_module_get(THIS_MODULE); } else if (action == BUS_NOTIFY_DEL_DEVICE) { if (sdev->scsi_dh_data == NULL || sdev->scsi_dh_data->scsi_dh != &clariion_dh) goto out; spin_lock_irqsave(sdev->request_queue->queue_lock, flags); scsi_dh_data = sdev->scsi_dh_data; sdev->scsi_dh_data = NULL; spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", CLARIION_NAME); kfree(scsi_dh_data); module_put(THIS_MODULE); } out: return 0; }