/** * zfcp_ccw_activate - activate adapter and wait for it to finish * @cdev: pointer to belonging ccw device * @clear: Status flags to clear. * @tag: s390dbf trace record tag
*/ staticint zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
{ struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
/* * We want to scan ports here, with some random backoff and without * rate limit. Recovery has already scheduled a port scan for us, * but with both random delay and rate limit. Nevertheless we get * what we want here by flushing the scheduled work after sleeping * an equivalent random time. * Let the port scan random delay elapse first. If recovery finishes * up to that point in time, that would be perfect for both recovery * and port scan. If not, i.e. recovery takes ages, there was no * point in waiting a random delay on top of the time consumed by * recovery.
*/
msleep(zfcp_fc_port_scan_backoff());
zfcp_erp_wait(adapter);
flush_delayed_work(&adapter->scan_work);
/** * zfcp_ccw_probe - probe function of zfcp driver * @cdev: pointer to belonging ccw device * * This function gets called by the common i/o layer for each FCP * device found on the current system. This is only a stub to make cio * work: To only allocate adapter resources for devices actually used, * the allocation is deferred to the first call to ccw_set_online.
*/ staticint zfcp_ccw_probe(struct ccw_device *cdev)
{ return 0;
}
/** * zfcp_ccw_remove - remove function of zfcp driver * @cdev: pointer to belonging ccw device * * This function gets called by the common i/o layer and removes an adapter * from the system. Task of this function is to get rid of all units and * ports that belong to this adapter. And in addition all resources of this * adapter will be freed too.
*/ staticvoid zfcp_ccw_remove(struct ccw_device *cdev)
{ struct zfcp_adapter *adapter; struct zfcp_port *port, *p; struct zfcp_unit *unit, *u;
LIST_HEAD(unit_remove_lh);
LIST_HEAD(port_remove_lh);
ccw_device_set_offline(cdev);
adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return;
write_lock_irq(&adapter->port_list_lock);
list_for_each_entry(port, &adapter->port_list, list) {
write_lock(&port->unit_list_lock);
list_splice_init(&port->unit_list, &unit_remove_lh);
write_unlock(&port->unit_list_lock);
}
list_splice_init(&adapter->port_list, &port_remove_lh);
write_unlock_irq(&adapter->port_list_lock);
zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */
list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
device_unregister(&unit->dev);
/** * zfcp_ccw_set_online - set_online function of zfcp driver * @cdev: pointer to belonging ccw device * * This function gets called by the common i/o layer and sets an * adapter into state online. The first call will allocate all * adapter resources that will be retained until the device is removed * via zfcp_ccw_remove. * * Setting an fcp device online means that it will be registered with * the SCSI stack, that the QDIO queues will be set up and that the * adapter will be opened.
*/ staticint zfcp_ccw_set_online(struct ccw_device *cdev)
{ struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
if (!adapter) {
adapter = zfcp_adapter_enqueue(cdev);
if (IS_ERR(adapter)) {
dev_err(&cdev->dev, "Setting up data structures for the " "FCP adapter failed\n"); return PTR_ERR(adapter);
}
kref_get(&adapter->ref);
}
/* * We want to scan ports here, always, with some random delay and * without rate limit - basically what zfcp_ccw_activate() has * achieved for us. Not quite! That port scan depended on * !no_auto_port_rescan. So let's cover the no_auto_port_rescan * case here to make sure a port scan is done unconditionally. * Since zfcp_ccw_activate() has waited the desired random time, * we can immediately schedule and flush a port scan for the * remaining cases.
*/
zfcp_fc_inverse_conditional_port_scan(adapter);
flush_delayed_work(&adapter->scan_work);
zfcp_ccw_adapter_put(adapter); return 0;
}
/** * zfcp_ccw_set_offline - set_offline function of zfcp driver * @cdev: pointer to belonging ccw device * * This function gets called by the common i/o layer and sets an adapter * into state offline.
*/ staticint zfcp_ccw_set_offline(struct ccw_device *cdev)
{ struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
/** * zfcp_ccw_notify - ccw notify function * @cdev: pointer to belonging ccw device * @event: indicates if adapter was detached or attached * * This function gets called by the common i/o layer if an adapter has gone * or reappeared.
*/ staticint zfcp_ccw_notify(struct ccw_device *cdev, int event)
{ struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
if (!adapter) return 1;
switch (event) { case CIO_GONE:
dev_warn(&cdev->dev, "The FCP device has been detached\n");
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); break; case CIO_NO_PATH:
dev_warn(&cdev->dev, "The CHPID for the FCP device is offline\n");
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); break; case CIO_OPER:
dev_info(&cdev->dev, "The FCP device is operational again\n");
zfcp_erp_set_adapter_status(adapter,
ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, "ccnoti4"); break; case CIO_BOXED:
dev_warn(&cdev->dev, "The FCP device did not respond within " "the specified time\n");
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5"); break;
}
zfcp_ccw_adapter_put(adapter); return 1;
}
/** * zfcp_ccw_shutdown - handle shutdown from cio * @cdev: device for adapter to shutdown.
*/ staticvoid zfcp_ccw_shutdown(struct ccw_device *cdev)
{ struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.