// SPDX-License-Identifier: GPL-2.0 /* * zfcp device driver * * Module interface and handling of zfcp data structures. * * Copyright IBM Corp. 2002, 2020
*/
/* * Driver authors: * Martin Peschke (originator of the driver) * Raimund Schroeder * Aron Zeh * Wolfgang Taphorn * Stefan Bader * Heiko Carstens (kernel 2.6 port of the driver) * Andreas Herrmann * Maxim Shchetynin * Volker Sameske * Ralph Wuerthner * Michael Loehr * Swen Schillig * Christof Schmitt * Martin Petermann * Sven Schuetz * Steffen Maier * Benjamin Block
*/
err_out:
kfree(str_saved);
pr_err("%s is not a valid SCSI device\n", devstr);
}
staticint __init zfcp_module_init(void)
{ int retval = -ENOMEM;
if (zfcp_experimental_dix)
pr_warn("DIX is enabled. It is experimental and might cause problems\n");
zfcp_fsf_qtcb_cache = zfcp_cache_hw_align("zfcp_fsf_qtcb", sizeof(struct fsf_qtcb)); if (!zfcp_fsf_qtcb_cache) goto out_qtcb_cache;
zfcp_fc_req_cache = zfcp_cache_hw_align("zfcp_fc_req", sizeof(struct zfcp_fc_req)); if (!zfcp_fc_req_cache) goto out_fc_cache;
zfcp_scsi_transport_template =
fc_attach_transport(&zfcp_transport_functions); if (!zfcp_scsi_transport_template) goto out_transport;
scsi_transport_reserve_device(zfcp_scsi_transport_template, sizeof(struct zfcp_scsi_dev));
retval = ccw_driver_register(&zfcp_ccw_driver); if (retval) {
pr_err("The zfcp device driver could not register with " "the common I/O layer\n"); goto out_ccw_register;
}
if (init_device)
zfcp_init_device_setup(init_device); return 0;
/** * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn * @adapter: pointer to adapter to search for port * @wwpn: wwpn to search for * * Returns: pointer to zfcp_port or NULL
*/ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
u64 wwpn)
{ unsignedlong flags; struct zfcp_port *port;
read_lock_irqsave(&adapter->port_list_lock, flags);
list_for_each_entry(port, &adapter->port_list, list) if (port->wwpn == wwpn) { if (!get_device(&port->dev))
port = NULL;
read_unlock_irqrestore(&adapter->port_list_lock, flags); return port;
}
read_unlock_irqrestore(&adapter->port_list_lock, flags); return NULL;
}
/** * zfcp_status_read_refill - refill the long running status_read_requests * @adapter: ptr to struct zfcp_adapter for which the buffers should be refilled * * Return: * * 0 on success meaning at least one status read is pending * * 1 if posting failed and not a single status read buffer is pending, * also triggers adapter reopen recovery
*/ int zfcp_status_read_refill(struct zfcp_adapter *adapter)
{ while (atomic_add_unless(&adapter->stat_miss, -1, 0)) if (zfcp_fsf_status_read(adapter->qdio)) {
atomic_inc(&adapter->stat_miss); /* undo add -1 */ if (atomic_read(&adapter->stat_miss) >=
adapter->stat_read_buf_num) {
zfcp_erp_adapter_reopen(adapter, 0, "axsref1"); return 1;
} break;
} return 0;
}
/** * zfcp_adapter_enqueue - enqueue a new adapter to the list * @ccw_device: pointer to the struct cc_device * * Returns: struct zfcp_adapter* * Enqueues an adapter at the end of the adapter list in the driver data. * All adapter internal structures are set up. * Proc-fs entries are also created.
*/ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
{ struct zfcp_adapter *adapter;
if (!get_device(&ccw_device->dev)) return ERR_PTR(-ENODEV);
err_sysfs:
failed: /* TODO: make this more fine-granular */
cancel_delayed_work_sync(&adapter->scan_work);
cancel_work_sync(&adapter->stat_work);
cancel_work_sync(&adapter->ns_up_work);
cancel_work_sync(&adapter->version_change_lost_work);
zfcp_destroy_adapter_work_queue(adapter);
zfcp_ccw_adapter_put(adapter); /* final put to release */
}
/** * zfcp_adapter_release - remove the adapter from the resource list * @ref: pointer to struct kref * locks: adapter list write lock is assumed to be held by caller
*/ void zfcp_adapter_release(struct kref *ref)
{ struct zfcp_adapter *adapter = container_of(ref, struct zfcp_adapter,
ref); struct ccw_device *cdev = adapter->ccw_device;
/** * zfcp_port_enqueue - enqueue port to port list of adapter * @adapter: adapter where remote port is added * @wwpn: WWPN of the remote port to be enqueued * @status: initial status for the port * @d_id: destination id of the remote port to be enqueued * Returns: pointer to enqueued port on success, ERR_PTR on error * * All port internal structures are set up and the sysfs entry is generated. * d_id is used to enqueue ports with a well known address like the Directory * Service for nameserver lookup.
*/ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
u32 status, u32 d_id)
{ struct zfcp_port *port; int retval = -ENOMEM;
kref_get(&adapter->ref);
port = zfcp_get_port_by_wwpn(adapter, wwpn); if (port) {
put_device(&port->dev);
retval = -EEXIST; goto err_put;
}
port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); if (!port) goto err_put;
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.