zfcp_aux.c 20.5 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
C
Christof Schmitt 已提交
2
 * zfcp device driver
L
Linus Torvalds 已提交
3
 *
C
Christof Schmitt 已提交
4
 * Module interface and handling of zfcp data structures.
L
Linus Torvalds 已提交
5
 *
6
 * Copyright IBM Corporation 2002, 2009
L
Linus Torvalds 已提交
7 8
 */

9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Driver authors:
 *            Martin Peschke (originator of the driver)
 *            Raimund Schroeder
 *            Aron Zeh
 *            Wolfgang Taphorn
 *            Stefan Bader
 *            Heiko Carstens (kernel 2.6 port of the driver)
 *            Andreas Herrmann
 *            Maxim Shchetynin
 *            Volker Sameske
 *            Ralph Wuerthner
C
Christof Schmitt 已提交
21 22 23 24 25
 *            Michael Loehr
 *            Swen Schillig
 *            Christof Schmitt
 *            Martin Petermann
 *            Sven Schuetz
26 27
 */

28 29 30
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

31
#include <linux/miscdevice.h>
32
#include <linux/seq_file.h>
L
Linus Torvalds 已提交
33 34
#include "zfcp_ext.h"

35 36
#define ZFCP_BUS_ID_SIZE	20

37
MODULE_AUTHOR("IBM Deutschland Entwicklung GmbH - linux390@de.ibm.com");
38
MODULE_DESCRIPTION("FCP HBA driver");
L
Linus Torvalds 已提交
39 40
MODULE_LICENSE("GPL");

41 42
static char *init_device;
module_param_named(device, init_device, charp, 0400);
L
Linus Torvalds 已提交
43 44
MODULE_PARM_DESC(device, "specify initial device");

45 46 47 48 49 50
static struct kmem_cache *zfcp_cache_hw_align(const char *name,
					      unsigned long size)
{
	return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL);
}

51
static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
52
{
53
	int idx;
54 55 56 57 58 59

	adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head),
				    GFP_KERNEL);
	if (!adapter->req_list)
		return -ENOMEM;

60 61
	for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
		INIT_LIST_HEAD(&adapter->req_list[idx]);
62 63 64
	return 0;
}

65 66 67 68 69 70
/**
 * zfcp_reqlist_isempty - is the request list empty
 * @adapter: pointer to struct zfcp_adapter
 *
 * Returns: true if list is empty, false otherwise
 */
71 72
int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
{
73
	unsigned int idx;
74

75 76
	for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
		if (!list_empty(&adapter->req_list[idx]))
77 78 79 80
			return 0;
	return 1;
}

