diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_erp.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 155 |
1 files changed, 60 insertions, 95 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index c75d6f35cb5..73d366ba31e 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -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(¤t->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); |