/* * Eyecatcher pseudo flag to bitwise or-combine with enum zfcp_erp_act_type. * Used to indicate that an ERP action could not be set up despite a detected * need for some recovery.
*/ #define ZFCP_ERP_ACTION_NONE 0xc0 /* * Eyecatcher pseudo flag to bitwise or-combine with enum zfcp_erp_act_type. * Used to indicate that ERP not needed because the object has * ZFCP_STATUS_COMMON_ERP_FAILED.
*/ #define ZFCP_ERP_ACTION_FAILED 0xe0
switch (want) { case ZFCP_ERP_ACTION_REOPEN_LUN:
zsdev = sdev_to_zfcp(sdev); if (atomic_read(&zsdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
need = 0; break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
need = 0; break; case ZFCP_ERP_ACTION_REOPEN_PORT: if (atomic_read(&port->status) &
ZFCP_STATUS_COMMON_ERP_FAILED) {
need = 0; /* ensure propagation of failed status to new devices */
zfcp_erp_set_port_status(
port, ZFCP_STATUS_COMMON_ERP_FAILED);
} break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (atomic_read(&adapter->status) &
ZFCP_STATUS_COMMON_ERP_FAILED) {
need = 0; /* ensure propagation of failed status to new devices */
zfcp_erp_set_adapter_status(
adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
} break;
}
if (WARN_ON_ONCE(need != ZFCP_ERP_ACTION_REOPEN_LUN &&
need != ZFCP_ERP_ACTION_REOPEN_PORT &&
need != ZFCP_ERP_ACTION_REOPEN_PORT_FORCED &&
need != ZFCP_ERP_ACTION_REOPEN_ADAPTER)) return NULL;
switch (need) { 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_or(ZFCP_STATUS_COMMON_ERP_INUSE,
&zfcp_sdev->status);
erp_action = &zfcp_sdev->erp_action;
WARN_ON_ONCE(erp_action->port != port);
WARN_ON_ONCE(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: case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: if (!get_device(&port->dev)) return NULL;
zfcp_erp_action_dismiss_port(port);
atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
erp_action = &port->erp_action;
WARN_ON_ONCE(erp_action->port != port);
WARN_ON_ONCE(erp_action->sdev != NULL); if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; break;
write_lock_irqsave(&adapter->erp_lock, flags); /* Stand-in zfcp port with fields just good enough for * zfcp_dbf_rec_trig() and zfcp_dbf_set_common(). * Under lock because tmpport is static.
*/
atomic_set(&tmpport.status, -1); /* unknown */
tmpport.wwpn = port_name;
tmpport.d_id = port_id;
zfcp_dbf_rec_trig(dbftag, adapter, &tmpport, NULL,
ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
ZFCP_ERP_ACTION_NONE);
write_unlock_irqrestore(&adapter->erp_lock, flags);
}
/** * 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. * @dbftag: Tag for debug trace event.
*/ void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *dbftag)
{ unsignedlong flags; struct zfcp_adapter *adapter = port->adapter;
/** * zfcp_erp_port_reopen - trigger remote port recovery * @port: port to recover * @clear: flags in port status to be cleared * @dbftag: Tag for debug trace event.
*/ void zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *dbftag)
{ unsignedlong flags; struct zfcp_adapter *adapter = port->adapter;
/** * zfcp_erp_lun_shutdown - Shutdown LUN * @sdev: SCSI device / LUN to shut down. * @clear: Status flags to clear. * @dbftag: Tag for debug trace event.
*/ void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *dbftag)
{ int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
zfcp_erp_lun_reopen(sdev, clear | flags, dbftag);
}
/** * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion * @sdev: SCSI device / LUN to shut down. * @dbftag: Tag 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 *dbftag)
{ unsignedlong 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;
/* * We allocated the shost for the first time. Before it was NULL, * and so we deferred all updates in the xconf- and xport-data * handlers. We need to make up for that now, and make all the updates * that would have been done before. * * We can be sure that xconf- and xport-data succeeded, because * otherwise this function is not called. But they might have been * incomplete.
*/
/* * There is a remote possibility that the 'Exchange Port Data' request * reports a different connectivity status than 'Exchange Config Data'. * But any change to the connectivity status of the local optic that * happens after the initial xconf request is expected to be reported * to us, as soon as we post Status Read Buffers to the FCP channel * firmware after this function. So any resulting inconsistency will * only be momentary.
*/ if (config_data->header.incomplete)
zfcp_fsf_fc_host_link_down(adapter);
/* close queues to ensure that buffers are not accessed by adapter */
zfcp_qdio_close(adapter->qdio);
zfcp_fsf_req_dismiss_all(adapter);
adapter->fsf_req_seq_no = 0;
zfcp_fc_wka_ports_force_offline(adapter->gs); /* all ports and LUNs are closed */
zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN);
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN) {
zfcp_erp_adapter_strategy_close(act); if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY) return ZFCP_ERP_EXIT;
}
if (zfcp_erp_adapter_strategy_open(act)) {
ssleep(8); return ZFCP_ERP_FAILED;
}
return ZFCP_ERP_SUCCEEDED;
}
staticenum zfcp_erp_act_result zfcp_erp_port_forced_strategy_close( struct zfcp_erp_action *act)
{ int retval;
retval = zfcp_fsf_close_physical_port(act); if (retval == -ENOMEM) return ZFCP_ERP_NOMEM;
act->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING; if (retval) return ZFCP_ERP_FAILED;
return ZFCP_ERP_CONTINUES;
}
staticenum zfcp_erp_act_result zfcp_erp_port_forced_strategy( struct zfcp_erp_action *erp_action)
{ struct zfcp_port *port = erp_action->port; int status = atomic_read(&port->status);
switch (erp_action->step) { case ZFCP_ERP_STEP_UNINITIALIZED: if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
(status & ZFCP_STATUS_COMMON_OPEN)) return zfcp_erp_port_forced_strategy_close(erp_action); else return ZFCP_ERP_FAILED;
case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: if (!(status & ZFCP_STATUS_PORT_PHYS_OPEN)) return ZFCP_ERP_SUCCEEDED; break; case ZFCP_ERP_STEP_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_OPENING: case ZFCP_ERP_STEP_LUN_CLOSING: case ZFCP_ERP_STEP_LUN_OPENING: /* NOP */ break;
} return ZFCP_ERP_FAILED;
}
staticenum zfcp_erp_act_result zfcp_erp_port_strategy_close( struct zfcp_erp_action *erp_action)
{ int retval;
retval = zfcp_fsf_close_port(erp_action); if (retval == -ENOMEM) return ZFCP_ERP_NOMEM;
erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING; if (retval) return ZFCP_ERP_FAILED; return ZFCP_ERP_CONTINUES;
}
staticenum zfcp_erp_act_result zfcp_erp_port_strategy_open_port( struct zfcp_erp_action *erp_action)
{ int retval;
retval = zfcp_fsf_open_port(erp_action); if (retval == -ENOMEM) return ZFCP_ERP_NOMEM;
erp_action->step = ZFCP_ERP_STEP_PORT_OPENING; if (retval) return ZFCP_ERP_FAILED; return ZFCP_ERP_CONTINUES;
}
switch (act->step) { case ZFCP_ERP_STEP_UNINITIALIZED: case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_CLOSING: if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) return zfcp_erp_open_ptp_port(act); if (!port->d_id) {
zfcp_fc_trigger_did_lookup(port); return ZFCP_ERP_EXIT;
} return zfcp_erp_port_strategy_open_port(act);
case ZFCP_ERP_STEP_PORT_OPENING: /* D_ID might have changed during open */ if (p_status & ZFCP_STATUS_COMMON_OPEN) { if (!port->d_id) {
zfcp_fc_trigger_did_lookup(port); return ZFCP_ERP_EXIT;
} return ZFCP_ERP_SUCCEEDED;
} if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) {
port->d_id = 0; return ZFCP_ERP_FAILED;
} /* no early return otherwise, continue after switch case */ break; case ZFCP_ERP_STEP_LUN_CLOSING: case ZFCP_ERP_STEP_LUN_OPENING: /* NOP */ break;
} return ZFCP_ERP_FAILED;
}
if ((p_status & ZFCP_STATUS_COMMON_NOESC) &&
!(p_status & ZFCP_STATUS_COMMON_OPEN)) goto close_init_done;
switch (erp_action->step) { case ZFCP_ERP_STEP_UNINITIALIZED: if (p_status & ZFCP_STATUS_COMMON_OPEN) return zfcp_erp_port_strategy_close(erp_action); break;
case ZFCP_ERP_STEP_PORT_CLOSING: if (p_status & ZFCP_STATUS_COMMON_OPEN) return ZFCP_ERP_FAILED; break; case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_OPENING: case ZFCP_ERP_STEP_LUN_CLOSING: case ZFCP_ERP_STEP_LUN_OPENING: /* NOP */ break;
}
close_init_done: if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) return ZFCP_ERP_EXIT;
switch (erp_action->step) { case ZFCP_ERP_STEP_UNINITIALIZED:
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 */
fallthrough; 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_lun_strategy_open(erp_action);
case ZFCP_ERP_STEP_LUN_OPENING: if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) return ZFCP_ERP_SUCCEEDED; break; case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_OPENING: /* NOP */ break;
} return ZFCP_ERP_FAILED;
}
case ZFCP_ERP_FAILED : if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) {
zfcp_erp_port_block(port, 0);
result = ZFCP_ERP_EXIT;
}
atomic_inc(&port->erp_counter); if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
dev_err(&port->adapter->ccw_device->dev, "ERP failed for remote port 0x%016Lx\n",
(unsignedlonglong)port->wwpn);
zfcp_erp_set_port_status(port,
ZFCP_STATUS_COMMON_ERP_FAILED);
} break; case ZFCP_ERP_CONTINUES: case ZFCP_ERP_EXIT: case ZFCP_ERP_DISMISSED: case ZFCP_ERP_NOMEM: /* NOP */ break;
}
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
zfcp_erp_port_block(port, 0);
result = ZFCP_ERP_EXIT;
} return result;
}
case ZFCP_ERP_FAILED :
atomic_inc(&adapter->erp_counter); if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) {
dev_err(&adapter->ccw_device->dev, "ERP cannot recover an error " "on the FCP device\n");
zfcp_erp_set_adapter_status(adapter,
ZFCP_STATUS_COMMON_ERP_FAILED);
} break; case ZFCP_ERP_CONTINUES: case ZFCP_ERP_EXIT: case ZFCP_ERP_DISMISSED: case ZFCP_ERP_NOMEM: /* NOP */ break;
}
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
zfcp_erp_adapter_block(adapter, 0);
result = ZFCP_ERP_EXIT;
} return result;
}
switch (type) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) {
_zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_COMMON_ERP_FAILED, "ersscg1"); return ZFCP_ERP_EXIT;
} break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: if (zfcp_erp_strat_change_det(&port->status, erp_status)) {
_zfcp_erp_port_reopen(port,
ZFCP_STATUS_COMMON_ERP_FAILED, "ersscg2"); return ZFCP_ERP_EXIT;
} break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT:
atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
&erp_action->port->status); break;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
&erp_action->adapter->status); break;
}
}
/** * zfcp_erp_try_rport_unblock - unblock rport if no more/new recovery * @port: zfcp_port whose fc_rport we should try to unblock
*/ staticvoid zfcp_erp_try_rport_unblock(struct zfcp_port *port)
{ unsignedlong flags; struct zfcp_adapter *adapter = port->adapter; int port_status; struct Scsi_Host *shost = adapter->scsi_host; struct scsi_device *sdev;
write_lock_irqsave(&adapter->erp_lock, flags);
port_status = atomic_read(&port->status); if ((port_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 ||
(port_status & (ZFCP_STATUS_COMMON_ERP_INUSE |
ZFCP_STATUS_COMMON_ERP_FAILED)) != 0) { /* new ERP of severity >= port triggered elsewhere meanwhile or * local link down (adapter erp_failed but not clear unblock)
*/
zfcp_dbf_rec_run_lvl(4, "ertru_p", &port->erp_action);
write_unlock_irqrestore(&adapter->erp_lock, flags); return;
}
spin_lock(shost->host_lock);
__shost_for_each_device(sdev, shost) { struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev); int lun_status;
if (sdev->sdev_state == SDEV_DEL ||
sdev->sdev_state == SDEV_CANCEL) continue; if (zsdev->port != port) continue; /* LUN under port of interest */
lun_status = atomic_read(&zsdev->status); if ((lun_status & ZFCP_STATUS_COMMON_ERP_FAILED) != 0) continue; /* unblock rport despite failed LUNs */ /* LUN recovery not given up yet [maybe follow-up pending] */ if ((lun_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 ||
(lun_status & ZFCP_STATUS_COMMON_ERP_INUSE) != 0) { /* LUN blocked: * not yet unblocked [LUN recovery pending] * or meanwhile blocked [new LUN recovery triggered]
*/
zfcp_dbf_rec_run_lvl(4, "ertru_l", &zsdev->erp_action);
spin_unlock(shost->host_lock);
write_unlock_irqrestore(&adapter->erp_lock, flags); return;
}
} /* now port has no child or all children have completed recovery, * and no ERP of severity >= port was meanwhile triggered elsewhere
*/
zfcp_scsi_schedule_rport_register(port);
spin_unlock(shost->host_lock);
write_unlock_irqrestore(&adapter->erp_lock, flags);
}
switch (act->type) { case ZFCP_ERP_ACTION_REOPEN_LUN: if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
scsi_device_put(sdev);
zfcp_erp_try_rport_unblock(port); break;
case ZFCP_ERP_ACTION_REOPEN_PORT: /* This switch case might also happen after a forced reopen * was successfully done and thus overwritten with a new * non-forced reopen at `ersfs_2'. In this case, we must not * do the clean-up of the non-forced version.
*/ if (act->step != ZFCP_ERP_STEP_UNINITIALIZED) if (result == ZFCP_ERP_SUCCEEDED)
zfcp_erp_try_rport_unblock(port);
fallthrough; 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);
zfcp_fc_conditional_port_scan(adapter);
queue_work(adapter->work_queue, &adapter->ns_up_work);
} else
unregister_service_level(&adapter->service_level);
if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
zfcp_erp_action_dequeue(erp_action);
result = ZFCP_ERP_DISMISSED; goto unlock;
}
if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
result = ZFCP_ERP_FAILED; goto check_target;
}
zfcp_erp_action_to_running(erp_action);
/* no lock to allow for blocking operations */
write_unlock_irqrestore(&adapter->erp_lock, flags);
result = zfcp_erp_strategy_do_action(erp_action);
write_lock_irqsave(&adapter->erp_lock, flags);
if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
result = ZFCP_ERP_CONTINUES;
switch (result) { case ZFCP_ERP_NOMEM: if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) {
++adapter->erp_low_mem_count;
erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;
} if (adapter->erp_total_count == adapter->erp_low_mem_count)
_zfcp_erp_adapter_reopen(adapter, 0, "erstgy1"); else {
zfcp_erp_strategy_memwait(erp_action);
result = ZFCP_ERP_CONTINUES;
} goto unlock;
case ZFCP_ERP_CONTINUES: if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
--adapter->erp_low_mem_count;
erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
} goto unlock; case ZFCP_ERP_SUCCEEDED: case ZFCP_ERP_FAILED: case ZFCP_ERP_EXIT: case ZFCP_ERP_DISMISSED: /* NOP */ break;
}
check_target:
result = zfcp_erp_strategy_check_target(erp_action, result);
zfcp_erp_action_dequeue(erp_action);
result = zfcp_erp_strategy_statechange(erp_action, result); if (result == ZFCP_ERP_EXIT) goto unlock; if (result == ZFCP_ERP_SUCCEEDED)
zfcp_erp_strategy_followup_success(erp_action); if (result == ZFCP_ERP_FAILED)
zfcp_erp_strategy_followup_failed(erp_action);
if (act) { /* there is more to come after dismission, no notify */ if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
zfcp_erp_wakeup(adapter);
}
}
return 0;
}
/** * zfcp_erp_thread_setup - Start ERP thread for adapter * @adapter: Adapter to start the ERP thread for * * Return: 0 on success, or error code from kthread_run().
*/ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
{ struct task_struct *thread;
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 PTR_ERR(thread);
}
adapter->erp_thread = thread; return 0;
}
/** * zfcp_erp_thread_kill - Stop ERP thread. * @adapter: Adapter where the ERP thread should be stopped. * * The caller of this routine ensures that the specified adapter has * been shut down and that this operation has been completed. Thus, * there are no pending erp_actions which would need to be handled * here.
*/ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
{
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));
}
/** * zfcp_erp_wait - wait for completion of error recovery on an adapter * @adapter: adapter for which to wait for completion of its error recovery
*/ void zfcp_erp_wait(struct zfcp_adapter *adapter)
{
wait_event(adapter->erp_done_wqh,
!(atomic_read(&adapter->status) &
ZFCP_STATUS_ADAPTER_ERP_PENDING));
}
/** * zfcp_erp_set_adapter_status - set adapter status bits * @adapter: adapter to change the status * @mask: status bits to change * * Changes in common status bits are propagated to attached ports and LUNs.
*/ void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
{ struct zfcp_port *port; struct scsi_device *sdev; unsignedlong flags;
u32 common_mask = mask & ZFCP_COMMON_FLAGS;
/* * if `scsi_host` is missing, xconfig/xport data has never completed * yet, so we can't access it, but there are also no SDEVs yet
*/ if (adapter->scsi_host == NULL) return;
/* * if `scsi_host` is missing, xconfig/xport data has never completed * yet, so we can't access it, but there are also no SDEVs yet
*/ if (adapter->scsi_host == NULL) return;
/** * zfcp_erp_set_port_status - set port status bits * @port: port to change the status * @mask: status bits to change * * Changes in common status bits are propagated to attached LUNs.
*/ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
{ struct scsi_device *sdev;
u32 common_mask = mask & ZFCP_COMMON_FLAGS; unsignedlong flags;
/** * zfcp_erp_clear_port_status - clear port status bits * @port: adapter to change the status * @mask: status bits to change * * Changes in common status bits are propagated to attached LUNs.
*/ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
{ struct scsi_device *sdev;
u32 common_mask = mask & ZFCP_COMMON_FLAGS;
u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; unsignedlong flags;
atomic_andnot(mask, &port->status);
if (!common_mask) return;
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_andnot(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);
}
/** * 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_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
atomic_or(mask, &zfcp_sdev->status);
}
/** * 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_clear_lun_status(struct scsi_device *sdev, u32 mask)
{ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
atomic_andnot(mask, &zfcp_sdev->status);
if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
atomic_set(&zfcp_sdev->erp_counter, 0);
}
/** * zfcp_erp_adapter_reset_sync() - Really reopen adapter and wait. * @adapter: Pointer to zfcp_adapter to reopen. * @dbftag: Trace tag string of length %ZFCP_DBF_TAG_LEN.
*/ void zfcp_erp_adapter_reset_sync(struct zfcp_adapter *adapter, char *dbftag)
{
zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, dbftag);
zfcp_erp_wait(adapter);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.