81
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
L
Linus Torvalds 已提交
82
{
83
	struct ccw_device *ccwdev;
L
Linus Torvalds 已提交
84 85 86 87
	struct zfcp_adapter *adapter;
	struct zfcp_port *port;
	struct zfcp_unit *unit;

88 89 90 91 92 93
	ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
	if (!ccwdev)
		return;

	if (ccw_device_set_online(ccwdev))
		goto out_ccwdev;
L
Linus Torvalds 已提交
94

95 96
	mutex_lock(&zfcp_data.config_mutex);
	adapter = dev_get_drvdata(&ccwdev->dev);
97
	if (!adapter)
98 99 100 101 102
		goto out_unlock;
	zfcp_adapter_get(adapter);

	port = zfcp_get_port_by_wwpn(adapter, wwpn);
	if (!port)
L
Linus Torvalds 已提交
103
		goto out_port;
104 105

	zfcp_port_get(port);
106
	unit = zfcp_unit_enqueue(port, lun);
107
	if (IS_ERR(unit))
L
Linus Torvalds 已提交
108
		goto out_unit;
109
	mutex_unlock(&zfcp_data.config_mutex);
110

111
	zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
L
Linus Torvalds 已提交
112
	zfcp_erp_wait(adapter);
113
	flush_work(&unit->scsi_work);
114

115
	mutex_lock(&zfcp_data.config_mutex);
L
Linus Torvalds 已提交
116
	zfcp_unit_put(unit);
117
out_unit:
L
Linus Torvalds 已提交
118
	zfcp_port_put(port);
119
out_port:
L
Linus Torvalds 已提交
120
	zfcp_adapter_put(adapter);
121
out_unlock:
122
	mutex_unlock(&zfcp_data.config_mutex);
123 124
out_ccwdev:
	put_device(&ccwdev->dev);
L
Linus Torvalds 已提交
125 126 127
	return;
}

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
static void __init zfcp_init_device_setup(char *devstr)
{
	char *token;
	char *str;
	char busid[ZFCP_BUS_ID_SIZE];
	u64 wwpn, lun;

	/* duplicate devstr and keep the original for sysfs presentation*/
	str = kmalloc(strlen(devstr) + 1, GFP_KERNEL);
	if (!str)
		return;

	strcpy(str, devstr);

	token = strsep(&str, ",");
	if (!token || strlen(token) >= ZFCP_BUS_ID_SIZE)
		goto err_out;
	strncpy(busid, token, ZFCP_BUS_ID_SIZE);

	token = strsep(&str, ",");
	if (!token || strict_strtoull(token, 0, (unsigned long long *) &wwpn))
		goto err_out;

	token = strsep(&str, ",");
	if (!token || strict_strtoull(token, 0, (unsigned long long *) &lun))
		goto err_out;

	kfree(str);
	zfcp_init_device_configure(busid, wwpn, lun);
	return;

 err_out:
	kfree(str);
	pr_err("%s is not a valid SCSI device\n", devstr);
}

164
static int __init zfcp_module_init(void)
L
Linus Torvalds 已提交
165
{
166 167
	int retval = -ENOMEM;

168 169 170
	zfcp_data.gpn_ft_cache = zfcp_cache_hw_align("zfcp_gpn",
					sizeof(struct ct_iu_gpn_ft_req));
	if (!zfcp_data.gpn_ft_cache)
171
		goto out;
L
Linus Torvalds 已提交
172

173 174 175 176 177 178 179
	zfcp_data.qtcb_cache = zfcp_cache_hw_align("zfcp_qtcb",
					sizeof(struct fsf_qtcb));
	if (!zfcp_data.qtcb_cache)
		goto out_qtcb_cache;

	zfcp_data.sr_buffer_cache = zfcp_cache_hw_align("zfcp_sr",
					sizeof(struct fsf_status_read_buffer));
180 181 182
	if (!zfcp_data.sr_buffer_cache)
		goto out_sr_cache;

183 184
	zfcp_data.gid_pn_cache = zfcp_cache_hw_align("zfcp_gid",
					sizeof(struct zfcp_gid_pn_data));
185 186
	if (!zfcp_data.gid_pn_cache)
		goto out_gid_cache;
L
Linus Torvalds 已提交
187

188
	mutex_init(&zfcp_data.config_mutex);
189 190
	rwlock_init(&zfcp_data.config_lock);

191 192 193 194
	zfcp_data.scsi_transport_template =
		fc_attach_transport(&zfcp_transport_functions);
	if (!zfcp_data.scsi_transport_template)
		goto out_transport;
L
Linus Torvalds 已提交
195 196

	retval = misc_register(&zfcp_cfdc_misc);
197
	if (retval) {
198
		pr_err("Registering the misc device zfcp_cfdc failed\n");
199
		goto out_misc;
L
Linus Torvalds 已提交
200 201 202 203
	}

	retval = zfcp_ccw_register();
	if (retval) {
204
		pr_err("The zfcp device driver could not register with "
205
		       "the common I/O layer\n");
L
Linus Torvalds 已提交
206 207 208
		goto out_ccw_register;
	}

209 210 211
	if (init_device)
		zfcp_init_device_setup(init_device);
	return 0;
L
Linus Torvalds 已提交
212

213
out_ccw_register:
L
Linus Torvalds 已提交
214
	misc_deregister(&zfcp_cfdc_misc);
215
out_misc:
216
	fc_release_transport(zfcp_data.scsi_transport_template);
217
out_transport:
218
	kmem_cache_destroy(zfcp_data.gid_pn_cache);
219
out_gid_cache:
220
	kmem_cache_destroy(zfcp_data.sr_buffer_cache);
221
out_sr_cache:
222 223 224
	kmem_cache_destroy(zfcp_data.qtcb_cache);
out_qtcb_cache:
	kmem_cache_destroy(zfcp_data.gpn_ft_cache);
225
out:
L
Linus Torvalds 已提交
226 227 228
	return retval;
}

