diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_erp.c')
| -rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 787 |
1 files changed, 370 insertions, 417 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index e3dbeda9717..c82fe65c412 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3,7 +3,7 @@ * * Error Recovery Procedures (ERP). * - * Copyright IBM Corporation 2002, 2010 + * Copyright IBM Corp. 2002, 2010 */ #define KMSG_COMPONENT "zfcp" @@ -21,6 +21,7 @@ enum zfcp_erp_act_flags { ZFCP_STATUS_ERP_DISMISSING = 0x00100000, ZFCP_STATUS_ERP_DISMISSED = 0x00200000, ZFCP_STATUS_ERP_LOWMEM = 0x00400000, + ZFCP_STATUS_ERP_NO_REF = 0x00800000, }; enum zfcp_erp_steps { @@ -29,12 +30,12 @@ enum zfcp_erp_steps { ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, ZFCP_ERP_STEP_PORT_OPENING = 0x0800, - ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, - ZFCP_ERP_STEP_UNIT_OPENING = 0x2000, + ZFCP_ERP_STEP_LUN_CLOSING = 0x1000, + ZFCP_ERP_STEP_LUN_OPENING = 0x2000, }; enum zfcp_erp_act_type { - ZFCP_ERP_ACTION_REOPEN_UNIT = 1, + ZFCP_ERP_ACTION_REOPEN_LUN = 1, ZFCP_ERP_ACTION_REOPEN_PORT = 2, ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, @@ -56,9 +57,8 @@ enum zfcp_erp_act_result { static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) { - zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL, - ZFCP_STATUS_COMMON_UNBLOCKED | mask, - ZFCP_CLEAR); + zfcp_erp_clear_adapter_status(adapter, + ZFCP_STATUS_COMMON_UNBLOCKED | mask); } static int zfcp_erp_action_exists(struct zfcp_erp_action *act) @@ -76,9 +76,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_dbf_rec_action("erardy1", act); + zfcp_dbf_rec_run("erardy1", act); wake_up(&adapter->erp_ready_wq); - zfcp_dbf_rec_thread("erardy2", adapter->dbf); + zfcp_dbf_rec_run("erardy2", act); } static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) @@ -88,23 +88,26 @@ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) zfcp_erp_action_ready(act); } -static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) +static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev) { - if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE) - zfcp_erp_action_dismiss(&unit->erp_action); + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + + if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_INUSE) + zfcp_erp_action_dismiss(&zfcp_sdev->erp_action); } static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) { - struct zfcp_unit *unit; + struct scsi_device *sdev; if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) zfcp_erp_action_dismiss(&port->erp_action); else { - read_lock(&port->unit_list_lock); - list_for_each_entry(unit, &port->unit_list, list) - zfcp_erp_action_dismiss_unit(unit); - read_unlock(&port->unit_list_lock); + spin_lock(port->adapter->scsi_host->host_lock); + __shost_for_each_device(sdev, port->adapter->scsi_host) + if (sdev_to_zfcp(sdev)->port == port) + zfcp_erp_action_dismiss_lun(sdev); + spin_unlock(port->adapter->scsi_host->host_lock); } } @@ -124,15 +127,17 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, struct zfcp_port *port, - struct zfcp_unit *unit) + struct scsi_device *sdev) { int need = want; - int u_status, p_status, a_status; + int l_status, p_status, a_status; + struct zfcp_scsi_dev *zfcp_sdev; switch (want) { - case ZFCP_ERP_ACTION_REOPEN_UNIT: - u_status = atomic_read(&unit->status); - if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE) + case ZFCP_ERP_ACTION_REOPEN_LUN: + zfcp_sdev = sdev_to_zfcp(sdev); + l_status = atomic_read(&zfcp_sdev->status); + if (l_status & ZFCP_STATUS_COMMON_ERP_INUSE) return 0; p_status = atomic_read(&port->status); if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) || @@ -141,15 +146,21 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, if (!(p_status & ZFCP_STATUS_COMMON_UNBLOCKED)) need = ZFCP_ERP_ACTION_REOPEN_PORT; /* fall through */ - case ZFCP_ERP_ACTION_REOPEN_PORT: case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: p_status = atomic_read(&port->status); + if (!(p_status & ZFCP_STATUS_COMMON_OPEN)) + need = ZFCP_ERP_ACTION_REOPEN_PORT; + /* fall through */ + case ZFCP_ERP_ACTION_REOPEN_PORT: + p_status = atomic_read(&port->status); if (p_status & ZFCP_STATUS_COMMON_ERP_INUSE) return 0; a_status = atomic_read(&adapter->status); if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) || a_status & ZFCP_STATUS_COMMON_ERP_FAILED) return 0; + if (p_status & ZFCP_STATUS_COMMON_NOESC) + return need; if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED)) need = ZFCP_ERP_ACTION_REOPEN_ADAPTER; /* fall through */ @@ -165,22 +176,29 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, return need; } -static struct zfcp_erp_action *zfcp_erp_setup_act(int need, +static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, struct zfcp_adapter *adapter, struct zfcp_port *port, - struct zfcp_unit *unit) + struct scsi_device *sdev) { struct zfcp_erp_action *erp_action; - u32 status = 0; + struct zfcp_scsi_dev *zfcp_sdev; switch (need) { - case ZFCP_ERP_ACTION_REOPEN_UNIT: - if (!get_device(&unit->dev)) - return NULL; - atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); - erp_action = &unit->erp_action; - if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) - status = ZFCP_STATUS_ERP_CLOSE_ONLY; + case ZFCP_ERP_ACTION_REOPEN_LUN: + zfcp_sdev = sdev_to_zfcp(sdev); + if (!(act_status & ZFCP_STATUS_ERP_NO_REF)) + if (scsi_device_get(sdev)) + return NULL; + atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, + &zfcp_sdev->status); + erp_action = &zfcp_sdev->erp_action; + memset(erp_action, 0, sizeof(struct zfcp_erp_action)); + erp_action->port = port; + erp_action->sdev = sdev; + if (!(atomic_read(&zfcp_sdev->status) & + ZFCP_STATUS_COMMON_RUNNING)) + act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; break; case ZFCP_ERP_ACTION_REOPEN_PORT: @@ -190,8 +208,10 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, zfcp_erp_action_dismiss_port(port); atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); erp_action = &port->erp_action; + memset(erp_action, 0, sizeof(struct zfcp_erp_action)); + erp_action->port = port; if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) - status = ZFCP_STATUS_ERP_CLOSE_ONLY; + act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: @@ -199,66 +219,65 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, zfcp_erp_action_dismiss_adapter(adapter); atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); erp_action = &adapter->erp_action; + memset(erp_action, 0, sizeof(struct zfcp_erp_action)); if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_RUNNING)) - status = ZFCP_STATUS_ERP_CLOSE_ONLY; + act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; break; default: return NULL; } - memset(erp_action, 0, sizeof(struct zfcp_erp_action)); erp_action->adapter = adapter; - erp_action->port = port; - erp_action->unit = unit; erp_action->action = need; - erp_action->status = status; + erp_action->status = act_status; return erp_action; } static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, struct zfcp_port *port, - struct zfcp_unit *unit, char *id, void *ref) + struct scsi_device *sdev, + char *id, u32 act_status) { int retval = 1, need; - struct zfcp_erp_action *act = NULL; + struct zfcp_erp_action *act; if (!adapter->erp_thread) return -EIO; - need = zfcp_erp_required_act(want, adapter, port, unit); + need = zfcp_erp_required_act(want, adapter, port, sdev); if (!need) goto out; - atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); - act = zfcp_erp_setup_act(need, adapter, port, unit); + act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev); if (!act) goto out; + atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); ++adapter->erp_total_count; list_add_tail(&act->list, &adapter->erp_ready_head); wake_up(&adapter->erp_ready_wq); - zfcp_dbf_rec_thread("eracte1", adapter->dbf); retval = 0; out: - zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit); + zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need); return retval; } static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, - int clear_mask, char *id, void *ref) + int clear_mask, char *id) { zfcp_erp_adapter_block(adapter, clear_mask); zfcp_scsi_schedule_rports_block(adapter); /* ensure propagation of failed status to new devices */ if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - zfcp_erp_adapter_failed(adapter, "erareo1", NULL); + zfcp_erp_set_adapter_status(adapter, + ZFCP_STATUS_COMMON_ERP_FAILED); return -EIO; } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, - adapter, NULL, NULL, id, ref); + adapter, NULL, NULL, id, 0); } /** @@ -266,10 +285,8 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, * @adapter: Adapter to reopen. * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ -void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, - char *id, void *ref) +void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id) { unsigned long flags; @@ -278,10 +295,11 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, write_lock_irqsave(&adapter->erp_lock, flags); if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) - zfcp_erp_adapter_failed(adapter, "erareo1", NULL); + zfcp_erp_set_adapter_status(adapter, + ZFCP_STATUS_COMMON_ERP_FAILED); else zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, - NULL, NULL, id, ref); + NULL, NULL, id, 0); write_unlock_irqrestore(&adapter->erp_lock, flags); } @@ -290,13 +308,12 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, * @adapter: Adapter to shut down. * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, - char *id, void *ref) + char *id) { int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; - zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref); + zfcp_erp_adapter_reopen(adapter, clear | flags, id); } /** @@ -304,38 +321,21 @@ void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, * @port: Port to shut down. * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. - */ -void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id, - void *ref) -{ - int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; - zfcp_erp_port_reopen(port, clear | flags, id, ref); -} - -/** - * zfcp_erp_unit_shutdown - Shutdown unit - * @unit: Unit to shut down. - * @clear: Status flags to clear. - * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ -void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id, - void *ref) +void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id) { int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; - zfcp_erp_unit_reopen(unit, clear | flags, id, ref); + zfcp_erp_port_reopen(port, clear | flags, id); } static void zfcp_erp_port_block(struct zfcp_port *port, int clear) { - zfcp_erp_modify_port_status(port, "erpblk1", NULL, - ZFCP_STATUS_COMMON_UNBLOCKED | clear, - ZFCP_CLEAR); + zfcp_erp_clear_port_status(port, + ZFCP_STATUS_COMMON_UNBLOCKED | clear); } -static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, - int clear, char *id, void *ref) +static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, + char *id) { zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); @@ -344,136 +344,171 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, return; zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, - port->adapter, port, NULL, id, ref); + port->adapter, port, NULL, id, 0); } /** * zfcp_erp_port_forced_reopen - Forced close of port and open again * @port: Port to force close and to reopen. + * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ -void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id, - void *ref) +void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id) { unsigned long flags; struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(&adapter->erp_lock, flags); - _zfcp_erp_port_forced_reopen(port, clear, id, ref); + _zfcp_erp_port_forced_reopen(port, clear, id); write_unlock_irqrestore(&adapter->erp_lock, flags); } -static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, - void *ref) +static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { /* ensure propagation of failed status to new devices */ - zfcp_erp_port_failed(port, "erpreo1", NULL); + zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); return -EIO; } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, - port->adapter, port, NULL, id, ref); + port->adapter, port, NULL, id, 0); } /** * zfcp_erp_port_reopen - trigger remote port recovery * @port: port to recover * @clear_mask: flags in port status to be cleared + * @id: Id for debug trace event. * * Returns 0 if recovery has been triggered, < 0 if not. */ -int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) +int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { int retval; unsigned long flags; struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(&adapter->erp_lock, flags); - retval = _zfcp_erp_port_reopen(port, clear, id, ref); + retval = _zfcp_erp_port_reopen(port, clear, id); write_unlock_irqrestore(&adapter->erp_lock, flags); return retval; } -static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) +static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask) { - zfcp_erp_modify_unit_status(unit, "erublk1", NULL, - ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, - ZFCP_CLEAR); + zfcp_erp_clear_lun_status(sdev, + ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask); } -static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, - void *ref) +static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, + u32 act_status) { - struct zfcp_adapter *adapter = unit->port->adapter; + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; - zfcp_erp_unit_block(unit, clear); + zfcp_erp_lun_block(sdev, clear); - if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) return; - zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, - adapter, unit->port, unit, id, ref); + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter, + zfcp_sdev->port, sdev, id, act_status); } /** - * zfcp_erp_unit_reopen - initiate reopen of a unit - * @unit: unit to be reopened - * @clear_mask: specifies flags in unit status to be cleared + * zfcp_erp_lun_reopen - initiate reopen of a LUN + * @sdev: SCSI device / LUN to be reopened + * @clear_mask: specifies flags in LUN status to be cleared + * @id: Id for debug trace event. + * * Return: 0 on success, < 0 on error */ -void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, - void *ref) +void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id) { unsigned long flags; - struct zfcp_port *port = unit->port; + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_port *port = zfcp_sdev->port; struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(&adapter->erp_lock, flags); - _zfcp_erp_unit_reopen(unit, clear, id, ref); + _zfcp_erp_lun_reopen(sdev, clear, id, 0); write_unlock_irqrestore(&adapter->erp_lock, flags); } -static int status_change_set(unsigned long mask, atomic_t *status) +/** + * zfcp_erp_lun_shutdown - Shutdown LUN + * @sdev: SCSI device / LUN to shut down. + * @clear: Status flags to clear. + * @id: Id for debug trace event. + */ +void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id) { - return (atomic_read(status) ^ mask) & mask; + int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; + zfcp_erp_lun_reopen(sdev, clear | flags, id); } -static int status_change_clear(unsigned long mask, atomic_t *status) +/** + * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion + * @sdev: SCSI device / LUN to shut down. + * @id: Id for debug trace event. + * + * Do not acquire a reference for the LUN when creating the ERP + * action. It is safe, because this function waits for the ERP to + * complete first. This allows to shutdown the LUN, even when the SCSI + * device is in the state SDEV_DEL when scsi_device_get will fail. + */ +void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id) { - return atomic_read(status) & mask; + unsigned long flags; + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_port *port = zfcp_sdev->port; + struct zfcp_adapter *adapter = port->adapter; + int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; + + write_lock_irqsave(&adapter->erp_lock, flags); + _zfcp_erp_lun_reopen(sdev, clear, id, ZFCP_STATUS_ERP_NO_REF); + write_unlock_irqrestore(&adapter->erp_lock, flags); + + zfcp_erp_wait(adapter); +} + +static int status_change_set(unsigned long mask, atomic_t *status) +{ + return (atomic_read(status) ^ mask) & mask; } static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) { if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) - zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf); + zfcp_dbf_rec_run("eraubl1", &adapter->erp_action); 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_dbf_rec_port("erpubl1", NULL, port); + zfcp_dbf_rec_run("erpubl1", &port->erp_action); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); } -static void zfcp_erp_unit_unblock(struct zfcp_unit *unit) +static void zfcp_erp_lun_unblock(struct scsi_device *sdev) { - if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status)) - zfcp_dbf_rec_unit("eruubl1", NULL, unit); - atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status); + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + + if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status)) + zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action); + atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->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_dbf_rec_action("erator1", erp_action); + zfcp_dbf_rec_run("erator1", erp_action); } static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) @@ -490,11 +525,11 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) if (act->status & (ZFCP_STATUS_ERP_DISMISSED | ZFCP_STATUS_ERP_TIMEDOUT)) { req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; - zfcp_dbf_rec_action("erscf_1", act); + zfcp_dbf_rec_run("erscf_1", act); req->erp_action = NULL; } if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) - zfcp_dbf_rec_action("erscf_2", act); + zfcp_dbf_rec_run("erscf_2", act); if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) act->fsf_req_id = 0; } else @@ -545,41 +580,42 @@ static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) } static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, - int clear, char *id, void *ref) + int clear, char *id) { struct zfcp_port *port; read_lock(&adapter->port_list_lock); list_for_each_entry(port, &adapter->port_list, list) - _zfcp_erp_port_reopen(port, clear, id, ref); + _zfcp_erp_port_reopen(port, clear, id); read_unlock(&adapter->port_list_lock); } -static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, - char *id, void *ref) +static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear, + char *id) { - struct zfcp_unit *unit; + struct scsi_device *sdev; - read_lock(&port->unit_list_lock); - list_for_each_entry(unit, &port->unit_list, list) - _zfcp_erp_unit_reopen(unit, clear, id, ref); - read_unlock(&port->unit_list_lock); + spin_lock(port->adapter->scsi_host->host_lock); + __shost_for_each_device(sdev, port->adapter->scsi_host) + if (sdev_to_zfcp(sdev)->port == port) + _zfcp_erp_lun_reopen(sdev, clear, id, 0); + spin_unlock(port->adapter->scsi_host->host_lock); } static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) { switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: - _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL); + _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1"); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: - _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL); + _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2"); break; case ZFCP_ERP_ACTION_REOPEN_PORT: - _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL); + _zfcp_erp_port_reopen(act->port, 0, "ersff_3"); break; - case ZFCP_ERP_ACTION_REOPEN_UNIT: - _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL); + case ZFCP_ERP_ACTION_REOPEN_LUN: + _zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", 0); break; } } @@ -588,13 +624,13 @@ static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act) { switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: - _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL); + _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1"); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: - _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL); + _zfcp_erp_port_reopen(act->port, 0, "ersfs_2"); break; case ZFCP_ERP_ACTION_REOPEN_PORT: - _zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL); + _zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3"); break; } } @@ -613,17 +649,6 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter) read_unlock_irqrestore(&adapter->erp_lock, flags); } -static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) -{ - struct zfcp_qdio *qdio = act->adapter->qdio; - - if (zfcp_qdio_open(qdio)) - return ZFCP_ERP_FAILED; - init_waitqueue_head(&qdio->req_q_wq); - atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status); - return ZFCP_ERP_SUCCEEDED; -} - static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) { struct zfcp_port *port; @@ -631,7 +656,7 @@ static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) adapter->peer_d_id); if (IS_ERR(port)) /* error or port already attached */ return; - _zfcp_erp_port_reopen(port, 0, "ereptp1", NULL); + _zfcp_erp_port_reopen(port, 0, "ereptp1"); } static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) @@ -654,10 +679,8 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) return ZFCP_ERP_FAILED; } - 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; @@ -696,10 +719,10 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) if (ret) return ZFCP_ERP_FAILED; - zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf); + zfcp_dbf_rec_run("erasox1", act); wait_event(adapter->erp_ready_wq, !list_empty(&adapter->erp_ready_head)); - zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf); + zfcp_dbf_rec_run("erasox2", act); if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) return ZFCP_ERP_FAILED; @@ -714,6 +737,14 @@ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act) if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED) return ZFCP_ERP_FAILED; + if (mempool_resize(act->adapter->pool.sr_data, + act->adapter->stat_read_buf_num, GFP_KERNEL)) + return ZFCP_ERP_FAILED; + + if (mempool_resize(act->adapter->pool.status_read_req, + act->adapter->stat_read_buf_num, GFP_KERNEL)) + return ZFCP_ERP_FAILED; + atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num); if (zfcp_status_read_refill(act->adapter)) return ZFCP_ERP_FAILED; @@ -730,9 +761,8 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) zfcp_fsf_req_dismiss_all(adapter); adapter->fsf_req_seq_no = 0; 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); + /* all ports and LUNs are closed */ + zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN); atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); @@ -742,7 +772,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; - if (zfcp_erp_adapter_strategy_open_qdio(act)) { + if (zfcp_qdio_open(adapter->qdio)) { atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); @@ -849,7 +879,7 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) struct zfcp_port *port = act->port; if (port->wwpn != adapter->peer_wwpn) { - zfcp_erp_port_failed(port, "eroptp1", NULL); + zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); return ZFCP_ERP_FAILED; } port->d_id = adapter->peer_d_id; @@ -885,8 +915,7 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) } if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) { port->d_id = 0; - _zfcp_erp_port_reopen(port, 0, "erpsoc1", NULL); - return ZFCP_ERP_EXIT; + return ZFCP_ERP_FAILED; } /* fall through otherwise */ } @@ -922,82 +951,86 @@ close_init_done: return zfcp_erp_port_strategy_open_common(erp_action); } -static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) +static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev) { - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | - ZFCP_STATUS_UNIT_SHARED | - ZFCP_STATUS_UNIT_READONLY, - &unit->status); + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, + &zfcp_sdev->status); } -static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) +static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action) { - int retval = zfcp_fsf_close_unit(erp_action); + int retval = zfcp_fsf_close_lun(erp_action); if (retval == -ENOMEM) return ZFCP_ERP_NOMEM; - erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING; + erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING; if (retval) return ZFCP_ERP_FAILED; return ZFCP_ERP_CONTINUES; } -static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) +static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action) { - int retval = zfcp_fsf_open_unit(erp_action); + int retval = zfcp_fsf_open_lun(erp_action); if (retval == -ENOMEM) return ZFCP_ERP_NOMEM; - erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING; + erp_action->step = ZFCP_ERP_STEP_LUN_OPENING; if (retval) return ZFCP_ERP_FAILED; return ZFCP_ERP_CONTINUES; } -static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) +static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action) { - struct zfcp_unit *unit = erp_action->unit; + struct scsi_device *sdev = erp_action->sdev; + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); switch (erp_action->step) { case ZFCP_ERP_STEP_UNINITIALIZED: - zfcp_erp_unit_strategy_clearstati(unit); - if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) - return zfcp_erp_unit_strategy_close(erp_action); + zfcp_erp_lun_strategy_clearstati(sdev); + if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) + return zfcp_erp_lun_strategy_close(erp_action); /* already closed, fall through */ - case ZFCP_ERP_STEP_UNIT_CLOSING: - if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) + case ZFCP_ERP_STEP_LUN_CLOSING: + if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) return ZFCP_ERP_FAILED; if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) return ZFCP_ERP_EXIT; - return zfcp_erp_unit_strategy_open(erp_action); + return zfcp_erp_lun_strategy_open(erp_action); - case ZFCP_ERP_STEP_UNIT_OPENING: - if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) + case ZFCP_ERP_STEP_LUN_OPENING: + if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) return ZFCP_ERP_SUCCEEDED; } return ZFCP_ERP_FAILED; } -static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) +static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result) { + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + switch (result) { case ZFCP_ERP_SUCCEEDED : - atomic_set(&unit->erp_counter, 0); - zfcp_erp_unit_unblock(unit); + atomic_set(&zfcp_sdev->erp_counter, 0); + zfcp_erp_lun_unblock(sdev); break; case ZFCP_ERP_FAILED : - atomic_inc(&unit->erp_counter); - if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) { - dev_err(&unit->port->adapter->ccw_device->dev, - "ERP failed for unit 0x%016Lx on " + atomic_inc(&zfcp_sdev->erp_counter); + if (atomic_read(&zfcp_sdev->erp_counter) > ZFCP_MAX_ERPS) { + dev_err(&zfcp_sdev->port->adapter->ccw_device->dev, + "ERP failed for LUN 0x%016Lx on " "port 0x%016Lx\n", - (unsigned long long)unit->fcp_lun, - (unsigned long long)unit->port->wwpn); - zfcp_erp_unit_failed(unit, "erusck1", NULL); + (unsigned long long)zfcp_scsi_dev_lun(sdev), + (unsigned long long)zfcp_sdev->port->wwpn); + zfcp_erp_set_lun_status(sdev, + ZFCP_STATUS_COMMON_ERP_FAILED); } break; } - if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - zfcp_erp_unit_block(unit, 0); + if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { + zfcp_erp_lun_block(sdev, 0); result = ZFCP_ERP_EXIT; } return result; @@ -1021,7 +1054,8 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) dev_err(&port->adapter->ccw_device->dev, "ERP failed for remote port 0x%016Lx\n", (unsigned long long)port->wwpn); - zfcp_erp_port_failed(port, "erpsck1", NULL); + zfcp_erp_set_port_status(port, + ZFCP_STATUS_COMMON_ERP_FAILED); } break; } @@ -1048,7 +1082,8 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, dev_err(&adapter->ccw_device->dev, "ERP cannot recover an error " "on the FCP device\n"); - zfcp_erp_adapter_failed(adapter, "erasck1", NULL); + zfcp_erp_set_adapter_status(adapter, + ZFCP_STATUS_COMMON_ERP_FAILED); } break; } @@ -1065,12 +1100,12 @@ static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, { struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_port *port = erp_action->port; - struct zfcp_unit *unit = erp_action->unit; + struct scsi_device *sdev = erp_action->sdev; switch (erp_action->action) { - case ZFCP_ERP_ACTION_REOPEN_UNIT: - result = zfcp_erp_strategy_check_unit(unit, result); + case ZFCP_ERP_ACTION_REOPEN_LUN: + result = zfcp_erp_strategy_check_lun(sdev, result); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: @@ -1105,7 +1140,8 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) int action = act->action; struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; - struct zfcp_unit *unit = act->unit; + struct scsi_device *sdev = act->sdev; + struct zfcp_scsi_dev *zfcp_sdev; u32 erp_status = act->status; switch (action) { @@ -1113,7 +1149,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { _zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "ersscg1", NULL); + "ersscg1"); return ZFCP_ERP_EXIT; } break; @@ -1123,16 +1159,17 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) if (zfcp_erp_strat_change_det(&port->status, erp_status)) { _zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - "ersscg2", NULL); + "ersscg2"); return ZFCP_ERP_EXIT; } break; - case ZFCP_ERP_ACTION_REOPEN_UNIT: - if (zfcp_erp_strat_change_det(&unit->status, erp_status)) { - _zfcp_erp_unit_reopen(unit, - ZFCP_STATUS_COMMON_ERP_FAILED, - "ersscg3", NULL); + case ZFCP_ERP_ACTION_REOPEN_LUN: + zfcp_sdev = sdev_to_zfcp(sdev); + if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) { + _zfcp_erp_lun_reopen(sdev, + ZFCP_STATUS_COMMON_ERP_FAILED, + "ersscg3", 0); return ZFCP_ERP_EXIT; } break; @@ -1143,6 +1180,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) { struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_scsi_dev *zfcp_sdev; adapter->erp_total_count--; if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { @@ -1151,12 +1189,13 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) } list_del(&erp_action->list); - zfcp_dbf_rec_action("eractd1", erp_action); + zfcp_dbf_rec_run("eractd1", erp_action); switch (erp_action->action) { - case ZFCP_ERP_ACTION_REOPEN_UNIT: + case ZFCP_ERP_ACTION_REOPEN_LUN: + zfcp_sdev = sdev_to_zfcp(erp_action->sdev); atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, - &erp_action->unit->status); + &zfcp_sdev->status); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: @@ -1176,32 +1215,30 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; - struct zfcp_unit *unit = act->unit; + struct scsi_device *sdev = act->sdev; switch (act->action) { - case ZFCP_ERP_ACTION_REOPEN_UNIT: - if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { - get_device(&unit->dev); - if (scsi_queue_work(unit->port->adapter->scsi_host, - &unit->scsi_work) <= 0) - put_device(&unit->dev); - } - put_device(&unit->dev); + case ZFCP_ERP_ACTION_REOPEN_LUN: + if (!(act->status & ZFCP_STATUS_ERP_NO_REF)) + scsi_device_put(sdev); break; - case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: if (result == ZFCP_ERP_SUCCEEDED) zfcp_scsi_schedule_rport_register(port); + /* fall through */ + case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: put_device(&port->dev); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (result == ZFCP_ERP_SUCCEEDED) { register_service_level(&adapter->service_level); - queue_work(adapter->work_queue, &adapter->scan_work); + zfcp_fc_conditional_port_scan(adapter); + queue_work(adapter->work_queue, &adapter->ns_up_work); } else unregister_service_level(&adapter->service_level); + kref_put(&adapter->ref, zfcp_adapter_release); break; } @@ -1216,8 +1253,8 @@ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) return zfcp_erp_port_forced_strategy(erp_action); case ZFCP_ERP_ACTION_REOPEN_PORT: return zfcp_erp_port_strategy(erp_action); - case ZFCP_ERP_ACTION_REOPEN_UNIT: - return zfcp_erp_unit_strategy(erp_action); + case ZFCP_ERP_ACTION_REOPEN_LUN: + return zfcp_erp_lun_strategy(erp_action); } return ZFCP_ERP_FAILED; } @@ -1239,6 +1276,11 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) goto unlock; } + if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { + retval = ZFCP_ERP_FAILED; + goto check_target; + } + zfcp_erp_action_to_running(erp_action); /* no lock to allow for blocking operations */ @@ -1256,7 +1298,7 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; } if (adapter->erp_total_count == adapter->erp_low_mem_count) - _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1", NULL); + _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1"); else { zfcp_erp_strategy_memwait(erp_action); retval = ZFCP_ERP_CONTINUES; @@ -1271,6 +1313,7 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) goto unlock; } +check_target: retval = zfcp_erp_strategy_check_target(erp_action, retval); zfcp_erp_action_dequeue(erp_action); retval = zfcp_erp_strategy_statechange(erp_action, retval); @@ -1299,11 +1342,9 @@ static int zfcp_erp_thread(void *data) unsigned long flags; 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); if (kthread_should_stop()) break; @@ -1364,42 +1405,6 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) } /** - * zfcp_erp_adapter_failed - Set adapter status to failed. - * @adapter: Failed adapter. - * @id: Event id for debug trace. - * @ref: Reference for debug trace. - */ -void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref) -{ - zfcp_erp_modify_adapter_status(adapter, id, ref, - ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); -} - -/** - * zfcp_erp_port_failed - Set port status to failed. - * @port: Failed port. - * @id: Event id for debug trace. - * @ref: Reference for debug trace. - */ -void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref) -{ - zfcp_erp_modify_port_status(port, id, ref, - ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); -} - -/** - * zfcp_erp_unit_failed - Set unit status to failed. - * @unit: Failed unit. - * @id: Event id for debug trace. - * @ref: Reference for debug trace. - */ -void zfcp_erp_unit_failed(struct zfcp_unit *unit, char *id, void *ref) -{ - zfcp_erp_modify_unit_status(unit, id, ref, - ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); -} - -/** * zfcp_erp_wait - wait for completion of error recovery on an adapter * @adapter: adapter for which to wait for completion of its error recovery */ @@ -1411,210 +1416,158 @@ void zfcp_erp_wait(struct zfcp_adapter *adapter) } /** - * zfcp_erp_modify_adapter_status - change adapter status bits + * zfcp_erp_set_adapter_status - set adapter status bits * @adapter: adapter to change the status - * @id: id for the debug trace - * @ref: reference for the debug trace * @mask: status bits to change - * @set_or_clear: ZFCP_SET or ZFCP_CLEAR * - * Changes in common status bits are propagated to attached ports and units. + * Changes in common status bits are propagated to attached ports and LUNs. */ -void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id, - void *ref, u32 mask, int set_or_clear) +void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask) { struct zfcp_port *port; + struct scsi_device *sdev; unsigned long flags; u32 common_mask = mask & ZFCP_COMMON_FLAGS; - if (set_or_clear == ZFCP_SET) { - if (status_change_set(mask, &adapter->status)) - zfcp_dbf_rec_adapter(id, ref, adapter->dbf); - atomic_set_mask(mask, &adapter->status); - } else { - if (status_change_clear(mask, &adapter->status)) - 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); - } + atomic_set_mask(mask, &adapter->status); - if (common_mask) { - read_lock_irqsave(&adapter->port_list_lock, flags); - list_for_each_entry(port, &adapter->port_list, list) - zfcp_erp_modify_port_status(port, id, ref, common_mask, - set_or_clear); - read_unlock_irqrestore(&adapter->port_list_lock, flags); - } + if (!common_mask) + return; + + read_lock_irqsave(&adapter->port_list_lock, flags); + list_for_each_entry(port, &adapter->port_list, list) + atomic_set_mask(common_mask, &port->status); + read_unlock_irqrestore(&adapter->port_list_lock, flags); + + spin_lock_irqsave(adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, adapter->scsi_host) + atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status); + spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); } /** - * zfcp_erp_modify_port_status - change port status bits - * @port: port to change the status bits - * @id: id for the debug trace - * @ref: reference for the debug trace + * zfcp_erp_clear_adapter_status - clear adapter status bits + * @adapter: adapter to change the status * @mask: status bits to change - * @set_or_clear: ZFCP_SET or ZFCP_CLEAR * - * Changes in common status bits are propagated to attached units. + * Changes in common status bits are propagated to attached ports and LUNs. */ -void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref, - u32 mask, int set_or_clear) +void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask) { - struct zfcp_unit *unit; + struct zfcp_port *port; + struct scsi_device *sdev; unsigned long flags; u32 common_mask = mask & ZFCP_COMMON_FLAGS; + u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; + + atomic_clear_mask(mask, &adapter->status); + + if (!common_mask) + return; - if (set_or_clear == ZFCP_SET) { - if (status_change_set(mask, &port->status)) - zfcp_dbf_rec_port(id, ref, port); - atomic_set_mask(mask, &port->status); - } else { - if (status_change_clear(mask, &port->status)) - zfcp_dbf_rec_port(id, ref, port); - atomic_clear_mask(mask, &port->status); - if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) + if (clear_counter) + atomic_set(&adapter->erp_counter, 0); + + read_lock_irqsave(&adapter->port_list_lock, flags); + list_for_each_entry(port, &adapter->port_list, list) { + atomic_clear_mask(common_mask, &port->status); + if (clear_counter) atomic_set(&port->erp_counter, 0); } + read_unlock_irqrestore(&adapter->port_list_lock, flags); - if (common_mask) { - read_lock_irqsave(&port->unit_list_lock, flags); - list_for_each_entry(unit, &port->unit_list, list) - zfcp_erp_modify_unit_status(unit, id, ref, common_mask, - set_or_clear); - read_unlock_irqrestore(&port->unit_list_lock, flags); + spin_lock_irqsave(adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, adapter->scsi_host) { + atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status); + if (clear_counter) + atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); } + spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); } /** - * zfcp_erp_modify_unit_status - change unit status bits - * @unit: unit to change the status bits - * @id: id for the debug trace - * @ref: reference for the debug trace + * zfcp_erp_set_port_status - set port status bits + * @port: port to change the status * @mask: status bits to change - * @set_or_clear: ZFCP_SET or ZFCP_CLEAR - */ -void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref, - u32 mask, int set_or_clear) -{ - if (set_or_clear == ZFCP_SET) { - if (status_change_set(mask, &unit->status)) - zfcp_dbf_rec_unit(id, ref, unit); - atomic_set_mask(mask, &unit->status); - } else { - if (status_change_clear(mask, &unit->status)) - 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); - } - } -} - -/** - * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP - * @port: The "boxed" port. - * @id: The debug trace id. - * @id: Reference for the debug trace. + * + * Changes in common status bits are propagated to attached LUNs. */ -void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref) +void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask) { - zfcp_erp_modify_port_status(port, id, ref, - ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); - zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); -} + struct scsi_device *sdev; + u32 common_mask = mask & ZFCP_COMMON_FLAGS; + unsigned long flags; -/** - * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP - * @port: The "boxed" unit. - * @id: The debug trace id. - * @id: Reference for the debug trace. - */ -void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref) -{ - zfcp_erp_modify_unit_status(unit, id, ref, - ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); - zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); -} + atomic_set_mask(mask, &port->status); -/** - * zfcp_erp_port_access_denied - Adapter denied access to port. - * @port: port where access has been denied - * @id: id for debug trace - * @ref: reference for debug trace - * - * Since the adapter has denied access, stop using the port and the - * attached units. - */ -void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref) -{ - zfcp_erp_modify_port_status(port, id, ref, - ZFCP_STATUS_COMMON_ERP_FAILED | - ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); + if (!common_mask) + return; + + spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, port->adapter->scsi_host) + if (sdev_to_zfcp(sdev)->port == port) + atomic_set_mask(common_mask, + &sdev_to_zfcp(sdev)->status); + spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags); } /** - * zfcp_erp_unit_access_denied - Adapter denied access to unit. - * @unit: unit where access has been denied - * @id: id for debug trace - * @ref: reference for debug trace + * zfcp_erp_clear_port_status - clear port status bits + * @port: adapter to change the status + * @mask: status bits to change * - * Since the adapter has denied access, stop using the unit. + * Changes in common status bits are propagated to attached LUNs. */ -void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, char *id, void *ref) +void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) { - zfcp_erp_modify_unit_status(unit, id, ref, - ZFCP_STATUS_COMMON_ERP_FAILED | - ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); -} + struct scsi_device *sdev; + u32 common_mask = mask & ZFCP_COMMON_FLAGS; + u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; + unsigned long flags; -static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, char *id, - void *ref) -{ - int status = atomic_read(&unit->status); - if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | - ZFCP_STATUS_COMMON_ACCESS_BOXED))) + atomic_clear_mask(mask, &port->status); + + if (!common_mask) return; - zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); + if (clear_counter) + atomic_set(&port->erp_counter, 0); + + spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, port->adapter->scsi_host) + if (sdev_to_zfcp(sdev)->port == port) { + atomic_clear_mask(common_mask, + &sdev_to_zfcp(sdev)->status); + if (clear_counter) + atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); + } + spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags); } -static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id, - void *ref) +/** + * zfcp_erp_set_lun_status - set lun status bits + * @sdev: SCSI device / lun to set the status bits + * @mask: status bits to change + */ +void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask) { - struct zfcp_unit *unit; - unsigned long flags; - int status = atomic_read(&port->status); - - if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | - ZFCP_STATUS_COMMON_ACCESS_BOXED))) { - read_lock_irqsave(&port->unit_list_lock, flags); - list_for_each_entry(unit, &port->unit_list, list) - zfcp_erp_unit_access_changed(unit, id, ref); - read_unlock_irqrestore(&port->unit_list_lock, flags); - return; - } + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); - zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); + atomic_set_mask(mask, &zfcp_sdev->status); } /** - * zfcp_erp_adapter_access_changed - Process change in adapter ACT - * @adapter: Adapter where the Access Control Table (ACT) changed - * @id: Id for debug trace - * @ref: Reference for debug trace + * zfcp_erp_clear_lun_status - clear lun status bits + * @sdev: SCSi device / lun to clear the status bits + * @mask: status bits to change */ -void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id, - void *ref) +void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask) { - unsigned long flags; - struct zfcp_port *port; + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); - if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) - return; + atomic_clear_mask(mask, &zfcp_sdev->status); - read_lock_irqsave(&adapter->port_list_lock, flags); - list_for_each_entry(port, &adapter->port_list, list) - zfcp_erp_port_access_changed(port, id, ref); - read_unlock_irqrestore(&adapter->port_list_lock, flags); + if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) + atomic_set(&zfcp_sdev->erp_counter, 0); } + |
