brintos

brintos / linux-shallow public Read only

0
0
Text · 8.1 KiB · bdf2cc1 Raw
292 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * zfcp device driver4 *5 * Registration and callback for the s390 common I/O layer.6 *7 * Copyright IBM Corp. 2002, 20108 */9 10#define KMSG_COMPONENT "zfcp"11#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt12 13#include <linux/module.h>14#include "zfcp_ext.h"15#include "zfcp_reqlist.h"16 17#define ZFCP_MODEL_PRIV 0x418 19static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);20 21struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev)22{23	struct zfcp_adapter *adapter;24	unsigned long flags;25 26	spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);27	adapter = dev_get_drvdata(&cdev->dev);28	if (adapter)29		kref_get(&adapter->ref);30	spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);31	return adapter;32}33 34void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)35{36	unsigned long flags;37 38	spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);39	kref_put(&adapter->ref, zfcp_adapter_release);40	spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);41}42 43/**44 * zfcp_ccw_activate - activate adapter and wait for it to finish45 * @cdev: pointer to belonging ccw device46 * @clear: Status flags to clear.47 * @tag: s390dbf trace record tag48 */49static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)50{51	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);52 53	if (!adapter)54		return 0;55 56	zfcp_erp_clear_adapter_status(adapter, clear);57	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);58	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,59				tag);60 61	/*62	 * We want to scan ports here, with some random backoff and without63	 * rate limit. Recovery has already scheduled a port scan for us,64	 * but with both random delay and rate limit. Nevertheless we get65	 * what we want here by flushing the scheduled work after sleeping66	 * an equivalent random time.67	 * Let the port scan random delay elapse first. If recovery finishes68	 * up to that point in time, that would be perfect for both recovery69	 * and port scan. If not, i.e. recovery takes ages, there was no70	 * point in waiting a random delay on top of the time consumed by71	 * recovery.72	 */73	msleep(zfcp_fc_port_scan_backoff());74	zfcp_erp_wait(adapter);75	flush_delayed_work(&adapter->scan_work);76 77	zfcp_ccw_adapter_put(adapter);78 79	return 0;80}81 82static struct ccw_device_id zfcp_ccw_device_id[] = {83	{ CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x3) },84	{ CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, ZFCP_MODEL_PRIV) },85	{},86};87MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);88 89/**90 * zfcp_ccw_probe - probe function of zfcp driver91 * @cdev: pointer to belonging ccw device92 *93 * This function gets called by the common i/o layer for each FCP94 * device found on the current system. This is only a stub to make cio95 * work: To only allocate adapter resources for devices actually used,96 * the allocation is deferred to the first call to ccw_set_online.97 */98static int zfcp_ccw_probe(struct ccw_device *cdev)99{100	return 0;101}102 103/**104 * zfcp_ccw_remove - remove function of zfcp driver105 * @cdev: pointer to belonging ccw device106 *107 * This function gets called by the common i/o layer and removes an adapter108 * from the system. Task of this function is to get rid of all units and109 * ports that belong to this adapter. And in addition all resources of this110 * adapter will be freed too.111 */112static void zfcp_ccw_remove(struct ccw_device *cdev)113{114	struct zfcp_adapter *adapter;115	struct zfcp_port *port, *p;116	struct zfcp_unit *unit, *u;117	LIST_HEAD(unit_remove_lh);118	LIST_HEAD(port_remove_lh);119 120	ccw_device_set_offline(cdev);121 122	adapter = zfcp_ccw_adapter_by_cdev(cdev);123	if (!adapter)124		return;125 126	write_lock_irq(&adapter->port_list_lock);127	list_for_each_entry(port, &adapter->port_list, list) {128		write_lock(&port->unit_list_lock);129		list_splice_init(&port->unit_list, &unit_remove_lh);130		write_unlock(&port->unit_list_lock);131	}132	list_splice_init(&adapter->port_list, &port_remove_lh);133	write_unlock_irq(&adapter->port_list_lock);134	zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */135 136	list_for_each_entry_safe(unit, u, &unit_remove_lh, list)137		device_unregister(&unit->dev);138 139	list_for_each_entry_safe(port, p, &port_remove_lh, list)140		device_unregister(&port->dev);141 142	zfcp_adapter_unregister(adapter);143}144 145/**146 * zfcp_ccw_set_online - set_online function of zfcp driver147 * @cdev: pointer to belonging ccw device148 *149 * This function gets called by the common i/o layer and sets an150 * adapter into state online.  The first call will allocate all151 * adapter resources that will be retained until the device is removed152 * via zfcp_ccw_remove.153 *154 * Setting an fcp device online means that it will be registered with155 * the SCSI stack, that the QDIO queues will be set up and that the156 * adapter will be opened.157 */158static int zfcp_ccw_set_online(struct ccw_device *cdev)159{160	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);161 162	if (!adapter) {163		adapter = zfcp_adapter_enqueue(cdev);164 165		if (IS_ERR(adapter)) {166			dev_err(&cdev->dev,167				"Setting up data structures for the "168				"FCP adapter failed\n");169			return PTR_ERR(adapter);170		}171		kref_get(&adapter->ref);172	}173 174	/* initialize request counter */175	BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));176	adapter->req_no = 0;177 178	zfcp_ccw_activate(cdev, 0, "ccsonl1");179 180	/*181	 * We want to scan ports here, always, with some random delay and182	 * without rate limit - basically what zfcp_ccw_activate() has183	 * achieved for us. Not quite! That port scan depended on184	 * !no_auto_port_rescan. So let's cover the no_auto_port_rescan185	 * case here to make sure a port scan is done unconditionally.186	 * Since zfcp_ccw_activate() has waited the desired random time,187	 * we can immediately schedule and flush a port scan for the188	 * remaining cases.189	 */190	zfcp_fc_inverse_conditional_port_scan(adapter);191	flush_delayed_work(&adapter->scan_work);192	zfcp_ccw_adapter_put(adapter);193	return 0;194}195 196/**197 * zfcp_ccw_set_offline - set_offline function of zfcp driver198 * @cdev: pointer to belonging ccw device199 *200 * This function gets called by the common i/o layer and sets an adapter201 * into state offline.202 */203static int zfcp_ccw_set_offline(struct ccw_device *cdev)204{205	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);206 207	if (!adapter)208		return 0;209 210	zfcp_erp_set_adapter_status(adapter, 0);211	zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1");212	zfcp_erp_wait(adapter);213 214	zfcp_ccw_adapter_put(adapter);215	return 0;216}217 218/**219 * zfcp_ccw_notify - ccw notify function220 * @cdev: pointer to belonging ccw device221 * @event: indicates if adapter was detached or attached222 *223 * This function gets called by the common i/o layer if an adapter has gone224 * or reappeared.225 */226static int zfcp_ccw_notify(struct ccw_device *cdev, int event)227{228	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);229 230	if (!adapter)231		return 1;232 233	switch (event) {234	case CIO_GONE:235		dev_warn(&cdev->dev, "The FCP device has been detached\n");236		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");237		break;238	case CIO_NO_PATH:239		dev_warn(&cdev->dev,240			 "The CHPID for the FCP device is offline\n");241		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");242		break;243	case CIO_OPER:244		dev_info(&cdev->dev, "The FCP device is operational again\n");245		zfcp_erp_set_adapter_status(adapter,246					    ZFCP_STATUS_COMMON_RUNNING);247		zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,248					"ccnoti4");249		break;250	case CIO_BOXED:251		dev_warn(&cdev->dev, "The FCP device did not respond within "252				     "the specified time\n");253		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5");254		break;255	}256 257	zfcp_ccw_adapter_put(adapter);258	return 1;259}260 261/**262 * zfcp_ccw_shutdown - handle shutdown from cio263 * @cdev: device for adapter to shutdown.264 */265static void zfcp_ccw_shutdown(struct ccw_device *cdev)266{267	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);268 269	if (!adapter)270		return;271 272	zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1");273	zfcp_erp_wait(adapter);274	zfcp_erp_thread_kill(adapter);275 276	zfcp_ccw_adapter_put(adapter);277}278 279struct ccw_driver zfcp_ccw_driver = {280	.driver = {281		.owner	= THIS_MODULE,282		.name	= "zfcp",283	},284	.ids         = zfcp_ccw_device_id,285	.probe       = zfcp_ccw_probe,286	.remove      = zfcp_ccw_remove,287	.set_online  = zfcp_ccw_set_online,288	.set_offline = zfcp_ccw_set_offline,289	.notify      = zfcp_ccw_notify,290	.shutdown    = zfcp_ccw_shutdown,291};292