229
module_init(zfcp_module_init);
L
Linus Torvalds 已提交
230 231 232 233 234

/**
 * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
 * @port: pointer to port to search for unit
 * @fcp_lun: FCP LUN to search for
235 236
 *
 * Returns: pointer to zfcp_unit or NULL
L
Linus Torvalds 已提交
237
 */
238
struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
L
Linus Torvalds 已提交
239 240 241
{
	struct zfcp_unit *unit;

242
	list_for_each_entry(unit, &port->unit_list_head, list)
L
Linus Torvalds 已提交
243
		if ((unit->fcp_lun == fcp_lun) &&
244 245 246
		    !(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_REMOVE))
		    return unit;
	return NULL;
L
Linus Torvalds 已提交
247 248 249 250 251 252
}

/**
 * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn
 * @adapter: pointer to adapter to search for port
 * @wwpn: wwpn to search for
253 254
 *
 * Returns: pointer to zfcp_port or NULL
L
Linus Torvalds 已提交
255
 */
256
struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
257
					u64 wwpn)
L
Linus Torvalds 已提交
258 259 260
{
	struct zfcp_port *port;

261
	list_for_each_entry(port, &adapter->port_list_head, list)
262 263
		if ((port->wwpn == wwpn) &&
		    !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE))
264 265
			return port;
	return NULL;
L
Linus Torvalds 已提交
266 267
}

268 269 270 271 272
static void zfcp_sysfs_unit_release(struct device *dev)
{
	kfree(container_of(dev, struct zfcp_unit, sysfs_device));
}

L
Linus Torvalds 已提交
273 274 275 276
/**
 * zfcp_unit_enqueue - enqueue unit to unit list of a port.
 * @port: pointer to port where unit is added
 * @fcp_lun: FCP LUN of unit to be enqueued
277
 * Returns: pointer to enqueued unit on success, ERR_PTR on error
278
 * Locks: config_mutex must be held to serialize changes to the unit list
L
Linus Torvalds 已提交
279 280 281
 *
 * Sets up some unit internal structures and creates sysfs entry.
 */
282
struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
L
Linus Torvalds 已提交
283
{
284
	struct zfcp_unit *unit;
L
Linus Torvalds 已提交
285

286 287 288 289 290 291 292
	read_lock_irq(&zfcp_data.config_lock);
	if (zfcp_get_unit_by_lun(port, fcp_lun)) {
		read_unlock_irq(&zfcp_data.config_lock);
		return ERR_PTR(-EINVAL);
	}
	read_unlock_irq(&zfcp_data.config_lock);

293
	unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
L
Linus Torvalds 已提交
294
	if (!unit)
295
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
296 297 298

	atomic_set(&unit->refcount, 0);
	init_waitqueue_head(&unit->remove_wq);
299
	INIT_WORK(&unit->scsi_work, zfcp_scsi_scan);
L
Linus Torvalds 已提交
300 301 302 303

	unit->port = port;
	unit->fcp_lun = fcp_lun;

304 305 306 307 308
	if (dev_set_name(&unit->sysfs_device, "0x%016llx",
			 (unsigned long long) fcp_lun)) {
		kfree(unit);
		return ERR_PTR(-ENOMEM);
	}
L
Linus Torvalds 已提交
309 310 311 312 313 314 315
	unit->sysfs_device.parent = &port->sysfs_device;
	unit->sysfs_device.release = zfcp_sysfs_unit_release;
	dev_set_drvdata(&unit->sysfs_device, unit);

	/* mark unit unusable as long as sysfs registration is not complete */
	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);

