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