]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/s390/scsi/zfcp_erp.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[mv-sheeva.git] / drivers / s390 / scsi / zfcp_erp.c
index c75d6f35cb5f64d05e88ac8b423d7cb03e2977e6..73d366ba31e593755d2854d4591888b9e949bba9 100644 (file)
@@ -9,6 +9,7 @@
 #define KMSG_COMPONENT "zfcp"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kthread.h>
 #include "zfcp_ext.h"
 
 #define ZFCP_MAX_ERPS                   3
@@ -26,7 +27,6 @@ enum zfcp_erp_steps {
        ZFCP_ERP_STEP_FSF_XCONFIG       = 0x0001,
        ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
        ZFCP_ERP_STEP_PORT_CLOSING      = 0x0100,
-       ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400,
        ZFCP_ERP_STEP_PORT_OPENING      = 0x0800,
        ZFCP_ERP_STEP_UNIT_CLOSING      = 0x1000,
        ZFCP_ERP_STEP_UNIT_OPENING      = 0x2000,
@@ -75,9 +75,9 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
        struct zfcp_adapter *adapter = act->adapter;
 
        list_move(&act->list, &act->adapter->erp_ready_head);
-       zfcp_rec_dbf_event_action("erardy1", act);
-       up(&adapter->erp_ready_sem);
-       zfcp_rec_dbf_event_thread("erardy2", adapter);
+       zfcp_dbf_rec_action("erardy1", act);
+       wake_up(&adapter->erp_ready_wq);
+       zfcp_dbf_rec_thread("erardy2", adapter->dbf);
 }
 
 static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
@@ -150,6 +150,9 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
                a_status = atomic_read(&adapter->status);
                if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE)
                        return 0;
+               if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) &&
+                   !(a_status & ZFCP_STATUS_COMMON_OPEN))
+                       return 0; /* shutdown requested for closed adapter */
        }
 
        return need;
@@ -213,8 +216,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
        int retval = 1, need;
        struct zfcp_erp_action *act = NULL;
 
-       if (!(atomic_read(&adapter->status) &
-             ZFCP_STATUS_ADAPTER_ERP_THREAD_UP))
+       if (!adapter->erp_thread)
                return -EIO;
 
        need = zfcp_erp_required_act(want, adapter, port, unit);
@@ -227,12 +229,11 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
                goto out;
        ++adapter->erp_total_count;
        list_add_tail(&act->list, &adapter->erp_ready_head);
-       up(&adapter->erp_ready_sem);
-       zfcp_rec_dbf_event_thread("eracte1", adapter);
+       wake_up(&adapter->erp_ready_wq);
+       zfcp_dbf_rec_thread("eracte1", adapter->dbf);
        retval = 0;
  out:
-       zfcp_rec_dbf_event_trigger(id, ref, want, need, act,
-                                  adapter, port, unit);
+       zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit);
        return retval;
 }
 
@@ -443,28 +444,28 @@ static int status_change_clear(unsigned long mask, atomic_t *status)
 static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 {
        if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
-               zfcp_rec_dbf_event_adapter("eraubl1", NULL, adapter);
+               zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf);
        atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
 }
 
 static void zfcp_erp_port_unblock(struct zfcp_port *port)
 {
        if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
-               zfcp_rec_dbf_event_port("erpubl1", NULL, port);
+               zfcp_dbf_rec_port("erpubl1", NULL, port);
        atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
 }
 
 static void zfcp_erp_unit_unblock(struct zfcp_unit *unit)
 {
        if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))
-               zfcp_rec_dbf_event_unit("eruubl1", NULL, unit);
+               zfcp_dbf_rec_unit("eruubl1", NULL, unit);
        atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
 }
 
 static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
 {
        list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
-       zfcp_rec_dbf_event_action("erator1", erp_action);
+       zfcp_dbf_rec_action("erator1", erp_action);
 }
 
 static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
@@ -480,13 +481,12 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
                if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
                                   ZFCP_STATUS_ERP_TIMEDOUT)) {
                        act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
-                       zfcp_rec_dbf_event_action("erscf_1", act);
+                       zfcp_dbf_rec_action("erscf_1", act);
                        act->fsf_req->erp_action = NULL;
                }
                if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
-                       zfcp_rec_dbf_event_action("erscf_2", act);
-               if (act->fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED |
-                                           ZFCP_STATUS_FSFREQ_DISMISSED))
+                       zfcp_dbf_rec_action("erscf_2", act);
+               if (act->fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
                        act->fsf_req = NULL;
        } else
                act->fsf_req = NULL;