316 317 318 319 320 321 322 323
	spin_lock_init(&unit->latencies.lock);
	unit->latencies.write.channel.min = 0xFFFFFFFF;
	unit->latencies.write.fabric.min = 0xFFFFFFFF;
	unit->latencies.read.channel.min = 0xFFFFFFFF;
	unit->latencies.read.fabric.min = 0xFFFFFFFF;
	unit->latencies.cmd.channel.min = 0xFFFFFFFF;
	unit->latencies.cmd.fabric.min = 0xFFFFFFFF;

324 325 326 327
	if (device_register(&unit->sysfs_device)) {
		put_device(&unit->sysfs_device);
		return ERR_PTR(-EINVAL);
	}
L
Linus Torvalds 已提交
328

329 330
	if (sysfs_create_group(&unit->sysfs_device.kobj,
			       &zfcp_sysfs_unit_attrs)) {
L
Linus Torvalds 已提交
331
		device_unregister(&unit->sysfs_device);
332
		return ERR_PTR(-EINVAL);
L
Linus Torvalds 已提交
333 334 335 336 337
	}

	zfcp_unit_get(unit);

	write_lock_irq(&zfcp_data.config_lock);
338
	list_add_tail(&unit->list, &port->unit_list_head);
L
Linus Torvalds 已提交
339 340
	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
341

L
Linus Torvalds 已提交
342 343 344 345 346 347 348
	write_unlock_irq(&zfcp_data.config_lock);

	zfcp_port_get(port);

	return unit;
}

349 350 351 352 353 354 355 356
/**
 * zfcp_unit_dequeue - dequeue unit
 * @unit: pointer to zfcp_unit
 *
 * waits until all work is done on unit and removes it then from the unit->list
 * of the associated port.
 */
void zfcp_unit_dequeue(struct zfcp_unit *unit)
L
Linus Torvalds 已提交
357
{
358
	wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0);
L
Linus Torvalds 已提交
359 360 361 362
	write_lock_irq(&zfcp_data.config_lock);
	list_del(&unit->list);
	write_unlock_irq(&zfcp_data.config_lock);
	zfcp_port_put(unit->port);
363
	sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs);
L
Linus Torvalds 已提交
364 365 366
	device_unregister(&unit->sysfs_device);
}

367
static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
368
{
369
	/* must only be called with zfcp_data.config_mutex taken */
370 371 372
	adapter->pool.erp_req =
		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
	if (!adapter->pool.erp_req)
L
Linus Torvalds 已提交
373 374
		return -ENOMEM;

375 376 377 378 379
	adapter->pool.gid_pn_req =
		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
	if (!adapter->pool.gid_pn_req)
		return -ENOMEM;

380 381 382
	adapter->pool.scsi_req =
		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
	if (!adapter->pool.scsi_req)
L
Linus Torvalds 已提交
383 384
		return -ENOMEM;

385 386 387
	adapter->pool.scsi_abort =
		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
	if (!adapter->pool.scsi_abort)
L
Linus Torvalds 已提交
388 389
		return -ENOMEM;

390
	adapter->pool.status_read_req =
391
		mempool_create_kmalloc_pool(FSF_STATUS_READS_RECOM,
392
					    sizeof(struct zfcp_fsf_req));
393 394 395 396
	if (!adapter->pool.status_read_req)
		return -ENOMEM;

	adapter->pool.qtcb_pool =
397
		mempool_create_slab_pool(4, zfcp_data.qtcb_cache);
398
	if (!adapter->pool.qtcb_pool)
L
Linus Torvalds 已提交
399 400
		return -ENOMEM;

401
	adapter->pool.status_read_data =
402
		mempool_create_slab_pool(FSF_STATUS_READS_RECOM,
403
					 zfcp_data.sr_buffer_cache);
404
	if (!adapter->pool.status_read_data)
L
Linus Torvalds 已提交
405 406
		return -ENOMEM;

407
	adapter->pool.gid_pn_data =
408
		mempool_create_slab_pool(1, zfcp_data.gid_pn_cache);
409
	if (!adapter->pool.gid_pn_data)
L
Linus Torvalds 已提交
410 411 412 413 414
		return -ENOMEM;

	return 0;
}

