linux/drivers/s390/scsi/zfcp_ccw.c
<<
>>
Prefs
   1/*
   2 * zfcp device driver
   3 *
   4 * Registration and callback for the s390 common I/O layer.
   5 *
   6 * Copyright IBM Corporation 2002, 2009
   7 */
   8
   9#define KMSG_COMPONENT "zfcp"
  10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  11
  12#include "zfcp_ext.h"
  13
  14/**
  15 * zfcp_ccw_probe - probe function of zfcp driver
  16 * @ccw_device: pointer to belonging ccw device
  17 *
  18 * This function gets called by the common i/o layer and sets up the initial
  19 * data structures for each fcp adapter, which was detected by the system.
  20 * Also the sysfs files for this adapter will be created by this function.
  21 * In addition the nameserver port will be added to the ports of the adapter
  22 * and its sysfs representation will be created too.
  23 */
  24static int zfcp_ccw_probe(struct ccw_device *ccw_device)
  25{
  26        int retval = 0;
  27
  28        down(&zfcp_data.config_sema);
  29        if (zfcp_adapter_enqueue(ccw_device)) {
  30                dev_err(&ccw_device->dev,
  31                        "Setting up data structures for the "
  32                        "FCP adapter failed\n");
  33                retval = -EINVAL;
  34        }
  35        up(&zfcp_data.config_sema);
  36        return retval;
  37}
  38
  39/**
  40 * zfcp_ccw_remove - remove function of zfcp driver
  41 * @ccw_device: pointer to belonging ccw device
  42 *
  43 * This function gets called by the common i/o layer and removes an adapter
  44 * from the system. Task of this function is to get rid of all units and
  45 * ports that belong to this adapter. And in addition all resources of this
  46 * adapter will be freed too.
  47 */
  48static void zfcp_ccw_remove(struct ccw_device *ccw_device)
  49{
  50        struct zfcp_adapter *adapter;
  51        struct zfcp_port *port, *p;
  52        struct zfcp_unit *unit, *u;
  53        LIST_HEAD(unit_remove_lh);
  54        LIST_HEAD(port_remove_lh);
  55
  56        ccw_device_set_offline(ccw_device);
  57        down(&zfcp_data.config_sema);
  58        adapter = dev_get_drvdata(&ccw_device->dev);
  59
  60        write_lock_irq(&zfcp_data.config_lock);
  61        list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
  62                list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
  63                        list_move(&unit->list, &unit_remove_lh);
  64                        atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
  65                                        &unit->status);
  66                }
  67                list_move(&port->list, &port_remove_lh);
  68                atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
  69        }
  70        atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
  71        write_unlock_irq(&zfcp_data.config_lock);
  72
  73        list_for_each_entry_safe(port, p, &port_remove_lh, list) {
  74                list_for_each_entry_safe(unit, u, &unit_remove_lh, list) {
  75                        if (unit->device)
  76                                scsi_remove_device(unit->device);
  77                        zfcp_unit_dequeue(unit);
  78                }
  79                zfcp_port_dequeue(port);
  80        }
  81        wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
  82        zfcp_adapter_dequeue(adapter);
  83
  84        up(&zfcp_data.config_sema);
  85}
  86
  87/**
  88 * zfcp_ccw_set_online - set_online function of zfcp driver
  89 * @ccw_device: pointer to belonging ccw device
  90 *
  91 * This function gets called by the common i/o layer and sets an adapter
  92 * into state online. Setting an fcp device online means that it will be
  93 * registered with the SCSI stack, that the QDIO queues will be set up
  94 * and that the adapter will be opened (asynchronously).
  95 */
  96static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
  97{
  98        struct zfcp_adapter *adapter;
  99        int retval;
 100
 101        down(&zfcp_data.config_sema);
 102        adapter = dev_get_drvdata(&ccw_device->dev);
 103
 104        retval = zfcp_erp_thread_setup(adapter);
 105        if (retval)
 106                goto out;
 107
 108        /* initialize request counter */
 109        BUG_ON(!zfcp_reqlist_isempty(adapter));
 110        adapter->req_no = 0;
 111
 112        zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
 113                                       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
 114        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 115                                "ccsonl2", NULL);
 116        zfcp_erp_wait(adapter);
 117        up(&zfcp_data.config_sema);
 118        flush_work(&adapter->scan_work);
 119        return 0;
 120
 121 out:
 122        up(&zfcp_data.config_sema);
 123        return retval;
 124}
 125
 126/**
 127 * zfcp_ccw_set_offline - set_offline function of zfcp driver
 128 * @ccw_device: pointer to belonging ccw device
 129 *
 130 * This function gets called by the common i/o layer and sets an adapter
 131 * into state offline.
 132 */
 133static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 134{
 135        struct zfcp_adapter *adapter;
 136
 137        down(&zfcp_data.config_sema);
 138        adapter = dev_get_drvdata(&ccw_device->dev);
 139        zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
 140        zfcp_erp_wait(adapter);
 141        zfcp_erp_thread_kill(adapter);
 142        up(&zfcp_data.config_sema);
 143        return 0;
 144}
 145
 146/**
 147 * zfcp_ccw_notify - ccw notify function
 148 * @ccw_device: pointer to belonging ccw device
 149 * @event: indicates if adapter was detached or attached
 150 *
 151 * This function gets called by the common i/o layer if an adapter has gone
 152 * or reappeared.
 153 */
 154static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
 155{
 156        struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev);
 157
 158        switch (event) {
 159        case CIO_GONE:
 160                dev_warn(&adapter->ccw_device->dev,
 161                         "The FCP device has been detached\n");
 162                zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL);
 163                break;
 164        case CIO_NO_PATH:
 165                dev_warn(&adapter->ccw_device->dev,
 166                         "The CHPID for the FCP device is offline\n");
 167                zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL);
 168                break;
 169        case CIO_OPER:
 170                dev_info(&adapter->ccw_device->dev,
 171                         "The FCP device is operational again\n");
 172                zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
 173                                               ZFCP_STATUS_COMMON_RUNNING,
 174                                               ZFCP_SET);
 175                zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 176                                        "ccnoti4", NULL);
 177                break;
 178        case CIO_BOXED:
 179                dev_warn(&adapter->ccw_device->dev,
 180                         "The ccw device did not respond in time.\n");
 181                zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL);
 182                break;
 183        }
 184        return 1;
 185}
 186
 187/**
 188 * zfcp_ccw_shutdown - handle shutdown from cio
 189 * @cdev: device for adapter to shutdown.
 190 */
 191static void zfcp_ccw_shutdown(struct ccw_device *cdev)
 192{
 193        struct zfcp_adapter *adapter;
 194
 195        down(&zfcp_data.config_sema);
 196        adapter = dev_get_drvdata(&cdev->dev);
 197        zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
 198        zfcp_erp_wait(adapter);
 199        up(&zfcp_data.config_sema);
 200}
 201
 202static struct ccw_device_id zfcp_ccw_device_id[] = {
 203        { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x3) },
 204        { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x4) }, /* priv. */
 205        {},
 206};
 207
 208MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
 209
 210static struct ccw_driver zfcp_ccw_driver = {
 211        .owner       = THIS_MODULE,
 212        .name        = "zfcp",
 213        .ids         = zfcp_ccw_device_id,
 214        .probe       = zfcp_ccw_probe,
 215        .remove      = zfcp_ccw_remove,
 216        .set_online  = zfcp_ccw_set_online,
 217        .set_offline = zfcp_ccw_set_offline,
 218        .notify      = zfcp_ccw_notify,
 219        .shutdown    = zfcp_ccw_shutdown,
 220};
 221
 222/**
 223 * zfcp_ccw_register - ccw register function
 224 *
 225 * Registers the driver at the common i/o layer. This function will be called
 226 * at module load time/system start.
 227 */
 228int __init zfcp_ccw_register(void)
 229{
 230        return ccw_driver_register(&zfcp_ccw_driver);
 231}
 232
 233/**
 234 * zfcp_get_adapter_by_busid - find zfcp_adapter struct
 235 * @busid: bus id string of zfcp adapter to find
 236 */
 237struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid)
 238{
 239        struct ccw_device *ccw_device;
 240        struct zfcp_adapter *adapter = NULL;
 241
 242        ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
 243        if (ccw_device) {
 244                adapter = dev_get_drvdata(&ccw_device->dev);
 245                put_device(&ccw_device->dev);
 246        }
 247        return adapter;
 248}
 249