@@ -604,9 +604,11 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
 
 static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
 {
-       if (zfcp_qdio_open(act->adapter))
+       struct zfcp_qdio *qdio = act->adapter->qdio;
+
+       if (zfcp_qdio_open(qdio))
                return ZFCP_ERP_FAILED;
-       init_waitqueue_head(&act->adapter->request_wq);
+       init_waitqueue_head(&qdio->req_q_wq);
        atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status);
        return ZFCP_ERP_SUCCEEDED;
 }
@@ -641,9 +643,10 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action)
                        return ZFCP_ERP_FAILED;
                }
 
-               zfcp_rec_dbf_event_thread_lock("erasfx1", adapter);
-               down(&adapter->erp_ready_sem);
-               zfcp_rec_dbf_event_thread_lock("erasfx2", adapter);
+               zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf);
+               wait_event(adapter->erp_ready_wq,
+                          !list_empty(&adapter->erp_ready_head));
+               zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf);
                if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
                        break;
 
@@ -682,9 +685,10 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
        if (ret)
                return ZFCP_ERP_FAILED;
 
-       zfcp_rec_dbf_event_thread_lock("erasox1", adapter);
-       down(&adapter->erp_ready_sem);
-       zfcp_rec_dbf_event_thread_lock("erasox2", adapter);
+       zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf);
+       wait_event(adapter->erp_ready_wq,
+                  !list_empty(&adapter->erp_ready_head));
+       zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf);
        if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
                return ZFCP_ERP_FAILED;
 
@@ -711,10 +715,10 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
        struct zfcp_adapter *adapter = act->adapter;
 
        /* close queues to ensure that buffers are not accessed by adapter */
-       zfcp_qdio_close(adapter);
+       zfcp_qdio_close(adapter->qdio);
        zfcp_fsf_req_dismiss_all(adapter);
        adapter->fsf_req_seq_no = 0;
-       zfcp_fc_wka_port_force_offline(&adapter->gs->ds);
+       zfcp_fc_wka_ports_force_offline(adapter->gs);
        /* all ports and units are closed */
        zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
                                       ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
@@ -841,27 +845,6 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
        return zfcp_erp_port_strategy_open_port(act);
 }
 
