]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/s390/scsi/zfcp_ccw.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[mv-sheeva.git] / drivers / s390 / scsi / zfcp_ccw.c
index d9da5c42ccbe6ca617bf4f304f0f9ecb1c058ef2..0c90f8e71605882266cb644f1dd3fe9825e14ffd 100644 (file)
@@ -18,12 +18,15 @@ static int zfcp_ccw_suspend(struct ccw_device *cdev)
 {
        struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
 
-       down(&zfcp_data.config_sema);
+       if (!adapter)
+               return 0;
+
+       mutex_lock(&zfcp_data.config_mutex);
 
        zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL);
        zfcp_erp_wait(adapter);
 
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
 
        return 0;
 }
@@ -33,6 +36,9 @@ static int zfcp_ccw_activate(struct ccw_device *cdev)
 {
        struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
 
+       if (!adapter)
+               return 0;
+
        zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL,
                                       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -63,25 +69,14 @@ int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
  * zfcp_ccw_probe - probe function of zfcp driver
  * @ccw_device: pointer to belonging ccw device
  *
- * This function gets called by the common i/o layer and sets up the initial
- * data structures for each fcp adapter, which was detected by the system.
- * Also the sysfs files for this adapter will be created by this function.
- * In addition the nameserver port will be added to the ports of the adapter
- * and its sysfs representation will be created too.
+ * This function gets called by the common i/o layer for each FCP
+ * device found on the current system. This is only a stub to make cio
+ * work: To only allocate adapter resources for devices actually used,
+ * the allocation is deferred to the first call to ccw_set_online.
  */
 static int zfcp_ccw_probe(struct ccw_device *ccw_device)
 {
-       int retval = 0;
-
-       down(&zfcp_data.config_sema);
-       if (zfcp_adapter_enqueue(ccw_device)) {
-               dev_err(&ccw_device->dev,
-                       "Setting up data structures for the "
-                       "FCP adapter failed\n");
-               retval = -EINVAL;
-       }
-       up(&zfcp_data.config_sema);
-       return retval;
+       return 0;
 }
 
 /**
@@ -102,8 +97,11 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
        LIST_HEAD(port_remove_lh);
 
        ccw_device_set_offline(ccw_device);
-       down(&zfcp_data.config_sema);
+
+       mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&ccw_device->dev);
+       if (!adapter)
+               goto out;
 
        write_lock_irq(&zfcp_data.config_lock);
        list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
@@ -129,29 +127,41 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
        wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
        zfcp_adapter_dequeue(adapter);
 
-       up(&zfcp_data.config_sema);
+out:
+       mutex_unlock(&zfcp_data.config_mutex);
 }
 
 /**
  * zfcp_ccw_set_online - set_online function of zfcp driver
  * @ccw_device: pointer to belonging ccw device
  *
- * This function gets called by the common i/o layer and sets an adapter
- * into state online. Setting an fcp device online means that it will be
- * registered with the SCSI stack, that the QDIO queues will be set up
- * and that the adapter will be opened (asynchronously).
+ * This function gets called by the common i/o layer and sets an
+ * adapter into state online.  The first call will allocate all
+ * adapter resources that will be retained until the device is removed
+ * via zfcp_ccw_remove.
+ *
+ * Setting an fcp device online means that it will be registered with
+ * the SCSI stack, that the QDIO queues will be set up and that the
+ * adapter will be opened.
  */
 static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
 {
        struct zfcp_adapter *adapter;
-       int retval;
+       int ret = 0;
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&ccw_device->dev);
 
-       retval = zfcp_erp_thread_setup(adapter);
-       if (retval)
-               goto out;
+       if (!adapter) {
+               ret = zfcp_adapter_enqueue(ccw_device);
+               if (ret) {
+                       dev_err(&ccw_device->dev,
+                               "Setting up data structures for the "
+                               "FCP adapter failed\n");
+                       goto out;
+               }
+               adapter = dev_get_drvdata(&ccw_device->dev);
+       }
 
        /* initialize request counter */
        BUG_ON(!zfcp_reqlist_isempty(adapter));
@@ -162,13 +172,11 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
                                "ccsonl2", NULL);
        zfcp_erp_wait(adapter);
-       up(&zfcp_data.config_sema);
-       flush_work(&adapter->scan_work);
-       return 0;
-
- out:
-       up(&zfcp_data.config_sema);
-       return retval;
+out:
+       mutex_unlock(&zfcp_data.config_mutex);
+       if (!ret)
+               flush_work(&adapter->scan_work);
+       return ret;
 }
 
 /**
@@ -182,12 +190,15 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 {
        struct zfcp_adapter *adapter;
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&ccw_device->dev);
+       if (!adapter)
+               goto out;
+
        zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
        zfcp_erp_wait(adapter);
-       zfcp_erp_thread_kill(adapter);
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
+out:
        return 0;
 }
 
@@ -240,11 +251,12 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
 {
        struct zfcp_adapter *adapter;
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&cdev->dev);
        zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
        zfcp_erp_wait(adapter);
-       up(&zfcp_data.config_sema);
+       zfcp_erp_thread_kill(adapter);
+       mutex_unlock(&zfcp_data.config_mutex);
 }
 
 static struct ccw_driver zfcp_ccw_driver = {