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