File Index
Files and directories
Sign in
FILE

zfcp_ccw.c

File preview with syntax highlighting.

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