-void zfcp_erp_port_strategy_open_lookup(struct work_struct *work)
-{
-       int retval;
-       struct zfcp_port *port = container_of(work, struct zfcp_port,
-                                             gid_pn_work);
-
-       retval = zfcp_fc_ns_gid_pn(&port->erp_action);
-       if (!retval) {
-               port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
-               goto out;
-       }
-       if (retval == -ENOMEM) {
-               zfcp_erp_notify(&port->erp_action, ZFCP_STATUS_ERP_LOWMEM);
-               goto out;
-       }
-       /* all other error condtions */
-       zfcp_erp_notify(&port->erp_action, 0);
-out:
-       zfcp_port_put(port);
-}
-
 static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
 {
        struct zfcp_adapter *adapter = act->adapter;
@@ -876,15 +859,11 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
                        return zfcp_erp_open_ptp_port(act);
                if (!port->d_id) {
                        zfcp_port_get(port);
-                       if (!queue_work(zfcp_data.work_queue,
+                       if (!queue_work(adapter->work_queue,
                                        &port->gid_pn_work))
                                zfcp_port_put(port);
-                       return ZFCP_ERP_CONTINUES;
+                       return ZFCP_ERP_EXIT;
                }
-               /* fall through */
-       case ZFCP_ERP_STEP_NAMESERVER_LOOKUP:
-               if (!port->d_id)
-                       return ZFCP_ERP_FAILED;
                return zfcp_erp_port_strategy_open_port(act);
 
        case ZFCP_ERP_STEP_PORT_OPENING:
@@ -1163,7 +1142,7 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
        }
 
        list_del(&erp_action->list);
-       zfcp_rec_dbf_event_action("eractd1", erp_action);
+       zfcp_dbf_rec_action("eractd1", erp_action);
 
        switch (erp_action->action) {
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
@@ -1311,20 +1290,16 @@ static int zfcp_erp_thread(void *data)
        struct list_head *next;
        struct zfcp_erp_action *act;
        unsigned long flags;
-       int ignore;
-
-       daemonize("zfcperp%s", dev_name(&adapter->ccw_device->dev));
-       /* Block all signals */
-       siginitsetinv(&current->blocked, 0);
-       atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
-       wake_up(&adapter->erp_thread_wqh);
 
-       while (!(atomic_read(&adapter->status) &
-                ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) {
+       for (;;) {
+               zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf);
+               wait_event_interruptible(adapter->erp_ready_wq,
+                          !list_empty(&adapter->erp_ready_head) ||
+                          kthread_should_stop());
+               zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf);
 
-               zfcp_rec_dbf_event_thread_lock("erthrd1", adapter);
-               ignore = down_interruptible(&adapter->erp_ready_sem);
-               zfcp_rec_dbf_event_thread_lock("erthrd2", adapter);
+               if (kthread_should_stop())
+                       break;
 
                write_lock_irqsave(&adapter->erp_lock, flags);
                next = adapter->erp_ready_head.next;
@@ -1339,9 +1314,6 @@ static int zfcp_erp_thread(void *data)
                }
        }
 
-       atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
-       wake_up(&adapter->erp_thread_wqh);
-
        return 0;
 }
 
@@ -1353,18 +1325,17 @@ static int zfcp_erp_thread(void *data)
  */
 int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
 {
-       int retval;
+       struct task_struct *thread;
 
-       atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
-       retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
-       if (retval < 0) {
+       thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s",
+                            dev_name(&adapter->ccw_device->dev));
+       if (IS_ERR(thread)) {
                dev_err(&adapter->ccw_device->dev,
                        "Creating an ERP thread for the FCP device failed.\n");
-               return retval;
+               return PTR_ERR(thread);
        }
-       wait_event(adapter->erp_thread_wqh,
-                  atomic_read(&adapter->status) &
-                       ZFCP_STATUS_ADAPTER_ERP_THREAD_UP);
+
+       adapter->erp_thread = thread;
        return 0;
 }
 
@@ -1379,16 +1350,10 @@ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
  */
 void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
 {
-       atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
-       up(&adapter->erp_ready_sem);
-       zfcp_rec_dbf_event_thread_lock("erthrk1", adapter);
-
-       wait_event(adapter->erp_thread_wqh,
-                  !(atomic_read(&adapter->status) &
-                               ZFCP_STATUS_ADAPTER_ERP_THREAD_UP));
-
-       atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
-                         &adapter->status);
+       kthread_stop(adapter->erp_thread);
+       adapter->erp_thread = NULL;
+       WARN_ON(!list_empty(&adapter->erp_ready_head));
+       WARN_ON(!list_empty(&adapter->erp_running_head));
 }
 
 /**
@@ -1456,11 +1421,11 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
 
        if (set_or_clear == ZFCP_SET) {
                if (status_change_set(mask, &adapter->status))
-                       zfcp_rec_dbf_event_adapter(id, ref, adapter);
+                       zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
                atomic_set_mask(mask, &adapter->status);
        } else {
                if (status_change_clear(mask, &adapter->status))
-                       zfcp_rec_dbf_event_adapter(id, ref, adapter);
+                       zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
                atomic_clear_mask(mask, &adapter->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
                        atomic_set(&adapter->erp_counter, 0);
@@ -1490,11 +1455,11 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
 
        if (set_or_clear == ZFCP_SET) {
                if (status_change_set(mask, &port->status))
-                       zfcp_rec_dbf_event_port(id, ref, port);
+                       zfcp_dbf_rec_port(id, ref, port);
                atomic_set_mask(mask, &port->status);
        } else {
                if (status_change_clear(mask, &port->status))
-                       zfcp_rec_dbf_event_port(id, ref, port);
+                       zfcp_dbf_rec_port(id, ref, port);
                atomic_clear_mask(mask, &port->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
                        atomic_set(&port->erp_counter, 0);
@@ -1519,11 +1484,11 @@ void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
 {
        if (set_or_clear == ZFCP_SET) {
                if (status_change_set(mask, &unit->status))
-                       zfcp_rec_dbf_event_unit(id, ref, unit);
+                       zfcp_dbf_rec_unit(id, ref, unit);
                atomic_set_mask(mask, &unit->status);
        } else {
                if (status_change_clear(mask, &unit->status))
-                       zfcp_rec_dbf_event_unit(id, ref, unit);
+                       zfcp_dbf_rec_unit(id, ref, unit);
                atomic_clear_mask(mask, &unit->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
                        atomic_set(&unit->erp_counter, 0);