415
static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
416
{
417
	/* zfcp_data.config_mutex must be held */
418 419 420 421 422 423 424 425 426 427 428 429 430 431
	if (adapter->pool.erp_req)
		mempool_destroy(adapter->pool.erp_req);
	if (adapter->pool.scsi_req)
		mempool_destroy(adapter->pool.scsi_req);
	if (adapter->pool.scsi_abort)
		mempool_destroy(adapter->pool.scsi_abort);
	if (adapter->pool.qtcb_pool)
		mempool_destroy(adapter->pool.qtcb_pool);
	if (adapter->pool.status_read_req)
		mempool_destroy(adapter->pool.status_read_req);
	if (adapter->pool.status_read_data)
		mempool_destroy(adapter->pool.status_read_data);
	if (adapter->pool.gid_pn_data)
		mempool_destroy(adapter->pool.gid_pn_data);
L
Linus Torvalds 已提交
432 433
}

434 435 436 437 438 439 440 441 442
/**
 * zfcp_status_read_refill - refill the long running status_read_requests
 * @adapter: ptr to struct zfcp_adapter for which the buffers should be refilled
 *
 * Returns: 0 on success, 1 otherwise
 *
 * if there are 16 or more status_read requests missing an adapter_reopen
 * is triggered
 */
443 444 445
int zfcp_status_read_refill(struct zfcp_adapter *adapter)
{
	while (atomic_read(&adapter->stat_miss) > 0)
446
		if (zfcp_fsf_status_read(adapter->qdio)) {
447
			if (atomic_read(&adapter->stat_miss) >= 16) {
448 449
				zfcp_erp_adapter_reopen(adapter, 0, "axsref1",
							NULL);
450 451
				return 1;
			}
452
			break;
453 454
		} else
			atomic_dec(&adapter->stat_miss);
455 456 457 458 459 460 461 462 463
	return 0;
}

static void _zfcp_status_read_scheduler(struct work_struct *work)
{
	zfcp_status_read_refill(container_of(work, struct zfcp_adapter,
					     stat_work));
}

464 465 466 467 468 469 470 471 472 473
static void zfcp_print_sl(struct seq_file *m, struct service_level *sl)
{
	struct zfcp_adapter *adapter =
		container_of(sl, struct zfcp_adapter, service_level);

	seq_printf(m, "zfcp: %s microcode level %x\n",
		   dev_name(&adapter->ccw_device->dev),
		   adapter->fsf_lic_version);
}

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
static int zfcp_setup_adapter_work_queue(struct zfcp_adapter *adapter)
{
	char name[TASK_COMM_LEN];

	snprintf(name, sizeof(name), "zfcp_q_%s",
		 dev_name(&adapter->ccw_device->dev));
	adapter->work_queue = create_singlethread_workqueue(name);

	if (adapter->work_queue)
		return 0;
	return -ENOMEM;
}

static void zfcp_destroy_adapter_work_queue(struct zfcp_adapter *adapter)
{
	if (adapter->work_queue)
		destroy_workqueue(adapter->work_queue);
	adapter->work_queue = NULL;

}

