0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define KMSG_COMPONENT "zfcp"
0011 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0012
0013 #include <linux/module.h>
0014 #include "zfcp_ext.h"
0015 #include "zfcp_reqlist.h"
0016
0017 #define ZFCP_MODEL_PRIV 0x4
0018
0019 static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);
0020
0021 struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev)
0022 {
0023 struct zfcp_adapter *adapter;
0024 unsigned long flags;
0025
0026 spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);
0027 adapter = dev_get_drvdata(&cdev->dev);
0028 if (adapter)
0029 kref_get(&adapter->ref);
0030 spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
0031 return adapter;
0032 }
0033
0034 void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
0035 {
0036 unsigned long flags;
0037
0038 spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);
0039 kref_put(&adapter->ref, zfcp_adapter_release);
0040 spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
0041 }
0042
0043
0044
0045
0046
0047
0048
0049 static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
0050 {
0051 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
0052
0053 if (!adapter)
0054 return 0;
0055
0056 zfcp_erp_clear_adapter_status(adapter, clear);
0057 zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
0058 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
0059 tag);
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 msleep(zfcp_fc_port_scan_backoff());
0074 zfcp_erp_wait(adapter);
0075 flush_delayed_work(&adapter->scan_work);
0076
0077 zfcp_ccw_adapter_put(adapter);
0078
0079 return 0;
0080 }
0081
0082 static struct ccw_device_id zfcp_ccw_device_id[] = {
0083 { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x3) },
0084 { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, ZFCP_MODEL_PRIV) },
0085 {},
0086 };
0087 MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 static int zfcp_ccw_probe(struct ccw_device *cdev)
0099 {
0100 return 0;
0101 }
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 static void zfcp_ccw_remove(struct ccw_device *cdev)
0113 {
0114 struct zfcp_adapter *adapter;
0115 struct zfcp_port *port, *p;
0116 struct zfcp_unit *unit, *u;
0117 LIST_HEAD(unit_remove_lh);
0118 LIST_HEAD(port_remove_lh);
0119
0120 ccw_device_set_offline(cdev);
0121
0122 adapter = zfcp_ccw_adapter_by_cdev(cdev);
0123 if (!adapter)
0124 return;
0125
0126 write_lock_irq(&adapter->port_list_lock);
0127 list_for_each_entry(port, &adapter->port_list, list) {
0128 write_lock(&port->unit_list_lock);
0129 list_splice_init(&port->unit_list, &unit_remove_lh);
0130 write_unlock(&port->unit_list_lock);
0131 }
0132 list_splice_init(&adapter->port_list, &port_remove_lh);
0133 write_unlock_irq(&adapter->port_list_lock);
0134 zfcp_ccw_adapter_put(adapter);
0135
0136 list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
0137 device_unregister(&unit->dev);
0138
0139 list_for_each_entry_safe(port, p, &port_remove_lh, list)
0140 device_unregister(&port->dev);
0141
0142 zfcp_adapter_unregister(adapter);
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 static int zfcp_ccw_set_online(struct ccw_device *cdev)
0159 {
0160 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
0161
0162 if (!adapter) {
0163 adapter = zfcp_adapter_enqueue(cdev);
0164
0165 if (IS_ERR(adapter)) {
0166 dev_err(&cdev->dev,
0167 "Setting up data structures for the "
0168 "FCP adapter failed\n");
0169 return PTR_ERR(adapter);
0170 }
0171 kref_get(&adapter->ref);
0172 }
0173
0174
0175 BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
0176 adapter->req_no = 0;
0177
0178 zfcp_ccw_activate(cdev, 0, "ccsonl1");
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 zfcp_fc_inverse_conditional_port_scan(adapter);
0191 flush_delayed_work(&adapter->scan_work);
0192 zfcp_ccw_adapter_put(adapter);
0193 return 0;
0194 }
0195
0196
0197
0198
0199
0200
0201
0202
0203 static int zfcp_ccw_set_offline(struct ccw_device *cdev)
0204 {
0205 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
0206
0207 if (!adapter)
0208 return 0;
0209
0210 zfcp_erp_set_adapter_status(adapter, 0);
0211 zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1");
0212 zfcp_erp_wait(adapter);
0213
0214 zfcp_ccw_adapter_put(adapter);
0215 return 0;
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
0227 {
0228 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
0229
0230 if (!adapter)
0231 return 1;
0232
0233 switch (event) {
0234 case CIO_GONE:
0235 dev_warn(&cdev->dev, "The FCP device has been detached\n");
0236 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
0237 break;
0238 case CIO_NO_PATH:
0239 dev_warn(&cdev->dev,
0240 "The CHPID for the FCP device is offline\n");
0241 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
0242 break;
0243 case CIO_OPER:
0244 dev_info(&cdev->dev, "The FCP device is operational again\n");
0245 zfcp_erp_set_adapter_status(adapter,
0246 ZFCP_STATUS_COMMON_RUNNING);
0247 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
0248 "ccnoti4");
0249 break;
0250 case CIO_BOXED:
0251 dev_warn(&cdev->dev, "The FCP device did not respond within "
0252 "the specified time\n");
0253 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5");
0254 break;
0255 }
0256
0257 zfcp_ccw_adapter_put(adapter);
0258 return 1;
0259 }
0260
0261
0262
0263
0264
0265 static void zfcp_ccw_shutdown(struct ccw_device *cdev)
0266 {
0267 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
0268
0269 if (!adapter)
0270 return;
0271
0272 zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1");
0273 zfcp_erp_wait(adapter);
0274 zfcp_erp_thread_kill(adapter);
0275
0276 zfcp_ccw_adapter_put(adapter);
0277 }
0278
0279 struct ccw_driver zfcp_ccw_driver = {
0280 .driver = {
0281 .owner = THIS_MODULE,
0282 .name = "zfcp",
0283 },
0284 .ids = zfcp_ccw_device_id,
0285 .probe = zfcp_ccw_probe,
0286 .remove = zfcp_ccw_remove,
0287 .set_online = zfcp_ccw_set_online,
0288 .set_offline = zfcp_ccw_set_offline,
0289 .notify = zfcp_ccw_notify,
0290 .shutdown = zfcp_ccw_shutdown,
0291 };