diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_aux.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 213 |
1 files changed, 38 insertions, 175 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 96fa1f536394..645b0fcbb370 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -45,8 +45,8 @@ static char *init_device; | |||
45 | module_param_named(device, init_device, charp, 0400); | 45 | module_param_named(device, init_device, charp, 0400); |
46 | MODULE_PARM_DESC(device, "specify initial device"); | 46 | MODULE_PARM_DESC(device, "specify initial device"); |
47 | 47 | ||
48 | static struct kmem_cache *zfcp_cache_hw_align(const char *name, | 48 | static struct kmem_cache * __init zfcp_cache_hw_align(const char *name, |
49 | unsigned long size) | 49 | unsigned long size) |
50 | { | 50 | { |
51 | return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); | 51 | return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); |
52 | } | 52 | } |
@@ -56,7 +56,6 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | |||
56 | struct ccw_device *cdev; | 56 | struct ccw_device *cdev; |
57 | struct zfcp_adapter *adapter; | 57 | struct zfcp_adapter *adapter; |
58 | struct zfcp_port *port; | 58 | struct zfcp_port *port; |
59 | struct zfcp_unit *unit; | ||
60 | 59 | ||
61 | cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); | 60 | cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); |
62 | if (!cdev) | 61 | if (!cdev) |
@@ -72,17 +71,11 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | |||
72 | port = zfcp_get_port_by_wwpn(adapter, wwpn); | 71 | port = zfcp_get_port_by_wwpn(adapter, wwpn); |
73 | if (!port) | 72 | if (!port) |
74 | goto out_port; | 73 | goto out_port; |
74 | flush_work(&port->rport_work); | ||
75 | 75 | ||
76 | unit = zfcp_unit_enqueue(port, lun); | 76 | zfcp_unit_add(port, lun); |
77 | if (IS_ERR(unit)) | ||
78 | goto out_unit; | ||
79 | |||
80 | zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL); | ||
81 | zfcp_erp_wait(adapter); | ||
82 | flush_work(&unit->scsi_work); | ||
83 | |||
84 | out_unit: | ||
85 | put_device(&port->dev); | 77 | put_device(&port->dev); |
78 | |||
86 | out_port: | 79 | out_port: |
87 | zfcp_ccw_adapter_put(adapter); | 80 | zfcp_ccw_adapter_put(adapter); |
88 | out_ccw_device: | 81 | out_ccw_device: |
@@ -129,35 +122,23 @@ static int __init zfcp_module_init(void) | |||
129 | { | 122 | { |
130 | int retval = -ENOMEM; | 123 | int retval = -ENOMEM; |
131 | 124 | ||
132 | zfcp_data.gpn_ft_cache = zfcp_cache_hw_align("zfcp_gpn", | 125 | zfcp_fsf_qtcb_cache = zfcp_cache_hw_align("zfcp_fsf_qtcb", |
133 | sizeof(struct zfcp_fc_gpn_ft_req)); | 126 | sizeof(struct fsf_qtcb)); |
134 | if (!zfcp_data.gpn_ft_cache) | 127 | if (!zfcp_fsf_qtcb_cache) |
135 | goto out; | ||
136 | |||
137 | zfcp_data.qtcb_cache = zfcp_cache_hw_align("zfcp_qtcb", | ||
138 | sizeof(struct fsf_qtcb)); | ||
139 | if (!zfcp_data.qtcb_cache) | ||
140 | goto out_qtcb_cache; | 128 | goto out_qtcb_cache; |
141 | 129 | ||
142 | zfcp_data.sr_buffer_cache = zfcp_cache_hw_align("zfcp_sr", | 130 | zfcp_fc_req_cache = zfcp_cache_hw_align("zfcp_fc_req", |
143 | sizeof(struct fsf_status_read_buffer)); | 131 | sizeof(struct zfcp_fc_req)); |
144 | if (!zfcp_data.sr_buffer_cache) | 132 | if (!zfcp_fc_req_cache) |
145 | goto out_sr_cache; | 133 | goto out_fc_cache; |
146 | 134 | ||
147 | zfcp_data.gid_pn_cache = zfcp_cache_hw_align("zfcp_gid", | 135 | zfcp_scsi_transport_template = |
148 | sizeof(struct zfcp_fc_gid_pn)); | ||
149 | if (!zfcp_data.gid_pn_cache) | ||
150 | goto out_gid_cache; | ||
151 | |||
152 | zfcp_data.adisc_cache = zfcp_cache_hw_align("zfcp_adisc", | ||
153 | sizeof(struct zfcp_fc_els_adisc)); | ||
154 | if (!zfcp_data.adisc_cache) | ||
155 | goto out_adisc_cache; | ||
156 | |||
157 | zfcp_data.scsi_transport_template = | ||
158 | fc_attach_transport(&zfcp_transport_functions); | 136 | fc_attach_transport(&zfcp_transport_functions); |
159 | if (!zfcp_data.scsi_transport_template) | 137 | if (!zfcp_scsi_transport_template) |
160 | goto out_transport; | 138 | goto out_transport; |
139 | scsi_transport_reserve_device(zfcp_scsi_transport_template, | ||
140 | sizeof(struct zfcp_scsi_dev)); | ||
141 | |||
161 | 142 | ||
162 | retval = misc_register(&zfcp_cfdc_misc); | 143 | retval = misc_register(&zfcp_cfdc_misc); |
163 | if (retval) { | 144 | if (retval) { |
@@ -179,18 +160,12 @@ static int __init zfcp_module_init(void) | |||
179 | out_ccw_register: | 160 | out_ccw_register: |
180 | misc_deregister(&zfcp_cfdc_misc); | 161 | misc_deregister(&zfcp_cfdc_misc); |
181 | out_misc: | 162 | out_misc: |
182 | fc_release_transport(zfcp_data.scsi_transport_template); | 163 | fc_release_transport(zfcp_scsi_transport_template); |
183 | out_transport: | 164 | out_transport: |
184 | kmem_cache_destroy(zfcp_data.adisc_cache); | 165 | kmem_cache_destroy(zfcp_fc_req_cache); |
185 | out_adisc_cache: | 166 | out_fc_cache: |
186 | kmem_cache_destroy(zfcp_data.gid_pn_cache); | 167 | kmem_cache_destroy(zfcp_fsf_qtcb_cache); |
187 | out_gid_cache: | ||
188 | kmem_cache_destroy(zfcp_data.sr_buffer_cache); | ||
189 | out_sr_cache: | ||
190 | kmem_cache_destroy(zfcp_data.qtcb_cache); | ||
191 | out_qtcb_cache: | 168 | out_qtcb_cache: |
192 | kmem_cache_destroy(zfcp_data.gpn_ft_cache); | ||
193 | out: | ||
194 | return retval; | 169 | return retval; |
195 | } | 170 | } |
196 | 171 | ||
@@ -200,41 +175,14 @@ static void __exit zfcp_module_exit(void) | |||
200 | { | 175 | { |
201 | ccw_driver_unregister(&zfcp_ccw_driver); | 176 | ccw_driver_unregister(&zfcp_ccw_driver); |
202 | misc_deregister(&zfcp_cfdc_misc); | 177 | misc_deregister(&zfcp_cfdc_misc); |
203 | fc_release_transport(zfcp_data.scsi_transport_template); | 178 | fc_release_transport(zfcp_scsi_transport_template); |
204 | kmem_cache_destroy(zfcp_data.adisc_cache); | 179 | kmem_cache_destroy(zfcp_fc_req_cache); |
205 | kmem_cache_destroy(zfcp_data.gid_pn_cache); | 180 | kmem_cache_destroy(zfcp_fsf_qtcb_cache); |
206 | kmem_cache_destroy(zfcp_data.sr_buffer_cache); | ||
207 | kmem_cache_destroy(zfcp_data.qtcb_cache); | ||
208 | kmem_cache_destroy(zfcp_data.gpn_ft_cache); | ||
209 | } | 181 | } |
210 | 182 | ||
211 | module_exit(zfcp_module_exit); | 183 | module_exit(zfcp_module_exit); |
212 | 184 | ||
213 | /** | 185 | /** |
214 | * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN | ||
215 | * @port: pointer to port to search for unit | ||
216 | * @fcp_lun: FCP LUN to search for | ||
217 | * | ||
218 | * Returns: pointer to zfcp_unit or NULL | ||
219 | */ | ||
220 | struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) | ||
221 | { | ||
222 | unsigned long flags; | ||
223 | struct zfcp_unit *unit; | ||
224 | |||
225 | read_lock_irqsave(&port->unit_list_lock, flags); | ||
226 | list_for_each_entry(unit, &port->unit_list, list) | ||
227 | if (unit->fcp_lun == fcp_lun) { | ||
228 | if (!get_device(&unit->dev)) | ||
229 | unit = NULL; | ||
230 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
231 | return unit; | ||
232 | } | ||
233 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | /** | ||
238 | * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn | 186 | * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn |
239 | * @adapter: pointer to adapter to search for port | 187 | * @adapter: pointer to adapter to search for port |
240 | * @wwpn: wwpn to search for | 188 | * @wwpn: wwpn to search for |
@@ -259,92 +207,6 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, | |||
259 | return NULL; | 207 | return NULL; |
260 | } | 208 | } |
261 | 209 | ||
262 | /** | ||
263 | * zfcp_unit_release - dequeue unit | ||
264 | * @dev: pointer to device | ||
265 | * | ||
266 | * waits until all work is done on unit and removes it then from the unit->list | ||
267 | * of the associated port. | ||
268 | */ | ||
269 | static void zfcp_unit_release(struct device *dev) | ||
270 | { | ||
271 | struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); | ||
272 | |||
273 | put_device(&unit->port->dev); | ||
274 | kfree(unit); | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * zfcp_unit_enqueue - enqueue unit to unit list of a port. | ||
279 | * @port: pointer to port where unit is added | ||
280 | * @fcp_lun: FCP LUN of unit to be enqueued | ||
281 | * Returns: pointer to enqueued unit on success, ERR_PTR on error | ||
282 | * | ||
283 | * Sets up some unit internal structures and creates sysfs entry. | ||
284 | */ | ||
285 | struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | ||
286 | { | ||
287 | struct zfcp_unit *unit; | ||
288 | int retval = -ENOMEM; | ||
289 | |||
290 | get_device(&port->dev); | ||
291 | |||
292 | unit = zfcp_get_unit_by_lun(port, fcp_lun); | ||
293 | if (unit) { | ||
294 | put_device(&unit->dev); | ||
295 | retval = -EEXIST; | ||
296 | goto err_out; | ||
297 | } | ||
298 | |||
299 | unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); | ||
300 | if (!unit) | ||
301 | goto err_out; | ||
302 | |||
303 | unit->port = port; | ||
304 | unit->fcp_lun = fcp_lun; | ||
305 | unit->dev.parent = &port->dev; | ||
306 | unit->dev.release = zfcp_unit_release; | ||
307 | |||
308 | if (dev_set_name(&unit->dev, "0x%016llx", | ||
309 | (unsigned long long) fcp_lun)) { | ||
310 | kfree(unit); | ||
311 | goto err_out; | ||
312 | } | ||
313 | retval = -EINVAL; | ||
314 | |||
315 | INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work); | ||
316 | |||
317 | spin_lock_init(&unit->latencies.lock); | ||
318 | unit->latencies.write.channel.min = 0xFFFFFFFF; | ||
319 | unit->latencies.write.fabric.min = 0xFFFFFFFF; | ||
320 | unit->latencies.read.channel.min = 0xFFFFFFFF; | ||
321 | unit->latencies.read.fabric.min = 0xFFFFFFFF; | ||
322 | unit->latencies.cmd.channel.min = 0xFFFFFFFF; | ||
323 | unit->latencies.cmd.fabric.min = 0xFFFFFFFF; | ||
324 | |||
325 | if (device_register(&unit->dev)) { | ||
326 | put_device(&unit->dev); | ||
327 | goto err_out; | ||
328 | } | ||
329 | |||
330 | if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) | ||
331 | goto err_out_put; | ||
332 | |||
333 | write_lock_irq(&port->unit_list_lock); | ||
334 | list_add_tail(&unit->list, &port->unit_list); | ||
335 | write_unlock_irq(&port->unit_list_lock); | ||
336 | |||
337 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); | ||
338 | |||
339 | return unit; | ||
340 | |||
341 | err_out_put: | ||
342 | device_unregister(&unit->dev); | ||
343 | err_out: | ||
344 | put_device(&port->dev); | ||
345 | return ERR_PTR(retval); | ||
346 | } | ||
347 | |||
348 | static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) | 210 | static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) |
349 | { | 211 | { |
350 | adapter->pool.erp_req = | 212 | adapter->pool.erp_req = |
@@ -374,18 +236,18 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) | |||
374 | return -ENOMEM; | 236 | return -ENOMEM; |
375 | 237 | ||
376 | adapter->pool.qtcb_pool = | 238 | adapter->pool.qtcb_pool = |
377 | mempool_create_slab_pool(4, zfcp_data.qtcb_cache); | 239 | mempool_create_slab_pool(4, zfcp_fsf_qtcb_cache); |
378 | if (!adapter->pool.qtcb_pool) | 240 | if (!adapter->pool.qtcb_pool) |
379 | return -ENOMEM; | 241 | return -ENOMEM; |
380 | 242 | ||
381 | adapter->pool.status_read_data = | 243 | BUILD_BUG_ON(sizeof(struct fsf_status_read_buffer) > PAGE_SIZE); |
382 | mempool_create_slab_pool(FSF_STATUS_READS_RECOM, | 244 | adapter->pool.sr_data = |
383 | zfcp_data.sr_buffer_cache); | 245 | mempool_create_page_pool(FSF_STATUS_READS_RECOM, 0); |
384 | if (!adapter->pool.status_read_data) | 246 | if (!adapter->pool.sr_data) |
385 | return -ENOMEM; | 247 | return -ENOMEM; |
386 | 248 | ||
387 | adapter->pool.gid_pn = | 249 | adapter->pool.gid_pn = |
388 | mempool_create_slab_pool(1, zfcp_data.gid_pn_cache); | 250 | mempool_create_slab_pool(1, zfcp_fc_req_cache); |
389 | if (!adapter->pool.gid_pn) | 251 | if (!adapter->pool.gid_pn) |
390 | return -ENOMEM; | 252 | return -ENOMEM; |
391 | 253 | ||
@@ -404,8 +266,8 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) | |||
404 | mempool_destroy(adapter->pool.qtcb_pool); | 266 | mempool_destroy(adapter->pool.qtcb_pool); |
405 | if (adapter->pool.status_read_req) | 267 | if (adapter->pool.status_read_req) |
406 | mempool_destroy(adapter->pool.status_read_req); | 268 | mempool_destroy(adapter->pool.status_read_req); |
407 | if (adapter->pool.status_read_data) | 269 | if (adapter->pool.sr_data) |
408 | mempool_destroy(adapter->pool.status_read_data); | 270 | mempool_destroy(adapter->pool.sr_data); |
409 | if (adapter->pool.gid_pn) | 271 | if (adapter->pool.gid_pn) |
410 | mempool_destroy(adapter->pool.gid_pn); | 272 | mempool_destroy(adapter->pool.gid_pn); |
411 | } | 273 | } |
@@ -425,8 +287,7 @@ int zfcp_status_read_refill(struct zfcp_adapter *adapter) | |||
425 | if (zfcp_fsf_status_read(adapter->qdio)) { | 287 | if (zfcp_fsf_status_read(adapter->qdio)) { |
426 | if (atomic_read(&adapter->stat_miss) >= | 288 | if (atomic_read(&adapter->stat_miss) >= |
427 | adapter->stat_read_buf_num) { | 289 | adapter->stat_read_buf_num) { |
428 | zfcp_erp_adapter_reopen(adapter, 0, "axsref1", | 290 | zfcp_erp_adapter_reopen(adapter, 0, "axsref1"); |
429 | NULL); | ||
430 | return 1; | 291 | return 1; |
431 | } | 292 | } |
432 | break; | 293 | break; |
@@ -501,6 +362,7 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
501 | 362 | ||
502 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); | 363 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); |
503 | INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports); | 364 | INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports); |
365 | INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update); | ||
504 | 366 | ||
505 | if (zfcp_qdio_setup(adapter)) | 367 | if (zfcp_qdio_setup(adapter)) |
506 | goto failed; | 368 | goto failed; |
@@ -552,7 +414,7 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
552 | adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN; | 414 | adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN; |
553 | adapter->ccw_device->dev.dma_parms = &adapter->dma_parms; | 415 | adapter->ccw_device->dev.dma_parms = &adapter->dma_parms; |
554 | 416 | ||
555 | if (!zfcp_adapter_scsi_register(adapter)) | 417 | if (!zfcp_scsi_adapter_register(adapter)) |
556 | return adapter; | 418 | return adapter; |
557 | 419 | ||
558 | failed: | 420 | failed: |
@@ -566,14 +428,15 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter) | |||
566 | 428 | ||
567 | cancel_work_sync(&adapter->scan_work); | 429 | cancel_work_sync(&adapter->scan_work); |
568 | cancel_work_sync(&adapter->stat_work); | 430 | cancel_work_sync(&adapter->stat_work); |
431 | cancel_work_sync(&adapter->ns_up_work); | ||
569 | zfcp_destroy_adapter_work_queue(adapter); | 432 | zfcp_destroy_adapter_work_queue(adapter); |
570 | 433 | ||
571 | zfcp_fc_wka_ports_force_offline(adapter->gs); | 434 | zfcp_fc_wka_ports_force_offline(adapter->gs); |
572 | zfcp_adapter_scsi_unregister(adapter); | 435 | zfcp_scsi_adapter_unregister(adapter); |
573 | sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs); | 436 | sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs); |
574 | 437 | ||
575 | zfcp_erp_thread_kill(adapter); | 438 | zfcp_erp_thread_kill(adapter); |
576 | zfcp_dbf_adapter_unregister(adapter->dbf); | 439 | zfcp_dbf_adapter_unregister(adapter); |
577 | zfcp_qdio_destroy(adapter->qdio); | 440 | zfcp_qdio_destroy(adapter->qdio); |
578 | 441 | ||
579 | zfcp_ccw_adapter_put(adapter); /* final put to release */ | 442 | zfcp_ccw_adapter_put(adapter); /* final put to release */ |