495 496 497 498 499 500
/**
 * zfcp_adapter_enqueue - enqueue a new adapter to the list
 * @ccw_device: pointer to the struct cc_device
 *
 * Returns:	0             if a new adapter was successfully enqueued
 *		-ENOMEM       if alloc failed
L
Linus Torvalds 已提交
501 502 503
 * Enqueues an adapter at the end of the adapter list in the driver data.
 * All adapter internal structures are set up.
 * Proc-fs entries are also created.
504
 * locks: config_mutex must be held to serialize changes to the adapter list
L
Linus Torvalds 已提交
505
 */
506
int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
L
Linus Torvalds 已提交
507 508 509 510
{
	struct zfcp_adapter *adapter;

	/*
S
Swen Schillig 已提交
511
	 * Note: It is safe to release the list_lock, as any list changes
512
	 * are protected by the config_mutex, which must be held to get here
L
Linus Torvalds 已提交
513 514
	 */

515
	adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL);
C
Christof Schmitt 已提交
516
	if (!adapter)
517
		return -ENOMEM;
L
Linus Torvalds 已提交
518 519 520

	ccw_device->handler = NULL;
	adapter->ccw_device = ccw_device;
521
	atomic_set(&adapter->refcount, 0);
L
Linus Torvalds 已提交
522

523 524
	if (zfcp_qdio_setup(adapter))
		goto qdio_failed;
L
Linus Torvalds 已提交
525

S
Swen Schillig 已提交
526
	if (zfcp_allocate_low_mem_buffers(adapter))
527
		goto low_mem_buffers_failed;
L
Linus Torvalds 已提交
528

529
	if (zfcp_reqlist_alloc(adapter))
530
		goto low_mem_buffers_failed;
531

S
Swen Schillig 已提交
532
	if (zfcp_dbf_adapter_register(adapter))
533 534
		goto debug_register_failed;

535 536 537
	if (zfcp_setup_adapter_work_queue(adapter))
		goto work_queue_failed;

538 539 540
	if (zfcp_fc_gs_setup(adapter))
		goto generic_services_failed;

L
Linus Torvalds 已提交
541
	init_waitqueue_head(&adapter->remove_wq);
542
	init_waitqueue_head(&adapter->erp_ready_wq);
543
	init_waitqueue_head(&adapter->erp_done_wqh);
L
Linus Torvalds 已提交
544 545

	INIT_LIST_HEAD(&adapter->port_list_head);
546 547
	INIT_LIST_HEAD(&adapter->erp_ready_head);
	INIT_LIST_HEAD(&adapter->erp_running_head);
L
Linus Torvalds 已提交
548

549
	spin_lock_init(&adapter->req_list_lock);
550 551

	rwlock_init(&adapter->erp_lock);
L
Linus Torvalds 已提交
552 553
	rwlock_init(&adapter->abort_lock);

554 555 556
	if (zfcp_erp_thread_setup(adapter))
		goto erp_thread_failed;

557
	INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
558
	INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later);
L
Linus Torvalds 已提交
559

560 561
	adapter->service_level.seq_print = zfcp_print_sl;

L
Linus Torvalds 已提交
562 563 564 565 566
	/* mark adapter unusable as long as sysfs registration is not complete */
	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);

	dev_set_drvdata(&ccw_device->dev, adapter);

567 568
	if (sysfs_create_group(&ccw_device->dev.kobj,
			       &zfcp_sysfs_adapter_attrs))
L
Linus Torvalds 已提交
569 570 571
		goto sysfs_failed;

	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
572

573 574
	if (!zfcp_adapter_scsi_register(adapter))
		return 0;
L
Linus Torvalds 已提交
575

576
sysfs_failed:
577 578
	zfcp_erp_thread_kill(adapter);
erp_thread_failed:
579 580
	zfcp_fc_gs_destroy(adapter);
generic_services_failed:
581 582
	zfcp_destroy_adapter_work_queue(adapter);
work_queue_failed:
S
Swen Schillig 已提交
583
	zfcp_dbf_adapter_unregister(adapter->dbf);
