Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] zfcp: Move code for managing zfcp_unit devices to new file

Move the code for managing zfcp_unit devices to the new file
zfcp_unit.c. This is in preparation for the change that zfcp_unit will
only track the LUNs configured via unit_add, other data will be moved
from zfcp_unit to the new struct zfcp_scsi_dev.

Reviewed-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>

authored by

Christof Schmitt and committed by
James Bottomley
1daa4eb5 57c23773

+279 -213
+3 -2
drivers/s390/scsi/Makefile
··· 2 2 # Makefile for the S/390 specific device drivers 3 3 # 4 4 5 - zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \ 6 - zfcp_fsf.o zfcp_dbf.o zfcp_sysfs.o zfcp_fc.o zfcp_cfdc.o 5 + zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_cfdc.o zfcp_dbf.o zfcp_erp.o \ 6 + zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \ 7 + zfcp_unit.o 7 8 8 9 obj-$(CONFIG_ZFCP) += zfcp.o
+2 -120
drivers/s390/scsi/zfcp_aux.c
··· 56 56 struct ccw_device *cdev; 57 57 struct zfcp_adapter *adapter; 58 58 struct zfcp_port *port; 59 - struct zfcp_unit *unit; 60 59 61 60 cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); 62 61 if (!cdev) ··· 71 72 port = zfcp_get_port_by_wwpn(adapter, wwpn); 72 73 if (!port) 73 74 goto out_port; 74 - 75 75 flush_work(&port->rport_work); 76 - unit = zfcp_unit_enqueue(port, lun); 77 - if (IS_ERR(unit)) 78 - goto out_unit; 79 76 80 - zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL); 81 - zfcp_erp_wait(adapter); 82 - zfcp_scsi_scan(unit); 83 - 84 - out_unit: 77 + zfcp_unit_add(port, lun); 85 78 put_device(&port->dev); 79 + 86 80 out_port: 87 81 zfcp_ccw_adapter_put(adapter); 88 82 out_ccw_device: ··· 207 215 module_exit(zfcp_module_exit); 208 216 209 217 /** 210 - * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN 211 - * @port: pointer to port to search for unit 212 - * @fcp_lun: FCP LUN to search for 213 - * 214 - * Returns: pointer to zfcp_unit or NULL 215 - */ 216 - struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) 217 - { 218 - unsigned long flags; 219 - struct zfcp_unit *unit; 220 - 221 - read_lock_irqsave(&port->unit_list_lock, flags); 222 - list_for_each_entry(unit, &port->unit_list, list) 223 - if (unit->fcp_lun == fcp_lun) { 224 - if (!get_device(&unit->dev)) 225 - unit = NULL; 226 - read_unlock_irqrestore(&port->unit_list_lock, flags); 227 - return unit; 228 - } 229 - read_unlock_irqrestore(&port->unit_list_lock, flags); 230 - return NULL; 231 - } 232 - 233 - /** 234 218 * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn 235 219 * @adapter: pointer to adapter to search for port 236 220 * @wwpn: wwpn to search for ··· 229 261 } 230 262 read_unlock_irqrestore(&adapter->port_list_lock, flags); 231 263 return NULL; 232 - } 233 - 234 - /** 235 - * zfcp_unit_release - dequeue unit 236 - * @dev: pointer to device 237 - * 238 - * waits until all work is done on unit and removes it then from the unit->list 239 - * of the associated port. 240 - */ 241 - static void zfcp_unit_release(struct device *dev) 242 - { 243 - struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); 244 - 245 - put_device(&unit->port->dev); 246 - kfree(unit); 247 - } 248 - 249 - /** 250 - * zfcp_unit_enqueue - enqueue unit to unit list of a port. 251 - * @port: pointer to port where unit is added 252 - * @fcp_lun: FCP LUN of unit to be enqueued 253 - * Returns: pointer to enqueued unit on success, ERR_PTR on error 254 - * 255 - * Sets up some unit internal structures and creates sysfs entry. 256 - */ 257 - struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) 258 - { 259 - struct zfcp_unit *unit; 260 - int retval = -ENOMEM; 261 - 262 - get_device(&port->dev); 263 - 264 - unit = zfcp_get_unit_by_lun(port, fcp_lun); 265 - if (unit) { 266 - put_device(&unit->dev); 267 - retval = -EEXIST; 268 - goto err_out; 269 - } 270 - 271 - unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); 272 - if (!unit) 273 - goto err_out; 274 - 275 - unit->port = port; 276 - unit->fcp_lun = fcp_lun; 277 - unit->dev.parent = &port->dev; 278 - unit->dev.release = zfcp_unit_release; 279 - 280 - if (dev_set_name(&unit->dev, "0x%016llx", 281 - (unsigned long long) fcp_lun)) { 282 - kfree(unit); 283 - goto err_out; 284 - } 285 - retval = -EINVAL; 286 - 287 - INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work); 288 - 289 - spin_lock_init(&unit->latencies.lock); 290 - unit->latencies.write.channel.min = 0xFFFFFFFF; 291 - unit->latencies.write.fabric.min = 0xFFFFFFFF; 292 - unit->latencies.read.channel.min = 0xFFFFFFFF; 293 - unit->latencies.read.fabric.min = 0xFFFFFFFF; 294 - unit->latencies.cmd.channel.min = 0xFFFFFFFF; 295 - unit->latencies.cmd.fabric.min = 0xFFFFFFFF; 296 - 297 - if (device_register(&unit->dev)) { 298 - put_device(&unit->dev); 299 - goto err_out; 300 - } 301 - 302 - if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) 303 - goto err_out_put; 304 - 305 - write_lock_irq(&port->unit_list_lock); 306 - list_add_tail(&unit->list, &port->unit_list); 307 - write_unlock_irq(&port->unit_list_lock); 308 - 309 - atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); 310 - 311 - return unit; 312 - 313 - err_out_put: 314 - device_unregister(&unit->dev); 315 - err_out: 316 - put_device(&port->dev); 317 - return ERR_PTR(retval); 318 264 } 319 265 320 266 static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
+9 -4
drivers/s390/scsi/zfcp_ext.h
··· 15 15 #include "zfcp_fc.h" 16 16 17 17 /* zfcp_aux.c */ 18 - extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); 19 18 extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); 20 19 extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); 21 20 extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, 22 21 u32); 23 - extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); 24 22 extern void zfcp_sg_free_table(struct scatterlist *, int); 25 23 extern int zfcp_sg_setup_table(struct scatterlist *, int); 26 24 extern void zfcp_device_unregister(struct device *, ··· 161 163 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); 162 164 extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); 163 165 extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); 164 - extern void zfcp_scsi_scan(struct zfcp_unit *); 165 - extern void zfcp_scsi_scan_work(struct work_struct *); 166 166 extern void zfcp_scsi_set_prot(struct zfcp_adapter *); 167 167 extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int); 168 168 ··· 170 174 extern struct attribute_group zfcp_sysfs_port_attrs; 171 175 extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; 172 176 extern struct device_attribute *zfcp_sysfs_shost_attrs[]; 177 + 178 + /* zfcp_unit.c */ 179 + extern int zfcp_unit_add(struct zfcp_port *, u64); 180 + extern int zfcp_unit_remove(struct zfcp_port *, u64); 181 + extern struct zfcp_unit *zfcp_unit_find(struct zfcp_port *, u64); 182 + extern struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit); 183 + extern void zfcp_unit_scsi_scan(struct zfcp_unit *); 184 + extern void zfcp_unit_queue_scsi_scan(struct zfcp_port *); 185 + extern unsigned int zfcp_unit_sdev_status(struct zfcp_unit *); 173 186 174 187 #endif /* ZFCP_EXT_H */
+2 -39
drivers/s390/scsi/zfcp_scsi.c
··· 144 144 list_for_each_entry(port, &adapter->port_list, list) { 145 145 if (!port->rport || (id != port->rport->scsi_target_id)) 146 146 continue; 147 - unit = zfcp_get_unit_by_lun(port, lun); 147 + unit = zfcp_unit_find(port, lun); 148 148 if (unit) 149 149 break; 150 150 } ··· 534 534 } 535 535 } 536 536 537 - static void zfcp_scsi_queue_unit_register(struct zfcp_port *port) 538 - { 539 - struct zfcp_unit *unit; 540 - 541 - read_lock_irq(&port->unit_list_lock); 542 - list_for_each_entry(unit, &port->unit_list, list) { 543 - get_device(&unit->dev); 544 - if (scsi_queue_work(port->adapter->scsi_host, 545 - &unit->scsi_work) <= 0) 546 - put_device(&unit->dev); 547 - } 548 - read_unlock_irq(&port->unit_list_lock); 549 - } 550 - 551 537 static void zfcp_scsi_rport_register(struct zfcp_port *port) 552 538 { 553 539 struct fc_rport_identifiers ids; ··· 560 574 port->rport = rport; 561 575 port->starget_id = rport->scsi_target_id; 562 576 563 - zfcp_scsi_queue_unit_register(port); 577 + zfcp_unit_queue_scsi_scan(port); 564 578 } 565 579 566 580 static void zfcp_scsi_rport_block(struct zfcp_port *port) ··· 621 635 } 622 636 623 637 put_device(&port->dev); 624 - } 625 - 626 - /** 627 - * zfcp_scsi_scan - Register LUN with SCSI midlayer 628 - * @unit: The LUN/unit to register 629 - */ 630 - void zfcp_scsi_scan(struct zfcp_unit *unit) 631 - { 632 - struct fc_rport *rport = unit->port->rport; 633 - 634 - if (rport && rport->port_state == FC_PORTSTATE_ONLINE) 635 - scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, 636 - scsilun_to_int((struct scsi_lun *) 637 - &unit->fcp_lun), 0); 638 - } 639 - 640 - void zfcp_scsi_scan_work(struct work_struct *work) 641 - { 642 - struct zfcp_unit *unit = container_of(work, struct zfcp_unit, 643 - scsi_work); 644 - 645 - zfcp_scsi_scan(unit); 646 - put_device(&unit->dev); 647 638 } 648 639 649 640 /**
+8 -48
drivers/s390/scsi/zfcp_sysfs.c
··· 257 257 const char *buf, size_t count) 258 258 { 259 259 struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); 260 - struct zfcp_unit *unit; 261 260 u64 fcp_lun; 262 - int retval = -EINVAL; 263 - 264 - if (!(port && get_device(&port->dev))) 265 - return -EBUSY; 266 261 267 262 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) 268 - goto out; 263 + return -EINVAL; 269 264 270 - unit = zfcp_unit_enqueue(port, fcp_lun); 271 - if (IS_ERR(unit)) 272 - goto out; 273 - else 274 - retval = 0; 265 + if (zfcp_unit_add(port, fcp_lun)) 266 + return -EINVAL; 275 267 276 - zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); 277 - zfcp_erp_wait(unit->port->adapter); 278 - zfcp_scsi_scan(unit); 279 - out: 280 - put_device(&port->dev); 281 - return retval ? retval : (ssize_t) count; 268 + return count; 282 269 } 283 270 static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); 284 271 ··· 274 287 const char *buf, size_t count) 275 288 { 276 289 struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); 277 - struct zfcp_unit *unit; 278 290 u64 fcp_lun; 279 - int retval = -EINVAL; 280 - struct scsi_device *sdev; 281 - 282 - if (!(port && get_device(&port->dev))) 283 - return -EBUSY; 284 291 285 292 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) 286 - goto out; 293 + return -EINVAL; 287 294 288 - unit = zfcp_get_unit_by_lun(port, fcp_lun); 289 - if (!unit) 290 - goto out; 291 - else 292 - retval = 0; 295 + if (zfcp_unit_remove(port, fcp_lun)) 296 + return -EINVAL; 293 297 294 - sdev = scsi_device_lookup(port->adapter->scsi_host, 0, 295 - port->starget_id, 296 - scsilun_to_int((struct scsi_lun *)&fcp_lun)); 297 - if (sdev) { 298 - scsi_remove_device(sdev); 299 - scsi_device_put(sdev); 300 - } 301 - 302 - write_lock_irq(&port->unit_list_lock); 303 - list_del(&unit->list); 304 - write_unlock_irq(&port->unit_list_lock); 305 - 306 - put_device(&unit->dev); 307 - 308 - zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); 309 - zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); 310 - out: 311 - put_device(&port->dev); 312 - return retval ? retval : (ssize_t) count; 298 + return count; 313 299 } 314 300 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); 315 301
+255
drivers/s390/scsi/zfcp_unit.c
··· 1 + /* 2 + * zfcp device driver 3 + * 4 + * Tracking of manually configured LUNs and helper functions to 5 + * register the LUNs with the SCSI midlayer. 6 + * 7 + * Copyright IBM Corporation 2010 8 + */ 9 + 10 + #include "zfcp_def.h" 11 + #include "zfcp_ext.h" 12 + 13 + /** 14 + * zfcp_unit_scsi_scan - Register LUN with SCSI midlayer 15 + * @unit: The zfcp LUN/unit to register 16 + * 17 + * When the SCSI midlayer is not allowed to automatically scan and 18 + * attach SCSI devices, zfcp has to register the single devices with 19 + * the SCSI midlayer. 20 + */ 21 + void zfcp_unit_scsi_scan(struct zfcp_unit *unit) 22 + { 23 + struct fc_rport *rport = unit->port->rport; 24 + unsigned int lun; 25 + 26 + lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); 27 + 28 + if (rport && rport->port_state == FC_PORTSTATE_ONLINE) 29 + scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1); 30 + } 31 + 32 + static void zfcp_unit_scsi_scan_work(struct work_struct *work) 33 + { 34 + struct zfcp_unit *unit = container_of(work, struct zfcp_unit, 35 + scsi_work); 36 + 37 + zfcp_unit_scsi_scan(unit); 38 + put_device(&unit->dev); 39 + } 40 + 41 + /** 42 + * zfcp_unit_queue_scsi_scan - Register configured units on port 43 + * @port: The zfcp_port where to register units 44 + * 45 + * After opening a port, all units configured on this port have to be 46 + * registered with the SCSI midlayer. This function should be called 47 + * after calling fc_remote_port_add, so that the fc_rport is already 48 + * ONLINE and the call to scsi_scan_target runs the same way as the 49 + * call in the FC transport class. 50 + */ 51 + void zfcp_unit_queue_scsi_scan(struct zfcp_port *port) 52 + { 53 + struct zfcp_unit *unit; 54 + 55 + read_lock_irq(&port->unit_list_lock); 56 + list_for_each_entry(unit, &port->unit_list, list) { 57 + get_device(&unit->dev); 58 + if (scsi_queue_work(port->adapter->scsi_host, 59 + &unit->scsi_work) <= 0) 60 + put_device(&unit->dev); 61 + } 62 + read_unlock_irq(&port->unit_list_lock); 63 + } 64 + 65 + static struct zfcp_unit *_zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun) 66 + { 67 + struct zfcp_unit *unit; 68 + 69 + list_for_each_entry(unit, &port->unit_list, list) 70 + if (unit->fcp_lun == fcp_lun) { 71 + get_device(&unit->dev); 72 + return unit; 73 + } 74 + 75 + return NULL; 76 + } 77 + 78 + /** 79 + * zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN 80 + * @port: zfcp_port where to look for the unit 81 + * @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit 82 + * 83 + * If zfcp_unit is found, a reference is acquired that has to be 84 + * released later. 85 + * 86 + * Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit 87 + * with the specified FCP LUN. 88 + */ 89 + struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun) 90 + { 91 + struct zfcp_unit *unit; 92 + 93 + read_lock_irq(&port->unit_list_lock); 94 + unit = _zfcp_unit_find(port, fcp_lun); 95 + read_unlock_irq(&port->unit_list_lock); 96 + return unit; 97 + } 98 + 99 + /** 100 + * zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit. 101 + * @dev: pointer to device in zfcp_unit 102 + */ 103 + static void zfcp_unit_release(struct device *dev) 104 + { 105 + struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); 106 + 107 + put_device(&unit->port->dev); 108 + kfree(unit); 109 + } 110 + 111 + /** 112 + * zfcp_unit_enqueue - enqueue unit to unit list of a port. 113 + * @port: pointer to port where unit is added 114 + * @fcp_lun: FCP LUN of unit to be enqueued 115 + * Returns: 0 success 116 + * 117 + * Sets up some unit internal structures and creates sysfs entry. 118 + */ 119 + int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) 120 + { 121 + struct zfcp_unit *unit; 122 + 123 + unit = zfcp_unit_find(port, fcp_lun); 124 + if (unit) { 125 + put_device(&unit->dev); 126 + return -EEXIST; 127 + } 128 + 129 + unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); 130 + if (!unit) 131 + return -ENOMEM; 132 + 133 + unit->port = port; 134 + unit->fcp_lun = fcp_lun; 135 + unit->dev.parent = &port->dev; 136 + unit->dev.release = zfcp_unit_release; 137 + unit->latencies.write.channel.min = 0xFFFFFFFF; 138 + unit->latencies.write.fabric.min = 0xFFFFFFFF; 139 + unit->latencies.read.channel.min = 0xFFFFFFFF; 140 + unit->latencies.read.fabric.min = 0xFFFFFFFF; 141 + unit->latencies.cmd.channel.min = 0xFFFFFFFF; 142 + unit->latencies.cmd.fabric.min = 0xFFFFFFFF; 143 + INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work); 144 + spin_lock_init(&unit->latencies.lock); 145 + 146 + if (dev_set_name(&unit->dev, "0x%016llx", 147 + (unsigned long long) fcp_lun)) { 148 + kfree(unit); 149 + return -ENOMEM; 150 + } 151 + 152 + if (device_register(&unit->dev)) { 153 + put_device(&unit->dev); 154 + return -ENOMEM; 155 + } 156 + 157 + if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { 158 + device_unregister(&unit->dev); 159 + return -EINVAL; 160 + } 161 + 162 + get_device(&port->dev); 163 + 164 + write_lock_irq(&port->unit_list_lock); 165 + list_add_tail(&unit->list, &port->unit_list); 166 + write_unlock_irq(&port->unit_list_lock); 167 + 168 + atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); 169 + zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); 170 + zfcp_erp_wait(unit->port->adapter); 171 + zfcp_unit_scsi_scan(unit); 172 + 173 + return 0; 174 + } 175 + 176 + /** 177 + * zfcp_unit_sdev - Return SCSI device for zfcp_unit 178 + * @unit: The zfcp_unit where to get the SCSI device for 179 + * 180 + * Returns: scsi_device pointer on success, NULL if there is no SCSI 181 + * device for this zfcp_unit 182 + * 183 + * On success, the caller also holds a reference to the SCSI device 184 + * that must be released with scsi_device_put. 185 + */ 186 + struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit) 187 + { 188 + struct Scsi_Host *shost; 189 + struct zfcp_port *port; 190 + unsigned int lun; 191 + 192 + lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); 193 + port = unit->port; 194 + shost = port->adapter->scsi_host; 195 + return scsi_device_lookup(shost, 0, port->starget_id, lun); 196 + } 197 + 198 + /** 199 + * zfcp_unit_sdev_status - Return zfcp LUN status for SCSI device 200 + * @unit: The unit to lookup the SCSI device for 201 + * 202 + * Returns the zfcp LUN status field of the SCSI device if the SCSI device 203 + * for the zfcp_unit exists, 0 otherwise. 204 + */ 205 + unsigned int zfcp_unit_sdev_status(struct zfcp_unit *unit) 206 + { 207 + unsigned int status = 0; 208 + struct scsi_device *sdev; 209 + struct zfcp_scsi_dev *zfcp_sdev; 210 + 211 + sdev = zfcp_unit_sdev(unit); 212 + if (sdev) { 213 + zfcp_sdev = sdev_to_zfcp(sdev); 214 + status = atomic_read(&zfcp_sdev->status); 215 + scsi_device_put(sdev); 216 + } 217 + 218 + return status; 219 + } 220 + 221 + /** 222 + * zfcp_unit_remove - Remove entry from list of configured units 223 + * @port: The port where to remove the unit from the configuration 224 + * @fcp_lun: The 64 bit LUN of the unit to remove 225 + * 226 + * Returns: -EINVAL if a unit with the specified LUN does not exist, 227 + * 0 on success. 228 + */ 229 + int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun) 230 + { 231 + struct zfcp_unit *unit; 232 + struct scsi_device *sdev; 233 + 234 + write_lock_irq(&port->unit_list_lock); 235 + unit = _zfcp_unit_find(port, fcp_lun); 236 + if (unit) 237 + list_del(&unit->list); 238 + write_unlock_irq(&port->unit_list_lock); 239 + 240 + if (!unit) 241 + return -EINVAL; 242 + 243 + sdev = zfcp_unit_sdev(unit); 244 + if (sdev) { 245 + scsi_remove_device(sdev); 246 + scsi_device_put(sdev); 247 + } 248 + 249 + put_device(&unit->dev); 250 + 251 + zfcp_erp_unit_shutdown(unit, 0, "unrem_1", NULL); 252 + zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); 253 + 254 + return 0; 255 + }