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#define ZFCP_MODEL_PRIV 0x4
  15
  16static int zfcp_ccw_suspend(struct ccw_device *cdev)
  17
  18{
  19        struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
  20
  21        if (!adapter)
  22                return 0;
  23
  24        mutex_lock(&zfcp_data.config_mutex);
  25
  26        zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL);
  27        zfcp_erp_wait(adapter);
  28
  29        mutex_unlock(&zfcp_data.config_mutex);
  30
  31        return 0;
  32}
  33
  34static int zfcp_ccw_activate(struct ccw_device *cdev)
  35
  36{
  37        struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
  38
  39        if (!adapter)
  40                return 0;
  41
  42        zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL,
  43                                       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
  44        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
  45                                "ccresu2", NULL);
  46        zfcp_erp_wait(adapter);
  47        flush_work(&adapter->scan_work);
  48
  49        return 0;
  50}
  51
  52static struct ccw_device_id zfcp_ccw_device_id[] = {
  53        { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x3) },
  54        { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, ZFCP_MODEL_PRIV) },
  55        {},
  56};
  57MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
  58
  59/**
  60 * zfcp_ccw_priv_sch - check if subchannel is privileged
  61 * @adapter: Adapter/Subchannel to check
  62 */
  63int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
  64{
  65        return adapter->ccw_device->id.dev_model == ZFCP_MODEL_PRIV;
  66}
  67
  68/**
  69 * zfcp_ccw_probe - probe function of zfcp driver
  70 * @ccw_device: pointer to belonging ccw device
  71 *
  72 * This function gets called by the common i/o layer for each FCP
  73 * device found on the current system. This is only a stub to make cio
  74 * work: To only allocate adapter resources for devices actually used,
  75 * the allocation is deferred to the first call to ccw_set_online.
  76 */
  77static int zfcp_ccw_probe(struct ccw_device *ccw_device)
  78{
  79        return 0;
  80}
  81
  82/**
  83 * zfcp_ccw_remove - remove function of zfcp driver
  84 * @ccw_device: pointer to belonging ccw device
  85 *
  86 * This function gets called by the common i/o layer and removes an adapter
  87 * from the system. Task of this function is to get rid of all units and
  88 * ports that belong to this adapter. And in addition all resources of this
  89 * adapter will be freed too.
  90 */
  91static void zfcp_ccw_remove(struct ccw_device *ccw_device)
  92{
  93        struct zfcp_adapter *adapter;
  94        struct zfcp_port *port, *p;
  95        struct zfcp_unit *unit, *u;
  96        LIST_HEAD(unit_remove_lh);
  97        LIST_HEAD(port_remove_lh);
  98
  99        ccw_device_set_offline(ccw_device);
 100
 101        mutex_lock(&zfcp_data.config_mutex);
 102        adapter = dev_get_drvdata(&ccw_device->dev);
 103        if (!adapter)
 104                goto out;
 105        mutex_unlock(&zfcp_data.config_mutex);
 106
 107        cancel_work_sync(&adapter->scan_work);
 108
 109        mutex_lock(&zfcp_data.config_mutex);
 110
 111        /* this also removes the scsi devices, so call it first */
 112        zfcp_adapter_scsi_unregister(adapter);
 113
 114        write_lock_irq(&zfcp_data.config_lock);
 115        list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
 116                list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
 117                        list_move(&unit->list, &unit_remove_lh);
 118                        atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
 119                                        &unit->status);
 120                }
 121                list_move(&port->list, &port_remove_lh);
 122                atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
 123        }
 124        atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
 125        write_unlock_irq(&zfcp_data.config_lock);
 126
 127        list_for_each_entry_safe(port, p, &port_remove_lh, list) {
 128                list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
 129                        zfcp_unit_dequeue(unit);
 130                zfcp_port_dequeue(port);
 131        }
 132        wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
 133        zfcp_adapter_dequeue(adapter);
 134
 135out:
 136        mutex_unlock(&zfcp_data.config_mutex);
 137}
 138
 139/**
 140 * zfcp_ccw_set_online - set_online function of zfcp driver
 141 * @ccw_device: pointer to belonging ccw device
 142 *
 143 * This function gets called by the common i/o layer and sets an
 144 * adapter into state online.  The first call will allocate all
 145 * adapter resources that will be retained until the device is removed
 146 * via zfcp_ccw_remove.
 147 *
 148 * Setting an fcp device online means that it will be registered with
 149 * the SCSI stack, that the QDIO queues will be set up and that the
 150 * adapter will be opened.
 151 */
 152static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
 153{
 154        struct zfcp_adapter *adapter;
 155        int ret = 0;
 156
 157        mutex_lock(&zfcp_data.config_mutex);
 158        adapter = dev_get_drvdata(&ccw_device->dev);
 159
 160        if (!adapter) {
 161                ret = zfcp_adapter_enqueue(ccw_device);
 162                if (ret) {
 163                        dev_err(&ccw_device->dev,
 164                                "Setting up data structures for the "
 165                                "FCP adapter failed\n");
 166                        goto out;
 167                }
 168                adapter = dev_get_drvdata(&ccw_device->dev);
 169        }
 170
 171        /* initialize request counter */
 172        BUG_ON(!zfcp_reqlist_isempty(adapter));
 173        adapter->req_no = 0;
 174
 175        zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
 176                                       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
 177        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 178                                "ccsonl2", NULL);
 179        zfcp_erp_wait(adapter);
 180out:
 181        mutex_unlock(&zfcp_data.config_mutex);
 182        if (!ret)
 183                flush_work(&adapter->scan_work);
 184        return ret;
 185}
 186
 187/**
 188 * zfcp_ccw_set_offline - set_offline function of zfcp driver
 189 * @ccw_device: pointer to belonging ccw device
 190 *
 191 * This function gets called by the common i/o layer and sets an adapter
 192 * into state offline.
 193 */
 194static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 195{
 196        struct zfcp_adapter *adapter;
 197
 198        mutex_lock(&zfcp_data.config_mutex);
 199        adapter = dev_get_drvdata(&ccw_device->dev);
 200        zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
 201        zfcp_erp_wait(adapter);
 202        mutex_unlock(&zfcp_data.config_mutex);
 203        return 0;
 204}
 205
 206/**
 207 * zfcp_ccw_notify - ccw notify function
 208 * @ccw_device: pointer to belonging ccw device
 209 * @event: indicates if adapter was detached or attached
 210 *
 211 * This function gets called by the common i/o layer if an adapter has gone
 212 * or reappeared.
 213 */
 214static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
 215{
 216        struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev);
 217
 218        switch (event) {
 219        case CIO_GONE:
 220                dev_warn(&adapter->ccw_device->dev,
 221                         "The FCP device has been detached\n");
 222                zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL);
 223                break;
 224        case CIO_NO_PATH:
 225                dev_warn(&adapter->ccw_device->dev,
 226                         "The CHPID for the FCP device is offline\n");
 227                zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL);
 228                break;
 229        case CIO_OPER:
 230                dev_info(&adapter->ccw_device->dev,
 231                         "The FCP device is operational again\n");
 232                zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
 233                                               ZFCP_STATUS_COMMON_RUNNING,
 234                                               ZFCP_SET);
 235                zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 236                                        "ccnoti4", NULL);
 237                break;
 238        case CIO_BOXED:
 239                dev_warn(&adapter->ccw_device->dev, "The FCP device "
 240                         "did not respond within the specified time\n");
 241                zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL);
 242                break;
 243        }
 244        return 1;
 245}
 246
 247/**
 248 * zfcp_ccw_shutdown - handle shutdown from cio
 249 * @cdev: device for adapter to shutdown.
 250 */
 251static void zfcp_ccw_shutdown(struct ccw_device *cdev)
 252{
 253        struct zfcp_adapter *adapter;
 254
 255        mutex_lock(&zfcp_data.config_mutex);
 256        adapter = dev_get_drvdata(&cdev->dev);
 257        if (!adapter)
 258                goto out;
 259
 260        zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
 261        zfcp_erp_wait(adapter);
 262        zfcp_erp_thread_kill(adapter);
 263out:
 264        mutex_unlock(&zfcp_data.config_mutex);
 265}
 266
 267struct ccw_driver zfcp_ccw_driver = {
 268        .owner       = THIS_MODULE,
 269        .name        = "zfcp",
 270        .ids         = zfcp_ccw_device_id,
 271        .probe       = zfcp_ccw_probe,
 272        .remove      = zfcp_ccw_remove,
 273        .set_online  = zfcp_ccw_set_online,
 274        .set_offline = zfcp_ccw_set_offline,
 275        .notify      = zfcp_ccw_notify,
 276        .shutdown    = zfcp_ccw_shutdown,
 277        .freeze      = zfcp_ccw_suspend,
 278        .thaw        = zfcp_ccw_activate,
 279        .restore     = zfcp_ccw_activate,
 280};
 281
 282/**
 283 * zfcp_ccw_register - ccw register function
 284 *
 285 * Registers the driver at the common i/o layer. This function will be called
 286 * at module load time/system start.
 287 */
 288int __init zfcp_ccw_register(void)
 289{
 290        return ccw_driver_register(&zfcp_ccw_driver);
 291}
 292