584
debug_register_failed:
L
Linus Torvalds 已提交
585
	dev_set_drvdata(&ccw_device->dev, NULL);
586
	kfree(adapter->req_list);
587
low_mem_buffers_failed:
L
Linus Torvalds 已提交
588
	zfcp_free_low_mem_buffers(adapter);
589 590
qdio_failed:
	zfcp_qdio_destroy(adapter->qdio);
L
Linus Torvalds 已提交
591
	kfree(adapter);
592
	return -ENOMEM;
L
Linus Torvalds 已提交
593 594
}

595 596 597
/**
 * zfcp_adapter_dequeue - remove the adapter from the resource list
 * @adapter: pointer to struct zfcp_adapter which should be removed
L
Linus Torvalds 已提交
598 599
 * locks:	adapter list write lock is assumed to be held by caller
 */
600
void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
601 602 603 604
{
	int retval = 0;
	unsigned long flags;

605
	cancel_work_sync(&adapter->stat_work);
606
	zfcp_fc_wka_ports_force_offline(adapter->gs);
607
	zfcp_adapter_scsi_unregister(adapter);
608 609
	sysfs_remove_group(&adapter->ccw_device->dev.kobj,
			   &zfcp_sysfs_adapter_attrs);
L
Linus Torvalds 已提交
610 611
	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
	/* sanity check: no pending FSF requests */
612 613 614
	spin_lock_irqsave(&adapter->req_list_lock, flags);
	retval = zfcp_reqlist_isempty(adapter);
	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
615 616
	if (!retval)
		return;
L
Linus Torvalds 已提交
617

618
	zfcp_fc_gs_destroy(adapter);
619
	zfcp_erp_thread_kill(adapter);
620
	zfcp_destroy_adapter_work_queue(adapter);
S
Swen Schillig 已提交
621
	zfcp_dbf_adapter_unregister(adapter->dbf);
L
Linus Torvalds 已提交
622
	zfcp_free_low_mem_buffers(adapter);
623
	zfcp_qdio_destroy(adapter->qdio);
624
	kfree(adapter->req_list);
625 626
	kfree(adapter->fc_stats);
	kfree(adapter->stats_reset_data);
L
Linus Torvalds 已提交
627 628 629
	kfree(adapter);
}

630 631 632 633 634
static void zfcp_sysfs_port_release(struct device *dev)
{
	kfree(container_of(dev, struct zfcp_port, sysfs_device));
}

L
Linus Torvalds 已提交
635 636 637 638 639 640
/**
 * zfcp_port_enqueue - enqueue port to port list of adapter
 * @adapter: adapter where remote port is added
 * @wwpn: WWPN of the remote port to be enqueued
 * @status: initial status for the port
 * @d_id: destination id of the remote port to be enqueued
641
 * Returns: pointer to enqueued port on success, ERR_PTR on error
642
 * Locks: config_mutex must be held to serialize changes to the port list
L
Linus Torvalds 已提交
643 644 645 646 647
 *
 * All port internal structures are set up and the sysfs entry is generated.
 * d_id is used to enqueue ports with a well known address like the Directory
 * Service for nameserver lookup.
 */
648
struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
649
				     u32 status, u32 d_id)
