cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

zfcp_ccw.c (8325B)


      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 KMSG_COMPONENT "zfcp"
     11#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
     12
     13#include <linux/module.h>
     14#include "zfcp_ext.h"
     15#include "zfcp_reqlist.h"
     16
     17#define ZFCP_MODEL_PRIV 0x4
     18
     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 finish
     45 * @cdev: pointer to belonging ccw device
     46 * @clear: Status flags to clear.
     47 * @tag: s390dbf trace record tag
     48 */
     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 without
     63	 * rate limit. Recovery has already scheduled a port scan for us,
     64	 * but with both random delay and rate limit. Nevertheless we get
     65	 * what we want here by flushing the scheduled work after sleeping
     66	 * an equivalent random time.
     67	 * Let the port scan random delay elapse first. If recovery finishes
     68	 * up to that point in time, that would be perfect for both recovery
     69	 * and port scan. If not, i.e. recovery takes ages, there was no
     70	 * point in waiting a random delay on top of the time consumed by
     71	 * 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 driver
     91 * @cdev: pointer to belonging ccw device
     92 *
     93 * This function gets called by the common i/o layer for each FCP
     94 * device found on the current system. This is only a stub to make cio
     95 * 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 driver
    105 * @cdev: pointer to belonging ccw device
    106 *
    107 * This function gets called by the common i/o layer and removes an adapter
    108 * from the system. Task of this function is to get rid of all units and
    109 * ports that belong to this adapter. And in addition all resources of this
    110 * 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 driver
    147 * @cdev: pointer to belonging ccw device
    148 *
    149 * This function gets called by the common i/o layer and sets an
    150 * adapter into state online.  The first call will allocate all
    151 * adapter resources that will be retained until the device is removed
    152 * via zfcp_ccw_remove.
    153 *
    154 * Setting an fcp device online means that it will be registered with
    155 * the SCSI stack, that the QDIO queues will be set up and that the
    156 * 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 and
    182	 * without rate limit - basically what zfcp_ccw_activate() has
    183	 * achieved for us. Not quite! That port scan depended on
    184	 * !no_auto_port_rescan. So let's cover the no_auto_port_rescan
    185	 * 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 the
    188	 * 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 driver
    198 * @cdev: pointer to belonging ccw device
    199 *
    200 * This function gets called by the common i/o layer and sets an adapter
    201 * 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 function
    220 * @cdev: pointer to belonging ccw device
    221 * @event: indicates if adapter was detached or attached
    222 *
    223 * This function gets called by the common i/o layer if an adapter has gone
    224 * 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 cio
    263 * @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};