1 /* 2 * linux/drivers/s390/scsi/zfcp_ccw.c 3 * 4 * FCP adapter driver for IBM eServer zSeries 5 * 6 * CCW driver related routines 7 * 8 * (C) Copyright IBM Corp. 2003, 2004 9 * 10 * Authors: 11 * Martin Peschke <mpeschke@de.ibm.com> 12 * Heiko Carstens <heiko.carstens@de.ibm.com> 13 * Andreas Herrmann <aherrman@de.ibm.com> 14 * 15 * This program is free software; you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License as published by 17 * the Free Software Foundation; either version 2, or (at your option) 18 * any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with this program; if not, write to the Free Software 27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 28 */ 29 30 #include "zfcp_ext.h" 31 32 #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG 33 34 static int zfcp_ccw_probe(struct ccw_device *); 35 static void zfcp_ccw_remove(struct ccw_device *); 36 static int zfcp_ccw_set_online(struct ccw_device *); 37 static int zfcp_ccw_set_offline(struct ccw_device *); 38 static int zfcp_ccw_notify(struct ccw_device *, int); 39 static void zfcp_ccw_shutdown(struct device *); 40 41 static struct ccw_device_id zfcp_ccw_device_id[] = { 42 {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, 43 ZFCP_CONTROL_UNIT_MODEL, 44 ZFCP_DEVICE_TYPE, 45 ZFCP_DEVICE_MODEL)}, 46 {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, 47 ZFCP_CONTROL_UNIT_MODEL, 48 ZFCP_DEVICE_TYPE, 49 ZFCP_DEVICE_MODEL_PRIV)}, 50 {}, 51 }; 52 53 static struct ccw_driver zfcp_ccw_driver = { 54 .owner = THIS_MODULE, 55 .name = ZFCP_NAME, 56 .ids = zfcp_ccw_device_id, 57 .probe = zfcp_ccw_probe, 58 .remove = zfcp_ccw_remove, 59 .set_online = zfcp_ccw_set_online, 60 .set_offline = zfcp_ccw_set_offline, 61 .notify = zfcp_ccw_notify, 62 .driver = { 63 .shutdown = zfcp_ccw_shutdown, 64 }, 65 }; 66 67 MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id); 68 69 /** 70 * zfcp_ccw_probe - probe function of zfcp driver 71 * @ccw_device: pointer to belonging ccw device 72 * 73 * This function gets called by the common i/o layer and sets up the initial 74 * data structures for each fcp adapter, which was detected by the system. 75 * Also the sysfs files for this adapter will be created by this function. 76 * In addition the nameserver port will be added to the ports of the adapter 77 * and its sysfs representation will be created too. 78 */ 79 static int 80 zfcp_ccw_probe(struct ccw_device *ccw_device) 81 { 82 struct zfcp_adapter *adapter; 83 int retval = 0; 84 85 down(&zfcp_data.config_sema); 86 adapter = zfcp_adapter_enqueue(ccw_device); 87 if (!adapter) 88 retval = -EINVAL; 89 else 90 ZFCP_LOG_DEBUG("Probed adapter %s\n", 91 zfcp_get_busid_by_adapter(adapter)); 92 up(&zfcp_data.config_sema); 93 return retval; 94 } 95 96 /** 97 * zfcp_ccw_remove - remove function of zfcp driver 98 * @ccw_device: pointer to belonging ccw device 99 * 100 * This function gets called by the common i/o layer and removes an adapter 101 * from the system. Task of this function is to get rid of all units and 102 * ports that belong to this adapter. And in addition all resources of this 103 * adapter will be freed too. 104 */ 105 static void 106 zfcp_ccw_remove(struct ccw_device *ccw_device) 107 { 108 struct zfcp_adapter *adapter; 109 struct zfcp_port *port, *p; 110 struct zfcp_unit *unit, *u; 111 112 ccw_device_set_offline(ccw_device); 113 down(&zfcp_data.config_sema); 114 adapter = dev_get_drvdata(&ccw_device->dev); 115 116 ZFCP_LOG_DEBUG("Removing adapter %s\n", 117 zfcp_get_busid_by_adapter(adapter)); 118 write_lock_irq(&zfcp_data.config_lock); 119 list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { 120 list_for_each_entry_safe(unit, u, &port->unit_list_head, list) { 121 list_move(&unit->list, &port->unit_remove_lh); 122 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, 123 &unit->status); 124 } 125 list_move(&port->list, &adapter->port_remove_lh); 126 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); 127 } 128 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); 129 write_unlock_irq(&zfcp_data.config_lock); 130 131 list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) { 132 list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) { 133 zfcp_unit_dequeue(unit); 134 } 135 zfcp_port_dequeue(port); 136 } 137 zfcp_adapter_wait(adapter); 138 zfcp_adapter_dequeue(adapter); 139 140 up(&zfcp_data.config_sema); 141 } 142 143 /** 144 * zfcp_ccw_set_online - set_online function of zfcp driver 145 * @ccw_device: pointer to belonging ccw device 146 * 147 * This function gets called by the common i/o layer and sets an adapter 148 * into state online. Setting an fcp device online means that it will be 149 * registered with the SCSI stack, that the QDIO queues will be set up 150 * and that the adapter will be opened (asynchronously). 151 */ 152 static int 153 zfcp_ccw_set_online(struct ccw_device *ccw_device) 154 { 155 struct zfcp_adapter *adapter; 156 int retval; 157 158 down(&zfcp_data.config_sema); 159 adapter = dev_get_drvdata(&ccw_device->dev); 160 161 retval = zfcp_adapter_debug_register(adapter); 162 if (retval) 163 goto out; 164 retval = zfcp_erp_thread_setup(adapter); 165 if (retval) { 166 ZFCP_LOG_INFO("error: start of error recovery thread for " 167 "adapter %s failed\n", 168 zfcp_get_busid_by_adapter(adapter)); 169 goto out_erp_thread; 170 } 171 172 retval = zfcp_adapter_scsi_register(adapter); 173 if (retval) 174 goto out_scsi_register; 175 zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, 176 ZFCP_SET); 177 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); 178 zfcp_erp_wait(adapter); 179 goto out; 180 181 out_scsi_register: 182 zfcp_erp_thread_kill(adapter); 183 out_erp_thread: 184 zfcp_adapter_debug_unregister(adapter); 185 out: 186 up(&zfcp_data.config_sema); 187 return retval; 188 } 189 190 /** 191 * zfcp_ccw_set_offline - set_offline function of zfcp driver 192 * @ccw_device: pointer to belonging ccw device 193 * 194 * This function gets called by the common i/o layer and sets an adapter 195 * into state offline. Setting an fcp device offline means that it will be 196 * unregistered from the SCSI stack and that the adapter will be shut down 197 * asynchronously. 198 */ 199 static int 200 zfcp_ccw_set_offline(struct ccw_device *ccw_device) 201 { 202 struct zfcp_adapter *adapter; 203 204 down(&zfcp_data.config_sema); 205 adapter = dev_get_drvdata(&ccw_device->dev); 206 zfcp_erp_adapter_shutdown(adapter, 0); 207 zfcp_erp_wait(adapter); 208 zfcp_adapter_scsi_unregister(adapter); 209 zfcp_erp_thread_kill(adapter); 210 zfcp_adapter_debug_unregister(adapter); 211 up(&zfcp_data.config_sema); 212 return 0; 213 } 214 215 /** 216 * zfcp_ccw_notify 217 * @ccw_device: pointer to belonging ccw device 218 * @event: indicates if adapter was detached or attached 219 * 220 * This function gets called by the common i/o layer if an adapter has gone 221 * or reappeared. 222 */ 223 static int 224 zfcp_ccw_notify(struct ccw_device *ccw_device, int event) 225 { 226 struct zfcp_adapter *adapter; 227 228 down(&zfcp_data.config_sema); 229 adapter = dev_get_drvdata(&ccw_device->dev); 230 switch (event) { 231 case CIO_GONE: 232 ZFCP_LOG_NORMAL("adapter %s: device gone\n", 233 zfcp_get_busid_by_adapter(adapter)); 234 debug_text_event(adapter->erp_dbf,1,"dev_gone"); 235 zfcp_erp_adapter_shutdown(adapter, 0); 236 break; 237 case CIO_NO_PATH: 238 ZFCP_LOG_NORMAL("adapter %s: no path\n", 239 zfcp_get_busid_by_adapter(adapter)); 240 debug_text_event(adapter->erp_dbf,1,"no_path"); 241 zfcp_erp_adapter_shutdown(adapter, 0); 242 break; 243 case CIO_OPER: 244 ZFCP_LOG_NORMAL("adapter %s: operational again\n", 245 zfcp_get_busid_by_adapter(adapter)); 246 debug_text_event(adapter->erp_dbf,1,"dev_oper"); 247 zfcp_erp_modify_adapter_status(adapter, 248 ZFCP_STATUS_COMMON_RUNNING, 249 ZFCP_SET); 250 zfcp_erp_adapter_reopen(adapter, 251 ZFCP_STATUS_COMMON_ERP_FAILED); 252 break; 253 } 254 zfcp_erp_wait(adapter); 255 up(&zfcp_data.config_sema); 256 return 1; 257 } 258 259 /** 260 * zfcp_ccw_register - ccw register function 261 * 262 * Registers the driver at the common i/o layer. This function will be called 263 * at module load time/system start. 264 */ 265 int __init 266 zfcp_ccw_register(void) 267 { 268 int retval; 269 270 retval = ccw_driver_register(&zfcp_ccw_driver); 271 if (retval) 272 goto out; 273 retval = zfcp_sysfs_driver_create_files(&zfcp_ccw_driver.driver); 274 if (retval) 275 ccw_driver_unregister(&zfcp_ccw_driver); 276 out: 277 return retval; 278 } 279 280 /** 281 * zfcp_ccw_unregister - ccw unregister function 282 * 283 * Unregisters the driver from common i/o layer. Function will be called at 284 * module unload/system shutdown. 285 */ 286 void __exit 287 zfcp_ccw_unregister(void) 288 { 289 zfcp_sysfs_driver_remove_files(&zfcp_ccw_driver.driver); 290 ccw_driver_unregister(&zfcp_ccw_driver); 291 } 292 293 /** 294 * zfcp_ccw_shutdown - gets called on reboot/shutdown 295 * 296 * Makes sure that QDIO queues are down when the system gets stopped. 297 */ 298 static void 299 zfcp_ccw_shutdown(struct device *dev) 300 { 301 struct zfcp_adapter *adapter; 302 303 down(&zfcp_data.config_sema); 304 adapter = dev_get_drvdata(dev); 305 zfcp_erp_adapter_shutdown(adapter, 0); 306 zfcp_erp_wait(adapter); 307 up(&zfcp_data.config_sema); 308 } 309 310 #undef ZFCP_LOG_AREA 311