L
Linus Torvalds 已提交
650
{
651
	struct zfcp_port *port;
652 653 654 655 656 657 658

	read_lock_irq(&zfcp_data.config_lock);
	if (zfcp_get_port_by_wwpn(adapter, wwpn)) {
		read_unlock_irq(&zfcp_data.config_lock);
		return ERR_PTR(-EINVAL);
	}
	read_unlock_irq(&zfcp_data.config_lock);
L
Linus Torvalds 已提交
659

660
	port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
661
	if (!port)
662
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
663 664 665

	init_waitqueue_head(&port->remove_wq);
	INIT_LIST_HEAD(&port->unit_list_head);
666
	INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
667
	INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
668
	INIT_WORK(&port->rport_work, zfcp_scsi_rport_work);
L
Linus Torvalds 已提交
669 670

	port->adapter = adapter;
671 672
	port->d_id = d_id;
	port->wwpn = wwpn;
673
	port->rport_task = RPORT_NONE;
L
Linus Torvalds 已提交
674

675 676 677
	/* mark port unusable as long as sysfs registration is not complete */
	atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
	atomic_set(&port->refcount, 0);
L
Linus Torvalds 已提交
678

679 680 681 682 683
	if (dev_set_name(&port->sysfs_device, "0x%016llx",
			 (unsigned long long)wwpn)) {
		kfree(port);
		return ERR_PTR(-ENOMEM);
	}
684
	port->sysfs_device.parent = &adapter->ccw_device->dev;
L
Linus Torvalds 已提交
685 686 687
	port->sysfs_device.release = zfcp_sysfs_port_release;
	dev_set_drvdata(&port->sysfs_device, port);

688 689
	if (device_register(&port->sysfs_device)) {
		put_device(&port->sysfs_device);
690
		return ERR_PTR(-EINVAL);
691
	}
L
Linus Torvalds 已提交
692

693 694
	if (sysfs_create_group(&port->sysfs_device.kobj,
			       &zfcp_sysfs_port_attrs)) {
L
Linus Torvalds 已提交
695
		device_unregister(&port->sysfs_device);
696
		return ERR_PTR(-EINVAL);
L
Linus Torvalds 已提交
697 698 699 700 701
	}

	zfcp_port_get(port);

	write_lock_irq(&zfcp_data.config_lock);
702
	list_add_tail(&port->list, &adapter->port_list_head);
L
Linus Torvalds 已提交
703 704
	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
705

L
Linus Torvalds 已提交
706 707 708 709 710 711
	write_unlock_irq(&zfcp_data.config_lock);

	zfcp_adapter_get(adapter);
	return port;
}

712 713 714 715 716
/**
 * zfcp_port_dequeue - dequeues a port from the port list of the adapter
 * @port: pointer to struct zfcp_port which should be removed
 */
void zfcp_port_dequeue(struct zfcp_port *port)
L
Linus Torvalds 已提交
717 718 719 720
{
	write_lock_irq(&zfcp_data.config_lock);
	list_del(&port->list);
	write_unlock_irq(&zfcp_data.config_lock);
721 722
	wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
	cancel_work_sync(&port->rport_work); /* usually not necessary */
L
Linus Torvalds 已提交
723
	zfcp_adapter_put(port->adapter);
724
	sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
L
Linus Torvalds 已提交
725 726 727
	device_unregister(&port->sysfs_device);
}

728 729 730 731 732 733
/**
 * zfcp_sg_free_table - free memory used by scatterlists
 * @sg: pointer to scatterlist
 * @count: number of scatterlist which are to be free'ed
 * the scatterlist are expected to reference pages always
 */
734 735 736 737 738 739 740 741 742 743 744
void zfcp_sg_free_table(struct scatterlist *sg, int count)
{
	int i;

	for (i = 0; i < count; i++, sg++)
		if (sg)
			free_page((unsigned long) sg_virt(sg));
		else
			break;
}

745 746 747 748 749 750 751 752
/**
 * zfcp_sg_setup_table - init scatterlist and allocate, assign buffers
 * @sg: pointer to struct scatterlist
 * @count: number of scatterlists which should be assigned with buffers
 * of size page
 *
 * Returns: 0 on success, -ENOMEM otherwise
 */
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
int zfcp_sg_setup_table(struct scatterlist *sg, int count)
{
	void *addr;
	int i;

	sg_init_table(sg, count);
	for (i = 0; i < count; i++, sg++) {
		addr = (void *) get_zeroed_page(GFP_KERNEL);
		if (!addr) {
			zfcp_sg_free_table(sg, i);
			return -ENOMEM;
		}
		sg_set_buf(sg, addr, PAGE_SIZE);
	}
	return 0;
}