fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / s390 / scsi / zfcp_ccw.c
index c509c13..81680ef 100644 (file)
@@ -1,15 +1,8 @@
 /*
- * linux/drivers/s390/scsi/zfcp_ccw.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * FCP adapter driver for IBM eServer zSeries
- *
- * CCW driver related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- *      Martin Peschke <mpeschke@de.ibm.com>
- *     Heiko Carstens <heiko.carstens@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_CCW_C_REVISION "$Revision: 1.52 $"
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <asm/ccwdev.h>
 #include "zfcp_ext.h"
-#include "zfcp_def.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
 
@@ -41,6 +28,7 @@ static void zfcp_ccw_remove(struct ccw_device *);
 static int zfcp_ccw_set_online(struct ccw_device *);
 static int zfcp_ccw_set_offline(struct ccw_device *);
 static int zfcp_ccw_notify(struct ccw_device *, int);
+static void zfcp_ccw_shutdown(struct device *);
 
 static struct ccw_device_id zfcp_ccw_device_id[] = {
        {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE,
@@ -63,6 +51,9 @@ static struct ccw_driver zfcp_ccw_driver = {
        .set_online  = zfcp_ccw_set_online,
        .set_offline = zfcp_ccw_set_offline,
        .notify      = zfcp_ccw_notify,
+       .driver      = {
+               .shutdown = zfcp_ccw_shutdown,
+       },
 };
 
 MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
@@ -173,6 +164,11 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
        retval = zfcp_adapter_scsi_register(adapter);
        if (retval)
                goto out_scsi_register;
+
+       /* initialize request counter */
+       BUG_ON(!zfcp_reqlist_isempty(adapter));
+       adapter->req_no = 0;
+
        zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
                                       ZFCP_SET);
        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
@@ -232,14 +228,19 @@ zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
        case CIO_GONE:
                ZFCP_LOG_NORMAL("adapter %s: device gone\n",
                                zfcp_get_busid_by_adapter(adapter));
+               debug_text_event(adapter->erp_dbf,1,"dev_gone");
+               zfcp_erp_adapter_shutdown(adapter, 0);
                break;
        case CIO_NO_PATH:
                ZFCP_LOG_NORMAL("adapter %s: no path\n",
                                zfcp_get_busid_by_adapter(adapter));
+               debug_text_event(adapter->erp_dbf,1,"no_path");
+               zfcp_erp_adapter_shutdown(adapter, 0);
                break;
        case CIO_OPER:
                ZFCP_LOG_NORMAL("adapter %s: operational again\n",
                                zfcp_get_busid_by_adapter(adapter));
+               debug_text_event(adapter->erp_dbf,1,"dev_oper");
                zfcp_erp_modify_adapter_status(adapter,
                                               ZFCP_STATUS_COMMON_RUNNING,
                                               ZFCP_SET);
@@ -247,6 +248,7 @@ zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
                                        ZFCP_STATUS_COMMON_ERP_FAILED);
                break;
        }
+       zfcp_erp_wait(adapter);
        up(&zfcp_data.config_sema);
        return 1;
 }
@@ -273,16 +275,20 @@ zfcp_ccw_register(void)
 }
 
 /**
- * zfcp_ccw_unregister - ccw unregister function
+ * zfcp_ccw_shutdown - gets called on reboot/shutdown
  *
- * Unregisters the driver from common i/o layer. Function will be called at
- * module unload/system shutdown.
+ * Makes sure that QDIO queues are down when the system gets stopped.
  */
-void __exit
-zfcp_ccw_unregister(void)
+static void
+zfcp_ccw_shutdown(struct device *dev)
 {
-       zfcp_sysfs_driver_remove_files(&zfcp_ccw_driver.driver);
-       ccw_driver_unregister(&zfcp_ccw_driver);
+       struct zfcp_adapter *adapter;
+
+       down(&zfcp_data.config_sema);
+       adapter = dev_get_drvdata(dev);
+       zfcp_erp_adapter_shutdown(adapter, 0);
+       zfcp_erp_wait(adapter);
+       up(&zfcp_data.config_sema);
 }
 
 #undef ZFCP_LOG_AREA