11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * zfcp device driver
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * Module interface and handling of zfcp data structures.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
69edf7d75ee5f21663a0183d21f702682d0ef132fSteffen Maier * Copyright IBM Corp. 2002, 2013
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
94a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann/*
104a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann * Driver authors:
114a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Martin Peschke (originator of the driver)
124a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Raimund Schroeder
134a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Aron Zeh
144a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Wolfgang Taphorn
154a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Stefan Bader
164a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Heiko Carstens (kernel 2.6 port of the driver)
174a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Andreas Herrmann
184a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Maxim Shchetynin
194a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Volker Sameske
204a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann *            Ralph Wuerthner
21553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt *            Michael Loehr
22553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt *            Swen Schillig
23553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt *            Christof Schmitt
24553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt *            Martin Petermann
25553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt *            Sven Schuetz
269edf7d75ee5f21663a0183d21f702682d0ef132fSteffen Maier *            Steffen Maier
274a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann */
284a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann
29ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define KMSG_COMPONENT "zfcp"
30ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
31ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt
3245633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt#include <linux/miscdevice.h>
33bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt#include <linux/seq_file.h>
345a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
353a4c5d5964ed43a5524f6d289fb4cd37d39f3f1aHeiko Carstens#include <linux/module.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "zfcp_ext.h"
37dbf5dfe9dbcecf159139eec25ad256738cbc3715Christof Schmitt#include "zfcp_fc.h"
38b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt#include "zfcp_reqlist.h"
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4098df67b324a2a986987ce29986e44ae9156b6698Kay Sievers#define ZFCP_BUS_ID_SIZE	20
4198df67b324a2a986987ce29986e44ae9156b6698Kay Sievers
424a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas HerrmannMODULE_AUTHOR("IBM Deutschland Entwicklung GmbH - linux390@de.ibm.com");
43317e6b6519b5a34263a33f150ed57ad468b26a64Swen SchilligMODULE_DESCRIPTION("FCP HBA driver");
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
463623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmittstatic char *init_device;
473623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmittmodule_param_named(device, init_device, charp, 0400);
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(device, "specify initial device");
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051780d2c38a7294c2c302ae9d2ea517bd4153decChristof Schmittstatic struct kmem_cache * __init zfcp_cache_hw_align(const char *name,
5151780d2c38a7294c2c302ae9d2ea517bd4153decChristof Schmitt						      unsigned long size)
52a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig{
53a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL);
54a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig}
55a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
563623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmittstatic void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
58de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	struct ccw_device *cdev;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zfcp_adapter *adapter;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zfcp_port *port;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
63de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	if (!cdev)
64c5afd81e5d7ebacc9dd23954e169ac79a34fe399Christof Schmitt		return;
65c5afd81e5d7ebacc9dd23954e169ac79a34fe399Christof Schmitt
66de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	if (ccw_device_set_online(cdev))
67de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig		goto out_ccw_device;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
69de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	adapter = zfcp_ccw_adapter_by_cdev(cdev);
70317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	if (!adapter)
71de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig		goto out_ccw_device;
72c5afd81e5d7ebacc9dd23954e169ac79a34fe399Christof Schmitt
73c5afd81e5d7ebacc9dd23954e169ac79a34fe399Christof Schmitt	port = zfcp_get_port_by_wwpn(adapter, wwpn);
74c5afd81e5d7ebacc9dd23954e169ac79a34fe399Christof Schmitt	if (!port)
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_port;
7691978465b1e5f89025cd43cd2102943160ec6deeChristof Schmitt	flush_work(&port->rport_work);
77091694a556d168dc9df4d79e3a40116550b183cfSwen Schillig
781daa4eb50fa5cd4c8f9c55452606e786fd42053bChristof Schmitt	zfcp_unit_add(port, lun);
79615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	put_device(&port->dev);
801daa4eb50fa5cd4c8f9c55452606e786fd42053bChristof Schmitt
81317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schilligout_port:
82de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_ccw_adapter_put(adapter);
83de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schilligout_ccw_device:
84de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	put_device(&cdev->dev);
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
883623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmittstatic void __init zfcp_init_device_setup(char *devstr)
893623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt{
903623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	char *token;
91d10c0858f618c20547d4eda8aee9c3afd91599cfHeiko Carstens	char *str, *str_saved;
923623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	char busid[ZFCP_BUS_ID_SIZE];
933623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	u64 wwpn, lun;
943623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt
953623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	/* duplicate devstr and keep the original for sysfs presentation*/
96674c3a993c278b7469e1cf12bfc13e6838dfd877Christof Schmitt	str_saved = kstrdup(devstr, GFP_KERNEL);
97d10c0858f618c20547d4eda8aee9c3afd91599cfHeiko Carstens	str = str_saved;
983623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	if (!str)
993623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt		return;
1003623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt
1013623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	token = strsep(&str, ",");
1023623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	if (!token || strlen(token) >= ZFCP_BUS_ID_SIZE)
1033623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt		goto err_out;
1043623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	strncpy(busid, token, ZFCP_BUS_ID_SIZE);
1053623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt
1063623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	token = strsep(&str, ",");
107ee732ea8298ff5a38582f12354d9bbf0cb1faac1Martin Peschke	if (!token || kstrtoull(token, 0, (unsigned long long *) &wwpn))
1083623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt		goto err_out;
1093623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt
1103623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	token = strsep(&str, ",");
111ee732ea8298ff5a38582f12354d9bbf0cb1faac1Martin Peschke	if (!token || kstrtoull(token, 0, (unsigned long long *) &lun))
1123623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt		goto err_out;
1133623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt
114d10c0858f618c20547d4eda8aee9c3afd91599cfHeiko Carstens	kfree(str_saved);
1153623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	zfcp_init_device_configure(busid, wwpn, lun);
1163623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	return;
1173623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt
118d10c0858f618c20547d4eda8aee9c3afd91599cfHeiko Carstenserr_out:
119d10c0858f618c20547d4eda8aee9c3afd91599cfHeiko Carstens	kfree(str_saved);
1203623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	pr_err("%s is not a valid SCSI device\n", devstr);
1213623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt}
1223623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt
123317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schilligstatic int __init zfcp_module_init(void)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
125dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens	int retval = -ENOMEM;
126dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens
127259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt	zfcp_fsf_qtcb_cache = zfcp_cache_hw_align("zfcp_fsf_qtcb",
128259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt						  sizeof(struct fsf_qtcb));
129259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt	if (!zfcp_fsf_qtcb_cache)
130a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		goto out_qtcb_cache;
131a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
132087897e36982ef8536dc9c8baed159a31517b5e6Christof Schmitt	zfcp_fc_req_cache = zfcp_cache_hw_align("zfcp_fc_req",
133087897e36982ef8536dc9c8baed159a31517b5e6Christof Schmitt						sizeof(struct zfcp_fc_req));
134087897e36982ef8536dc9c8baed159a31517b5e6Christof Schmitt	if (!zfcp_fc_req_cache)
135087897e36982ef8536dc9c8baed159a31517b5e6Christof Schmitt		goto out_fc_cache;
136ee744622c65cd66824e8dd1b9509e515c800de14Christof Schmitt
1371947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	zfcp_scsi_transport_template =
138dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens		fc_attach_transport(&zfcp_transport_functions);
1391947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	if (!zfcp_scsi_transport_template)
140dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens		goto out_transport;
1411947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	scsi_transport_reserve_device(zfcp_scsi_transport_template,
14257c237731b92fadc7d44824276313ec330b1989bChristof Schmitt				      sizeof(struct zfcp_scsi_dev));
14357c237731b92fadc7d44824276313ec330b1989bChristof Schmitt
144c1fad4176464281e776022dee7d029144afbeb13Christof Schmitt	retval = ccw_driver_register(&zfcp_ccw_driver);
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
146ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt		pr_err("The zfcp device driver could not register with "
147ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		       "the common I/O layer\n");
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_ccw_register;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1513623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	if (init_device)
1523623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt		zfcp_init_device_setup(init_device);
1533623ecba19660d1d838f8b1a4d1e80007d603617Christof Schmitt	return 0;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
155317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schilligout_ccw_register:
1561947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	fc_release_transport(zfcp_scsi_transport_template);
157317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schilligout_transport:
158087897e36982ef8536dc9c8baed159a31517b5e6Christof Schmitt	kmem_cache_destroy(zfcp_fc_req_cache);
159087897e36982ef8536dc9c8baed159a31517b5e6Christof Schmittout_fc_cache:
160259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt	kmem_cache_destroy(zfcp_fsf_qtcb_cache);
161a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligout_qtcb_cache:
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
165317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schilligmodule_init(zfcp_module_init);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167c1fad4176464281e776022dee7d029144afbeb13Christof Schmittstatic void __exit zfcp_module_exit(void)
168c1fad4176464281e776022dee7d029144afbeb13Christof Schmitt{
169c1fad4176464281e776022dee7d029144afbeb13Christof Schmitt	ccw_driver_unregister(&zfcp_ccw_driver);
1701947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	fc_release_transport(zfcp_scsi_transport_template);
171087897e36982ef8536dc9c8baed159a31517b5e6Christof Schmitt	kmem_cache_destroy(zfcp_fc_req_cache);
172259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt	kmem_cache_destroy(zfcp_fsf_qtcb_cache);
173c1fad4176464281e776022dee7d029144afbeb13Christof Schmitt}
174c1fad4176464281e776022dee7d029144afbeb13Christof Schmitt
175c1fad4176464281e776022dee7d029144afbeb13Christof Schmittmodule_exit(zfcp_module_exit);
176c1fad4176464281e776022dee7d029144afbeb13Christof Schmitt
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: pointer to adapter to search for port
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @wwpn: wwpn to search for
181317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig *
182317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * Returns: pointer to zfcp_port or NULL
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
184317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schilligstruct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
1857ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					u64 wwpn)
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
187ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	unsigned long flags;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zfcp_port *port;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
190ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_lock_irqsave(&adapter->port_list_lock, flags);
191ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	list_for_each_entry(port, &adapter->port_list, list)
1926b183334c23969d52d4d9f775da554480d05ca4dSwen Schillig		if (port->wwpn == wwpn) {
193615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt			if (!get_device(&port->dev))
1946b183334c23969d52d4d9f775da554480d05ca4dSwen Schillig				port = NULL;
195ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig			read_unlock_irqrestore(&adapter->port_list_lock, flags);
196317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig			return port;
197ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig		}
198ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_unlock_irqrestore(&adapter->port_list_lock, flags);
199317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	return NULL;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
202317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schilligstatic int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
204a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	adapter->pool.erp_req =
205a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
206a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (!adapter->pool.erp_req)
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
209799b76d09aeee558d18c1f5b93e63f58f1d1fc11Christof Schmitt	adapter->pool.gid_pn_req =
210799b76d09aeee558d18c1f5b93e63f58f1d1fc11Christof Schmitt		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
211799b76d09aeee558d18c1f5b93e63f58f1d1fc11Christof Schmitt	if (!adapter->pool.gid_pn_req)
212799b76d09aeee558d18c1f5b93e63f58f1d1fc11Christof Schmitt		return -ENOMEM;
213799b76d09aeee558d18c1f5b93e63f58f1d1fc11Christof Schmitt
214a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	adapter->pool.scsi_req =
215a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
216a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (!adapter->pool.scsi_req)
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
219a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	adapter->pool.scsi_abort =
220a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
221a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (!adapter->pool.scsi_abort)
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
224a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	adapter->pool.status_read_req =
225317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig		mempool_create_kmalloc_pool(FSF_STATUS_READS_RECOM,
2260eaae62abaa1ad1f231932b6cdd9fb1b91df6651Matthew Dobson					    sizeof(struct zfcp_fsf_req));
227a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (!adapter->pool.status_read_req)
228a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		return -ENOMEM;
229a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
230a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	adapter->pool.qtcb_pool =
231259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt		mempool_create_slab_pool(4, zfcp_fsf_qtcb_cache);
232a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (!adapter->pool.qtcb_pool)
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
235c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	BUILD_BUG_ON(sizeof(struct fsf_status_read_buffer) > PAGE_SIZE);
236c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	adapter->pool.sr_data =
237c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt		mempool_create_page_pool(FSF_STATUS_READS_RECOM, 0);
238c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	if (!adapter->pool.sr_data)
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241dbf5dfe9dbcecf159139eec25ad256738cbc3715Christof Schmitt	adapter->pool.gid_pn =
242fcf7e6144df60cd5082e5bc52f1ca5d1ca99a2d6Christof Schmitt		mempool_create_slab_pool(1, zfcp_fc_req_cache);
243dbf5dfe9dbcecf159139eec25ad256738cbc3715Christof Schmitt	if (!adapter->pool.gid_pn)
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
249317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schilligstatic void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
251a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (adapter->pool.erp_req)
252a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_destroy(adapter->pool.erp_req);
253a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (adapter->pool.scsi_req)
254a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_destroy(adapter->pool.scsi_req);
255a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (adapter->pool.scsi_abort)
256a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_destroy(adapter->pool.scsi_abort);
257a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (adapter->pool.qtcb_pool)
258a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_destroy(adapter->pool.qtcb_pool);
259a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (adapter->pool.status_read_req)
260a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_destroy(adapter->pool.status_read_req);
261c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	if (adapter->pool.sr_data)
262c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt		mempool_destroy(adapter->pool.sr_data);
263dbf5dfe9dbcecf159139eec25ad256738cbc3715Christof Schmitt	if (adapter->pool.gid_pn)
264dbf5dfe9dbcecf159139eec25ad256738cbc3715Christof Schmitt		mempool_destroy(adapter->pool.gid_pn);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
267317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig/**
268317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * zfcp_status_read_refill - refill the long running status_read_requests
269317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * @adapter: ptr to struct zfcp_adapter for which the buffers should be refilled
270317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig *
271317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * Returns: 0 on success, 1 otherwise
272317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig *
273317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * if there are 16 or more status_read requests missing an adapter_reopen
274317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * is triggered
275317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig */
276d26ab06ede83287f99067fee3034c5455a75faf9Swen Schilligint zfcp_status_read_refill(struct zfcp_adapter *adapter)
277d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig{
278d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig	while (atomic_read(&adapter->stat_miss) > 0)
279564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		if (zfcp_fsf_status_read(adapter->qdio)) {
28064deb6efdc5504ce97b5c1c6f281fffbc150bd93Christof Schmitt			if (atomic_read(&adapter->stat_miss) >=
28164deb6efdc5504ce97b5c1c6f281fffbc150bd93Christof Schmitt			    adapter->stat_read_buf_num) {
282ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				zfcp_erp_adapter_reopen(adapter, 0, "axsref1");
2837afe29f7dd6dccbe454d7fd6cd6a5a7f7bcbc530Swen Schillig				return 1;
2847afe29f7dd6dccbe454d7fd6cd6a5a7f7bcbc530Swen Schillig			}
285d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig			break;
2867afe29f7dd6dccbe454d7fd6cd6a5a7f7bcbc530Swen Schillig		} else
2877afe29f7dd6dccbe454d7fd6cd6a5a7f7bcbc530Swen Schillig			atomic_dec(&adapter->stat_miss);
288d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig	return 0;
289d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig}
290d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig
291d26ab06ede83287f99067fee3034c5455a75faf9Swen Schilligstatic void _zfcp_status_read_scheduler(struct work_struct *work)
292d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig{
293d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig	zfcp_status_read_refill(container_of(work, struct zfcp_adapter,
294d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig					     stat_work));
295d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig}
296d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig
297bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmittstatic void zfcp_print_sl(struct seq_file *m, struct service_level *sl)
298bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt{
299bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt	struct zfcp_adapter *adapter =
300bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt		container_of(sl, struct zfcp_adapter, service_level);
301bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt
302bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt	seq_printf(m, "zfcp: %s microcode level %x\n",
303bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt		   dev_name(&adapter->ccw_device->dev),
304bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt		   adapter->fsf_lic_version);
305bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt}
306bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt
3074544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schilligstatic int zfcp_setup_adapter_work_queue(struct zfcp_adapter *adapter)
3084544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig{
3094544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	char name[TASK_COMM_LEN];
3104544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig
3114544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	snprintf(name, sizeof(name), "zfcp_q_%s",
3124544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig		 dev_name(&adapter->ccw_device->dev));
3134544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	adapter->work_queue = create_singlethread_workqueue(name);
3144544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig
3154544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	if (adapter->work_queue)
3164544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig		return 0;
3174544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	return -ENOMEM;
3184544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig}
3194544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig
3204544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schilligstatic void zfcp_destroy_adapter_work_queue(struct zfcp_adapter *adapter)
3214544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig{
3224544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	if (adapter->work_queue)
3234544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig		destroy_workqueue(adapter->work_queue);
3244544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	adapter->work_queue = NULL;
3254544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig
3264544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig}
3274544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig
328317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig/**
329317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * zfcp_adapter_enqueue - enqueue a new adapter to the list
330317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * @ccw_device: pointer to the struct cc_device
331317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig *
332de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig * Returns:	struct zfcp_adapter*
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Enqueues an adapter at the end of the adapter list in the driver data.
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All adapter internal structures are set up.
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Proc-fs entries are also created.
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
337de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schilligstruct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zfcp_adapter *adapter;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	if (!get_device(&ccw_device->dev))
342de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig		return ERR_PTR(-ENODEV);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
344317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL);
345f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	if (!adapter) {
346f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		put_device(&ccw_device->dev);
347de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig		return ERR_PTR(-ENOMEM);
348f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	}
349f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig
350f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	kref_init(&adapter->ref);
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccw_device->handler = NULL;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->ccw_device = ccw_device;
354f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig
355f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
3569eae07ef6bb5988163d8bb82cd952905db47b721Swen Schillig	INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
357038d9446a9e601d7972926ca69fee10eeda6f3c7Christof Schmitt	INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
359d5a282a1c5084ec7ebd9e6ab9723317f6b3fcd7bSwen Schillig	if (zfcp_qdio_setup(adapter))
360f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto failed;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36200bab91066a49468bfa4f6d5c8ad5e9ec53b7ea3Swen Schillig	if (zfcp_allocate_low_mem_buffers(adapter))
363f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto failed;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
365b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt	adapter->req_list = zfcp_reqlist_alloc();
366b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt	if (!adapter->req_list)
367f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto failed;
368317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig
3695771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	if (zfcp_dbf_adapter_register(adapter))
370f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto failed;
371317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig
3724544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	if (zfcp_setup_adapter_work_queue(adapter))
373f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto failed;
3744544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig
375d5a282a1c5084ec7ebd9e6ab9723317f6b3fcd7bSwen Schillig	if (zfcp_fc_gs_setup(adapter))
376f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto failed;
377d5a282a1c5084ec7ebd9e6ab9723317f6b3fcd7bSwen Schillig
378ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	rwlock_init(&adapter->port_list_lock);
379ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	INIT_LIST_HEAD(&adapter->port_list);
380ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig
3812d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz	INIT_LIST_HEAD(&adapter->events.list);
3822d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz	INIT_WORK(&adapter->events.work, zfcp_fc_post_event);
3832d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz	spin_lock_init(&adapter->events.list_lock);
3842d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz
385347c6a965dc110c91a77f65181fc011ee257a4a6Christof Schmitt	init_waitqueue_head(&adapter->erp_ready_wq);
386317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	init_waitqueue_head(&adapter->erp_done_wqh);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
388317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	INIT_LIST_HEAD(&adapter->erp_ready_head);
389317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	INIT_LIST_HEAD(&adapter->erp_running_head);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391c48a29d065cfa18c3e8699f5e3a84a59ad35e062Heiko Carstens	rwlock_init(&adapter->erp_lock);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rwlock_init(&adapter->abort_lock);
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
394143bb6bfe36d20618d8bf667915fe14d14b8ae2fChristof Schmitt	if (zfcp_erp_thread_setup(adapter))
395f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto failed;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
397bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt	adapter->service_level.seq_print = zfcp_print_sl;
398bd43a42b7e9880f426ed715f18bb4f963b7352afChristof Schmitt
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_set_drvdata(&ccw_device->dev, adapter);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40160221920706a01bef89af2577f9a90a8eeb4e662Swen Schillig	if (sysfs_create_group(&ccw_device->dev.kobj,
40260221920706a01bef89af2577f9a90a8eeb4e662Swen Schillig			       &zfcp_sysfs_adapter_attrs))
403f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto failed;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
405683229845f1780b10041ee7a1043fc8f10061455Christof Schmitt	/* report size limit per scatter-gather segment */
406683229845f1780b10041ee7a1043fc8f10061455Christof Schmitt	adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
407683229845f1780b10041ee7a1043fc8f10061455Christof Schmitt	adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
408683229845f1780b10041ee7a1043fc8f10061455Christof Schmitt
4099edf7d75ee5f21663a0183d21f702682d0ef132fSteffen Maier	adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM;
4109edf7d75ee5f21663a0183d21f702682d0ef132fSteffen Maier
4111947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	if (!zfcp_scsi_adapter_register(adapter))
412de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig		return adapter;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
414f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schilligfailed:
415de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_adapter_unregister(adapter);
416de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	return ERR_PTR(-ENOMEM);
417de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig}
418de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig
419de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schilligvoid zfcp_adapter_unregister(struct zfcp_adapter *adapter)
420de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig{
421de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	struct ccw_device *cdev = adapter->ccw_device;
422de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig
423de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	cancel_work_sync(&adapter->scan_work);
424de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	cancel_work_sync(&adapter->stat_work);
425038d9446a9e601d7972926ca69fee10eeda6f3c7Christof Schmitt	cancel_work_sync(&adapter->ns_up_work);
426de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_destroy_adapter_work_queue(adapter);
427de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig
428de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_fc_wka_ports_force_offline(adapter->gs);
4291947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	zfcp_scsi_adapter_unregister(adapter);
430de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs);
431de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig
432de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_erp_thread_kill(adapter);
433ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig	zfcp_dbf_adapter_unregister(adapter);
434de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_qdio_destroy(adapter->qdio);
435de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig
436de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_ccw_adapter_put(adapter); /* final put to release */
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
439317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig/**
440f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig * zfcp_adapter_release - remove the adapter from the resource list
441f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig * @ref: pointer to struct kref
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks:	adapter list write lock is assumed to be held by caller
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
444f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schilligvoid zfcp_adapter_release(struct kref *ref)
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
446f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	struct zfcp_adapter *adapter = container_of(ref, struct zfcp_adapter,
447f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig						    ref);
448de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	struct ccw_device *cdev = adapter->ccw_device;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
450f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
451d5a282a1c5084ec7ebd9e6ab9723317f6b3fcd7bSwen Schillig	zfcp_fc_gs_destroy(adapter);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	zfcp_free_low_mem_buffers(adapter);
453317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	kfree(adapter->req_list);
454f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	kfree(adapter->fc_stats);
455f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	kfree(adapter->stats_reset_data);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter);
457de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	put_device(&cdev->dev);
458f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig}
459f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig
460f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schilligstatic void zfcp_port_release(struct device *dev)
46160221920706a01bef89af2577f9a90a8eeb4e662Swen Schillig{
462615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
463f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig
464de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_ccw_adapter_put(port->adapter);
465f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	kfree(port);
46660221920706a01bef89af2577f9a90a8eeb4e662Swen Schillig}
46760221920706a01bef89af2577f9a90a8eeb4e662Swen Schillig
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_port_enqueue - enqueue port to port list of adapter
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: adapter where remote port is added
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @wwpn: WWPN of the remote port to be enqueued
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @status: initial status for the port
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @d_id: destination id of the remote port to be enqueued
474317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * Returns: pointer to enqueued port on success, ERR_PTR on error
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All port internal structures are set up and the sysfs entry is generated.
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d_id is used to enqueue ports with a well known address like the Directory
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Service for nameserver lookup.
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4807ba58c9cc16d296290fe645acb11db2b01276544Swen Schilligstruct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
481317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig				     u32 status, u32 d_id)
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4833859f6a248cbdfbe7b41663f3a2b51f48e30b281Andreas Herrmann	struct zfcp_port *port;
484f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	int retval = -ENOMEM;
485f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig
486f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	kref_get(&adapter->ref);
4870fac3f477b6b520ae7d972ceb6e958e6807c8e1aChristof Schmitt
488ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	port = zfcp_get_port_by_wwpn(adapter, wwpn);
489ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	if (port) {
490615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt		put_device(&port->dev);
491f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		retval = -EEXIST;
492f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto err_out;
4930fac3f477b6b520ae7d972ceb6e958e6807c8e1aChristof Schmitt	}
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
495317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!port)
497f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto err_out;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
499ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	rwlock_init(&port->unit_list_lock);
500ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	INIT_LIST_HEAD(&port->unit_list);
501d99b601b63386f3395dc26a699ae703a273d9982Steffen Maier	atomic_set(&port->units, 0);
502ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig
503799b76d09aeee558d18c1f5b93e63f58f1d1fc11Christof Schmitt	INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
5048fdf30d5429605a4c30cc515c73e5eab140035deChristof Schmitt	INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
505a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	INIT_WORK(&port->rport_work, zfcp_scsi_rport_work);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port->adapter = adapter;
508317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	port->d_id = d_id;
509317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig	port->wwpn = wwpn;
510a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	port->rport_task = RPORT_NONE;
511615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	port->dev.parent = &adapter->ccw_device->dev;
51283d4e1c33d9329e6d53cf4ac0a02c98ac83eba05Sebastian Ott	port->dev.groups = zfcp_port_attr_groups;
513615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	port->dev.release = zfcp_port_release;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
515615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
5160fac3f477b6b520ae7d972ceb6e958e6807c8e1aChristof Schmitt		kfree(port);
517f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto err_out;
5180fac3f477b6b520ae7d972ceb6e958e6807c8e1aChristof Schmitt	}
519f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	retval = -EINVAL;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	if (device_register(&port->dev)) {
522615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt		put_device(&port->dev);
523f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		goto err_out;
524f4395b652636398eb4712e6f3caf79c9a6c02e21Sebastian Ott	}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
526ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	write_lock_irq(&adapter->port_list_lock);
527ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	list_add_tail(&port->list, &adapter->port_list);
528ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	write_unlock_irq(&adapter->port_list_lock);
529ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig
5306b183334c23969d52d4d9f775da554480d05ca4dSwen Schillig	atomic_set_mask(status | ZFCP_STATUS_COMMON_RUNNING, &port->status);
531317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return port;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
534f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schilligerr_out:
535de3dc57214a1466034ecc4d4ffb10331d34c09a3Swen Schillig	zfcp_ccw_adapter_put(adapter);
536f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	return ERR_PTR(retval);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
539317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig/**
540317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * zfcp_sg_free_table - free memory used by scatterlists
541317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * @sg: pointer to scatterlist
542317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * @count: number of scatterlist which are to be free'ed
543317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * the scatterlist are expected to reference pages always
544317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig */
54545633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmittvoid zfcp_sg_free_table(struct scatterlist *sg, int count)
54645633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt{
54745633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt	int i;
54845633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt
54945633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt	for (i = 0; i < count; i++, sg++)
55045633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt		if (sg)
55145633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt			free_page((unsigned long) sg_virt(sg));
55245633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt		else
55345633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt			break;
55445633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt}
55545633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt
556317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig/**
557317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * zfcp_sg_setup_table - init scatterlist and allocate, assign buffers
558317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * @sg: pointer to struct scatterlist
559317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * @count: number of scatterlists which should be assigned with buffers
560317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * of size page
561317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig *
562317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig * Returns: 0 on success, -ENOMEM otherwise
563317e6b6519b5a34263a33f150ed57ad468b26a64Swen Schillig */
56445633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmittint zfcp_sg_setup_table(struct scatterlist *sg, int count)
56545633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt{
56645633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt	void *addr;
56745633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt	int i;
56845633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt
56945633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt	sg_init_table(sg, count);
57045633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt	for (i = 0; i < count; i++, sg++) {
57145633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt		addr = (void *) get_zeroed_page(GFP_KERNEL);
57245633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt		if (!addr) {
57345633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt			zfcp_sg_free_table(sg, i);
57445633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt			return -ENOMEM;
57545633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt		}
57645633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt		sg_set_buf(sg, addr, PAGE_SIZE);
57745633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt	}
57845633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt	return 0;
57945633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt}
580