diff options
| -rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 45 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 3370 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 25 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 43 |
4 files changed, 1280 insertions, 2203 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 206b6e7a8bfd..67f45fc62f53 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
| @@ -91,17 +91,11 @@ zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size) | |||
| 91 | /* max. number of (data buffer) SBALEs in largest SBAL chain | 91 | /* max. number of (data buffer) SBALEs in largest SBAL chain |
| 92 | multiplied with number of sectors per 4k block */ | 92 | multiplied with number of sectors per 4k block */ |
| 93 | 93 | ||
| 94 | #define ZFCP_TYPE2_RECOVERY_TIME 8 /* seconds */ | ||
| 95 | |||
| 96 | /********************* FSF SPECIFIC DEFINES *********************************/ | 94 | /********************* FSF SPECIFIC DEFINES *********************************/ |
| 97 | 95 | ||
| 98 | /* ATTENTION: value must not be used by hardware */ | 96 | /* ATTENTION: value must not be used by hardware */ |
| 99 | #define FSF_QTCB_UNSOLICITED_STATUS 0x6305 | 97 | #define FSF_QTCB_UNSOLICITED_STATUS 0x6305 |
| 100 | 98 | ||
| 101 | /* Do 1st retry in 1 second, then double the timeout for each following retry */ | ||
| 102 | #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 1 | ||
| 103 | #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 | ||
| 104 | |||
| 105 | /* timeout value for "default timer" for fsf requests */ | 99 | /* timeout value for "default timer" for fsf requests */ |
| 106 | #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ) | 100 | #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ) |
| 107 | 101 | ||
| @@ -349,45 +343,6 @@ struct zfcp_rc_entry { | |||
| 349 | #define ZFCP_STATUS_FSFREQ_RETRY 0x00000800 | 343 | #define ZFCP_STATUS_FSFREQ_RETRY 0x00000800 |
| 350 | #define ZFCP_STATUS_FSFREQ_DISMISSED 0x00001000 | 344 | #define ZFCP_STATUS_FSFREQ_DISMISSED 0x00001000 |
| 351 | 345 | ||
| 352 | /*********************** ERROR RECOVERY PROCEDURE DEFINES ********************/ | ||
| 353 | |||
| 354 | #define ZFCP_MAX_ERPS 3 | ||
| 355 | |||
| 356 | #define ZFCP_ERP_FSFREQ_TIMEOUT (30 * HZ) | ||
| 357 | #define ZFCP_ERP_MEMWAIT_TIMEOUT HZ | ||
| 358 | |||
| 359 | #define ZFCP_STATUS_ERP_TIMEDOUT 0x10000000 | ||
| 360 | #define ZFCP_STATUS_ERP_CLOSE_ONLY 0x01000000 | ||
| 361 | #define ZFCP_STATUS_ERP_DISMISSING 0x00100000 | ||
| 362 | #define ZFCP_STATUS_ERP_DISMISSED 0x00200000 | ||
| 363 | #define ZFCP_STATUS_ERP_LOWMEM 0x00400000 | ||
| 364 | |||
| 365 | #define ZFCP_ERP_STEP_UNINITIALIZED 0x00000000 | ||
| 366 | #define ZFCP_ERP_STEP_FSF_XCONFIG 0x00000001 | ||
| 367 | #define ZFCP_ERP_STEP_PHYS_PORT_CLOSING 0x00000010 | ||
| 368 | #define ZFCP_ERP_STEP_PORT_CLOSING 0x00000100 | ||
| 369 | #define ZFCP_ERP_STEP_NAMESERVER_OPEN 0x00000200 | ||
| 370 | #define ZFCP_ERP_STEP_NAMESERVER_LOOKUP 0x00000400 | ||
| 371 | #define ZFCP_ERP_STEP_PORT_OPENING 0x00000800 | ||
| 372 | #define ZFCP_ERP_STEP_UNIT_CLOSING 0x00001000 | ||
| 373 | #define ZFCP_ERP_STEP_UNIT_OPENING 0x00002000 | ||
| 374 | |||
| 375 | /* Ordered by escalation level (necessary for proper erp-code operation) */ | ||
| 376 | #define ZFCP_ERP_ACTION_REOPEN_ADAPTER 0x4 | ||
| 377 | #define ZFCP_ERP_ACTION_REOPEN_PORT_FORCED 0x3 | ||
| 378 | #define ZFCP_ERP_ACTION_REOPEN_PORT 0x2 | ||
| 379 | #define ZFCP_ERP_ACTION_REOPEN_UNIT 0x1 | ||
| 380 | |||
| 381 | #define ZFCP_ERP_ACTION_RUNNING 0x1 | ||
| 382 | #define ZFCP_ERP_ACTION_READY 0x2 | ||
| 383 | |||
| 384 | #define ZFCP_ERP_SUCCEEDED 0x0 | ||
| 385 | #define ZFCP_ERP_FAILED 0x1 | ||
| 386 | #define ZFCP_ERP_CONTINUES 0x2 | ||
| 387 | #define ZFCP_ERP_EXIT 0x3 | ||
| 388 | #define ZFCP_ERP_DISMISSED 0x4 | ||
| 389 | #define ZFCP_ERP_NOMEM 0x5 | ||
| 390 | |||
| 391 | /************************* STRUCTURE DEFINITIONS *****************************/ | 346 | /************************* STRUCTURE DEFINITIONS *****************************/ |
| 392 | 347 | ||
| 393 | struct zfcp_fsf_req; | 348 | struct zfcp_fsf_req; |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 4d797e5264d9..643ac4bba5b5 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
| @@ -8,1345 +8,582 @@ | |||
| 8 | 8 | ||
| 9 | #include "zfcp_ext.h" | 9 | #include "zfcp_ext.h" |
| 10 | 10 | ||
| 11 | static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int, u8, | 11 | #define ZFCP_MAX_ERPS 3 |
| 12 | void *); | 12 | |
| 13 | static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int, u8, | 13 | enum zfcp_erp_act_flags { |
| 14 | void *); | 14 | ZFCP_STATUS_ERP_TIMEDOUT = 0x10000000, |
| 15 | static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int, u8, void *); | 15 | ZFCP_STATUS_ERP_CLOSE_ONLY = 0x01000000, |
| 16 | static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int, u8, void *); | 16 | ZFCP_STATUS_ERP_DISMISSING = 0x00100000, |
| 17 | 17 | ZFCP_STATUS_ERP_DISMISSED = 0x00200000, | |
| 18 | static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int, u8, | 18 | ZFCP_STATUS_ERP_LOWMEM = 0x00400000, |
| 19 | void *); | 19 | }; |
| 20 | static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int, u8, | ||
| 21 | void *); | ||
| 22 | |||
| 23 | static void zfcp_erp_adapter_block(struct zfcp_adapter *, int); | ||
| 24 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *); | ||
| 25 | static void zfcp_erp_port_block(struct zfcp_port *, int); | ||
| 26 | static void zfcp_erp_port_unblock(struct zfcp_port *); | ||
| 27 | static void zfcp_erp_unit_block(struct zfcp_unit *, int); | ||
| 28 | static void zfcp_erp_unit_unblock(struct zfcp_unit *); | ||
| 29 | |||
| 30 | static int zfcp_erp_thread(void *); | ||
| 31 | |||
| 32 | static int zfcp_erp_strategy(struct zfcp_erp_action *); | ||
| 33 | |||
| 34 | static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *); | ||
| 35 | static int zfcp_erp_strategy_memwait(struct zfcp_erp_action *); | ||
| 36 | static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *, int); | ||
| 37 | static int zfcp_erp_strategy_check_unit(struct zfcp_unit *, int); | ||
| 38 | static int zfcp_erp_strategy_check_port(struct zfcp_port *, int); | ||
| 39 | static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *, int); | ||
| 40 | static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *, | ||
| 41 | struct zfcp_port *, | ||
| 42 | struct zfcp_unit *, int); | ||
| 43 | static int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); | ||
| 44 | static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *, | ||
| 45 | struct zfcp_port *, | ||
| 46 | struct zfcp_unit *, int); | ||
| 47 | static int zfcp_erp_strategy_check_queues(struct zfcp_adapter *); | ||
| 48 | static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int); | ||
| 49 | |||
| 50 | static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *); | ||
| 51 | static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int); | ||
| 52 | static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *); | ||
| 53 | static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); | ||
| 54 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); | ||
| 55 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); | ||
| 56 | static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *); | ||
| 57 | static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *); | ||
| 58 | static int zfcp_erp_adapter_strategy_open_fsf_statusread( | ||
| 59 | struct zfcp_erp_action *); | ||
| 60 | |||
| 61 | static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *); | ||
| 62 | static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *); | ||
| 63 | |||
| 64 | static int zfcp_erp_port_strategy(struct zfcp_erp_action *); | ||
| 65 | static int zfcp_erp_port_strategy_clearstati(struct zfcp_port *); | ||
| 66 | static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *); | ||
| 67 | static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *); | ||
| 68 | static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *); | ||
| 69 | static int zfcp_erp_port_strategy_open_nameserver_wakeup( | ||
| 70 | struct zfcp_erp_action *); | ||
| 71 | static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *); | ||
| 72 | static int zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *); | ||
| 73 | static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *); | ||
| 74 | |||
| 75 | static int zfcp_erp_unit_strategy(struct zfcp_erp_action *); | ||
| 76 | static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *); | ||
| 77 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *); | ||
| 78 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *); | ||
| 79 | |||
| 80 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); | ||
| 81 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *); | ||
| 82 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *); | ||
| 83 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *); | ||
| 84 | |||
| 85 | static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *, | ||
| 86 | struct zfcp_port *, struct zfcp_unit *, | ||
| 87 | u8 id, void *ref); | ||
| 88 | static int zfcp_erp_action_dequeue(struct zfcp_erp_action *); | ||
| 89 | static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *, | ||
| 90 | struct zfcp_port *, struct zfcp_unit *, | ||
| 91 | int); | ||
| 92 | |||
| 93 | static void zfcp_erp_action_ready(struct zfcp_erp_action *); | ||
| 94 | static int zfcp_erp_action_exists(struct zfcp_erp_action *); | ||
| 95 | |||
| 96 | static void zfcp_erp_action_to_ready(struct zfcp_erp_action *); | ||
| 97 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *); | ||
| 98 | |||
| 99 | static void zfcp_erp_memwait_handler(unsigned long); | ||
| 100 | 20 | ||
| 101 | /** | 21 | enum zfcp_erp_steps { |
| 102 | * zfcp_close_fsf - stop FSF operations for an adapter | 22 | ZFCP_ERP_STEP_UNINITIALIZED = 0x0000, |
| 103 | * | 23 | ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, |
| 104 | * Dismiss and cleanup all pending fsf_reqs (this wakes up all initiators of | 24 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, |
| 105 | * requests waiting for completion; especially this returns SCSI commands | 25 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, |
| 106 | * with error state). | 26 | ZFCP_ERP_STEP_NAMESERVER_OPEN = 0x0200, |
| 107 | */ | 27 | ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400, |
| 108 | static void zfcp_close_fsf(struct zfcp_adapter *adapter) | 28 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, |
| 109 | { | 29 | ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, |
| 110 | /* close queues to ensure that buffers are not accessed by adapter */ | 30 | ZFCP_ERP_STEP_UNIT_OPENING = 0x2000, |
| 111 | zfcp_qdio_close(adapter); | 31 | }; |
| 112 | zfcp_fsf_req_dismiss_all(adapter); | ||
| 113 | /* reset FSF request sequence number */ | ||
| 114 | adapter->fsf_req_seq_no = 0; | ||
| 115 | /* all ports and units are closed */ | ||
| 116 | zfcp_erp_modify_adapter_status(adapter, 24, NULL, | ||
| 117 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | ||
| 118 | } | ||
| 119 | 32 | ||
| 120 | /** | 33 | enum zfcp_erp_act_type { |
| 121 | * zfcp_fsf_request_timeout_handler - called if a request timed out | 34 | ZFCP_ERP_ACTION_REOPEN_UNIT = 1, |
| 122 | * @data: pointer to adapter for handler function | 35 | ZFCP_ERP_ACTION_REOPEN_PORT = 2, |
| 123 | * | 36 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, |
| 124 | * This function needs to be called if requests (ELS, Generic Service, | 37 | ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, |
| 125 | * or SCSI commands) exceed a certain time limit. The assumption is | 38 | }; |
| 126 | * that after the time limit the adapter get stuck. So we trigger a reopen of | 39 | |
| 127 | * the adapter. | 40 | enum zfcp_erp_act_state { |
| 128 | */ | 41 | ZFCP_ERP_ACTION_RUNNING = 1, |
| 129 | static void zfcp_fsf_request_timeout_handler(unsigned long data) | 42 | ZFCP_ERP_ACTION_READY = 2, |
| 130 | { | 43 | }; |
| 131 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | ||
| 132 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62, | ||
| 133 | NULL); | ||
| 134 | } | ||
| 135 | 44 | ||
| 136 | void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout) | 45 | enum zfcp_erp_act_result { |
| 46 | ZFCP_ERP_SUCCEEDED = 0, | ||
| 47 | ZFCP_ERP_FAILED = 1, | ||
| 48 | ZFCP_ERP_CONTINUES = 2, | ||
| 49 | ZFCP_ERP_EXIT = 3, | ||
| 50 | ZFCP_ERP_DISMISSED = 4, | ||
| 51 | ZFCP_ERP_NOMEM = 5, | ||
| 52 | }; | ||
| 53 | |||
| 54 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) | ||
| 137 | { | 55 | { |
| 138 | fsf_req->timer.function = zfcp_fsf_request_timeout_handler; | 56 | zfcp_erp_modify_adapter_status(adapter, 15, NULL, |
| 139 | fsf_req->timer.data = (unsigned long) fsf_req->adapter; | 57 | ZFCP_STATUS_COMMON_UNBLOCKED | mask, |
| 140 | fsf_req->timer.expires = jiffies + timeout; | 58 | ZFCP_CLEAR); |
| 141 | add_timer(&fsf_req->timer); | ||
| 142 | } | 59 | } |
| 143 | 60 | ||
| 144 | /* | 61 | static int zfcp_erp_action_exists(struct zfcp_erp_action *act) |
| 145 | * function: | ||
| 146 | * | ||
| 147 | * purpose: called if an adapter failed, | ||
| 148 | * initiates adapter recovery which is done | ||
| 149 | * asynchronously | ||
| 150 | * | ||
| 151 | * returns: 0 - initiated action successfully | ||
| 152 | * <0 - failed to initiate action | ||
| 153 | */ | ||
| 154 | static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, | ||
| 155 | int clear_mask, u8 id, void *ref) | ||
| 156 | { | 62 | { |
| 157 | int retval; | 63 | struct zfcp_erp_action *curr_act; |
| 158 | |||
| 159 | zfcp_erp_adapter_block(adapter, clear_mask); | ||
| 160 | 64 | ||
| 161 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { | 65 | list_for_each_entry(curr_act, &act->adapter->erp_running_head, list) |
| 162 | /* ensure propagation of failed status to new devices */ | 66 | if (act == curr_act) |
| 163 | zfcp_erp_adapter_failed(adapter, 13, NULL); | 67 | return ZFCP_ERP_ACTION_RUNNING; |
| 164 | retval = -EIO; | 68 | return 0; |
| 165 | goto out; | ||
| 166 | } | ||
| 167 | retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, | ||
| 168 | adapter, NULL, NULL, id, ref); | ||
| 169 | |||
| 170 | out: | ||
| 171 | return retval; | ||
| 172 | } | 69 | } |
| 173 | 70 | ||
| 174 | /* | 71 | static void zfcp_erp_action_ready(struct zfcp_erp_action *act) |
| 175 | * function: | ||
| 176 | * | ||
| 177 | * purpose: Wrappper for zfcp_erp_adapter_reopen_internal | ||
| 178 | * used to ensure the correct locking | ||
| 179 | * | ||
| 180 | * returns: 0 - initiated action successfully | ||
| 181 | * <0 - failed to initiate action | ||
| 182 | */ | ||
| 183 | int zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask, | ||
| 184 | u8 id, void *ref) | ||
| 185 | { | 72 | { |
| 186 | int retval; | 73 | struct zfcp_adapter *adapter = act->adapter; |
| 187 | unsigned long flags; | ||
| 188 | 74 | ||
| 189 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 75 | list_move(&act->list, &act->adapter->erp_ready_head); |
| 190 | write_lock(&adapter->erp_lock); | 76 | zfcp_rec_dbf_event_action(146, act); |
| 191 | retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask, id, ref); | 77 | up(&adapter->erp_ready_sem); |
| 192 | write_unlock(&adapter->erp_lock); | 78 | zfcp_rec_dbf_event_thread(2, adapter); |
| 193 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 194 | |||
| 195 | return retval; | ||
| 196 | } | 79 | } |
| 197 | 80 | ||
| 198 | int zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask, | 81 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) |
| 199 | u8 id, void *ref) | ||
| 200 | { | 82 | { |
| 201 | int retval; | 83 | act->status |= ZFCP_STATUS_ERP_DISMISSED; |
| 202 | 84 | if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING) | |
| 203 | retval = zfcp_erp_adapter_reopen(adapter, | 85 | zfcp_erp_action_ready(act); |
| 204 | ZFCP_STATUS_COMMON_RUNNING | | ||
| 205 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
| 206 | clear_mask, id, ref); | ||
| 207 | |||
| 208 | return retval; | ||
| 209 | } | 86 | } |
| 210 | 87 | ||
| 211 | int zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask, u8 id, | 88 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) |
| 212 | void *ref) | ||
| 213 | { | 89 | { |
| 214 | int retval; | 90 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
| 91 | zfcp_erp_action_dismiss(&unit->erp_action); | ||
| 92 | } | ||
| 215 | 93 | ||
| 216 | retval = zfcp_erp_port_reopen(port, | 94 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) |
| 217 | ZFCP_STATUS_COMMON_RUNNING | | 95 | { |
| 218 | ZFCP_STATUS_COMMON_ERP_FAILED | | 96 | struct zfcp_unit *unit; |
| 219 | clear_mask, id, ref); | ||
| 220 | 97 | ||
| 221 | return retval; | 98 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
| 99 | zfcp_erp_action_dismiss(&port->erp_action); | ||
| 100 | else | ||
| 101 | list_for_each_entry(unit, &port->unit_list_head, list) | ||
| 102 | zfcp_erp_action_dismiss_unit(unit); | ||
| 222 | } | 103 | } |
| 223 | 104 | ||
| 224 | int zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask, u8 id, | 105 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) |
| 225 | void *ref) | ||
| 226 | { | 106 | { |
| 227 | int retval; | 107 | struct zfcp_port *port; |
| 228 | |||
| 229 | retval = zfcp_erp_unit_reopen(unit, | ||
| 230 | ZFCP_STATUS_COMMON_RUNNING | | ||
| 231 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
| 232 | clear_mask, id, ref); | ||
| 233 | 108 | ||
| 234 | return retval; | 109 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
| 110 | zfcp_erp_action_dismiss(&adapter->erp_action); | ||
| 111 | else | ||
| 112 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
| 113 | zfcp_erp_action_dismiss_port(port); | ||
| 235 | } | 114 | } |
| 236 | 115 | ||
| 237 | /* | 116 | static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, |
| 238 | * function: | 117 | struct zfcp_port *port, |
| 239 | * | 118 | struct zfcp_unit *unit) |
| 240 | * purpose: called if a port failed to be opened normally | ||
| 241 | * initiates Forced Reopen recovery which is done | ||
| 242 | * asynchronously | ||
| 243 | * | ||
| 244 | * returns: 0 - initiated action successfully | ||
| 245 | * <0 - failed to initiate action | ||
| 246 | */ | ||
| 247 | static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, | ||
| 248 | int clear_mask, u8 id, | ||
| 249 | void *ref) | ||
| 250 | { | 119 | { |
| 251 | int retval; | 120 | int need = want; |
| 252 | 121 | int u_status, p_status, a_status; | |
| 253 | zfcp_erp_port_block(port, clear_mask); | ||
| 254 | 122 | ||
| 255 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { | 123 | switch (want) { |
| 256 | retval = -EIO; | 124 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
| 257 | goto out; | 125 | u_status = atomic_read(&unit->status); |
| 126 | if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
| 127 | return 0; | ||
| 128 | p_status = atomic_read(&port->status); | ||
| 129 | if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) || | ||
| 130 | p_status & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
| 131 | return 0; | ||
| 132 | if (!(p_status & ZFCP_STATUS_COMMON_UNBLOCKED)) | ||
| 133 | need = ZFCP_ERP_ACTION_REOPEN_PORT; | ||
| 134 | /* fall through */ | ||
| 135 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
| 136 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
| 137 | p_status = atomic_read(&port->status); | ||
| 138 | if (p_status & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
| 139 | return 0; | ||
| 140 | a_status = atomic_read(&adapter->status); | ||
| 141 | if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) || | ||
| 142 | a_status & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
| 143 | return 0; | ||
| 144 | if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED)) | ||
| 145 | need = ZFCP_ERP_ACTION_REOPEN_ADAPTER; | ||
| 146 | /* fall through */ | ||
| 147 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
| 148 | a_status = atomic_read(&adapter->status); | ||
| 149 | if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
| 150 | return 0; | ||
| 258 | } | 151 | } |
| 259 | 152 | ||
| 260 | retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, | 153 | return need; |
| 261 | port->adapter, port, NULL, id, ref); | ||
| 262 | |||
| 263 | out: | ||
| 264 | return retval; | ||
| 265 | } | 154 | } |
| 266 | 155 | ||
| 267 | /* | 156 | static struct zfcp_erp_action *zfcp_erp_setup_act(int need, |
| 268 | * function: | 157 | struct zfcp_adapter *adapter, |
| 269 | * | 158 | struct zfcp_port *port, |
| 270 | * purpose: Wrappper for zfcp_erp_port_forced_reopen_internal | 159 | struct zfcp_unit *unit) |
| 271 | * used to ensure the correct locking | ||
| 272 | * | ||
| 273 | * returns: 0 - initiated action successfully | ||
| 274 | * <0 - failed to initiate action | ||
| 275 | */ | ||
| 276 | int zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask, u8 id, | ||
| 277 | void *ref) | ||
| 278 | { | 160 | { |
| 279 | int retval; | 161 | struct zfcp_erp_action *erp_action; |
| 280 | unsigned long flags; | 162 | u32 status = 0; |
| 281 | struct zfcp_adapter *adapter; | ||
| 282 | |||
| 283 | adapter = port->adapter; | ||
| 284 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
| 285 | write_lock(&adapter->erp_lock); | ||
| 286 | retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask, id, | ||
| 287 | ref); | ||
| 288 | write_unlock(&adapter->erp_lock); | ||
| 289 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 290 | 163 | ||
| 291 | return retval; | 164 | switch (need) { |
| 292 | } | 165 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
| 166 | zfcp_unit_get(unit); | ||
| 167 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); | ||
| 168 | erp_action = &unit->erp_action; | ||
| 169 | if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) | ||
| 170 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | ||
| 171 | break; | ||
| 293 | 172 | ||
| 294 | /* | 173 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 295 | * function: | 174 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 296 | * | 175 | zfcp_port_get(port); |
| 297 | * purpose: called if a port is to be opened | 176 | zfcp_erp_action_dismiss_port(port); |
| 298 | * initiates Reopen recovery which is done | 177 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); |
| 299 | * asynchronously | 178 | erp_action = &port->erp_action; |
| 300 | * | 179 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) |
| 301 | * returns: 0 - initiated action successfully | 180 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; |
| 302 | * <0 - failed to initiate action | 181 | break; |
| 303 | */ | ||
| 304 | static int zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask, | ||
| 305 | u8 id, void *ref) | ||
| 306 | { | ||
| 307 | int retval; | ||
| 308 | 182 | ||
| 309 | zfcp_erp_port_block(port, clear_mask); | 183 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
| 184 | zfcp_adapter_get(adapter); | ||
| 185 | zfcp_erp_action_dismiss_adapter(adapter); | ||
| 186 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); | ||
| 187 | erp_action = &adapter->erp_action; | ||
| 188 | if (!(atomic_read(&adapter->status) & | ||
| 189 | ZFCP_STATUS_COMMON_RUNNING)) | ||
| 190 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | ||
| 191 | break; | ||
| 310 | 192 | ||
| 311 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { | 193 | default: |
| 312 | /* ensure propagation of failed status to new devices */ | 194 | return NULL; |
| 313 | zfcp_erp_port_failed(port, 14, NULL); | ||
| 314 | retval = -EIO; | ||
| 315 | goto out; | ||
| 316 | } | 195 | } |
| 317 | 196 | ||
| 318 | retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, | 197 | memset(erp_action, 0, sizeof(struct zfcp_erp_action)); |
| 319 | port->adapter, port, NULL, id, ref); | 198 | erp_action->adapter = adapter; |
| 199 | erp_action->port = port; | ||
| 200 | erp_action->unit = unit; | ||
| 201 | erp_action->action = need; | ||
| 202 | erp_action->status = status; | ||
| 320 | 203 | ||
| 321 | out: | 204 | return erp_action; |
| 322 | return retval; | ||
| 323 | } | 205 | } |
| 324 | 206 | ||
| 325 | /** | 207 | static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, |
| 326 | * zfcp_erp_port_reopen - initiate reopen of a remote port | 208 | struct zfcp_port *port, |
| 327 | * @port: port to be reopened | 209 | struct zfcp_unit *unit, u8 id, void *ref) |
| 328 | * @clear_mask: specifies flags in port status to be cleared | ||
| 329 | * Return: 0 on success, < 0 on error | ||
| 330 | * | ||
| 331 | * This is a wrappper function for zfcp_erp_port_reopen_internal. It ensures | ||
| 332 | * correct locking. An error recovery task is initiated to do the reopen. | ||
| 333 | * To wait for the completion of the reopen zfcp_erp_wait should be used. | ||
| 334 | */ | ||
| 335 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask, u8 id, | ||
| 336 | void *ref) | ||
| 337 | { | 210 | { |
| 338 | int retval; | 211 | int retval = 1, need; |
| 339 | unsigned long flags; | 212 | struct zfcp_erp_action *act = NULL; |
| 340 | struct zfcp_adapter *adapter = port->adapter; | ||
| 341 | 213 | ||
| 342 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 214 | if (!(atomic_read(&adapter->status) & |
| 343 | write_lock(&adapter->erp_lock); | 215 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP)) |
| 344 | retval = zfcp_erp_port_reopen_internal(port, clear_mask, id, ref); | 216 | return -EIO; |
| 345 | write_unlock(&adapter->erp_lock); | 217 | |
| 346 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 218 | need = zfcp_erp_required_act(want, adapter, port, unit); |
| 219 | if (!need) | ||
| 220 | goto out; | ||
| 347 | 221 | ||
| 222 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); | ||
| 223 | act = zfcp_erp_setup_act(need, adapter, port, unit); | ||
| 224 | if (!act) | ||
| 225 | goto out; | ||
| 226 | ++adapter->erp_total_count; | ||
| 227 | list_add_tail(&act->list, &adapter->erp_ready_head); | ||
| 228 | up(&adapter->erp_ready_sem); | ||
| 229 | zfcp_rec_dbf_event_thread(1, adapter); | ||
| 230 | retval = 0; | ||
| 231 | out: | ||
| 232 | zfcp_rec_dbf_event_trigger(id, ref, want, need, act, | ||
| 233 | adapter, port, unit); | ||
| 348 | return retval; | 234 | return retval; |
| 349 | } | 235 | } |
| 350 | 236 | ||
| 351 | /* | 237 | static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, |
| 352 | * function: | 238 | int clear_mask, u8 id, void *ref) |
| 353 | * | ||
| 354 | * purpose: called if a unit is to be opened | ||
| 355 | * initiates Reopen recovery which is done | ||
| 356 | * asynchronously | ||
| 357 | * | ||
| 358 | * returns: 0 - initiated action successfully | ||
| 359 | * <0 - failed to initiate action | ||
| 360 | */ | ||
| 361 | static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask, | ||
| 362 | u8 id, void *ref) | ||
| 363 | { | 239 | { |
| 364 | int retval; | 240 | zfcp_erp_adapter_block(adapter, clear_mask); |
| 365 | struct zfcp_adapter *adapter = unit->port->adapter; | ||
| 366 | |||
| 367 | zfcp_erp_unit_block(unit, clear_mask); | ||
| 368 | 241 | ||
| 369 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { | 242 | /* ensure propagation of failed status to new devices */ |
| 370 | retval = -EIO; | 243 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
| 371 | goto out; | 244 | zfcp_erp_adapter_failed(adapter, 13, NULL); |
| 245 | return -EIO; | ||
| 372 | } | 246 | } |
| 373 | 247 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, | |
| 374 | retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, | 248 | adapter, NULL, NULL, id, ref); |
| 375 | adapter, unit->port, unit, id, ref); | ||
| 376 | out: | ||
| 377 | return retval; | ||
| 378 | } | 249 | } |
| 379 | 250 | ||
| 380 | /** | 251 | /** |
| 381 | * zfcp_erp_unit_reopen - initiate reopen of a unit | 252 | * zfcp_erp_adapter_reopen - Reopen adapter. |
| 382 | * @unit: unit to be reopened | 253 | * @adapter: Adapter to reopen. |
| 383 | * @clear_mask: specifies flags in unit status to be cleared | 254 | * @clear: Status flags to clear. |
| 384 | * Return: 0 on success, < 0 on error | 255 | * @id: Id for debug trace event. |
| 385 | * | 256 | * @ref: Reference for debug trace event. |
| 386 | * This is a wrappper for zfcp_erp_unit_reopen_internal. It ensures correct | ||
| 387 | * locking. An error recovery task is initiated to do the reopen. | ||
| 388 | * To wait for the completion of the reopen zfcp_erp_wait should be used. | ||
| 389 | */ | 257 | */ |
| 390 | int zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask, u8 id, | 258 | void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, |
| 391 | void *ref) | 259 | u8 id, void *ref) |
| 392 | { | 260 | { |
| 393 | int retval; | ||
| 394 | unsigned long flags; | 261 | unsigned long flags; |
| 395 | struct zfcp_adapter *adapter; | ||
| 396 | struct zfcp_port *port; | ||
| 397 | |||
| 398 | port = unit->port; | ||
| 399 | adapter = port->adapter; | ||
| 400 | 262 | ||
| 401 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 263 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
| 402 | write_lock(&adapter->erp_lock); | 264 | write_lock(&adapter->erp_lock); |
| 403 | retval = zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref); | 265 | _zfcp_erp_adapter_reopen(adapter, clear, id, ref); |
| 404 | write_unlock(&adapter->erp_lock); | 266 | write_unlock(&adapter->erp_lock); |
| 405 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 267 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
| 406 | |||
| 407 | return retval; | ||
| 408 | } | 268 | } |
| 409 | 269 | ||
| 410 | /** | 270 | /** |
| 411 | * zfcp_erp_adapter_block - mark adapter as blocked, block scsi requests | 271 | * zfcp_erp_adapter_shutdown - Shutdown adapter. |
| 272 | * @adapter: Adapter to shut down. | ||
| 273 | * @clear: Status flags to clear. | ||
| 274 | * @id: Id for debug trace event. | ||
| 275 | * @ref: Reference for debug trace event. | ||
| 412 | */ | 276 | */ |
| 413 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) | 277 | void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, |
| 278 | u8 id, void *ref) | ||
| 414 | { | 279 | { |
| 415 | zfcp_erp_modify_adapter_status(adapter, 15, NULL, | 280 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
| 416 | ZFCP_STATUS_COMMON_UNBLOCKED | | 281 | zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref); |
| 417 | clear_mask, ZFCP_CLEAR); | ||
| 418 | } | 282 | } |
| 419 | 283 | ||
| 420 | /* FIXME: isn't really atomic */ | 284 | /** |
| 421 | /* | 285 | * zfcp_erp_port_shutdown - Shutdown port |
| 422 | * returns the mask which has not been set so far, i.e. | 286 | * @port: Port to shut down. |
| 423 | * 0 if no bit has been changed, !0 if some bit has been changed | 287 | * @clear: Status flags to clear. |
| 424 | */ | 288 | * @id: Id for debug trace event. |
| 425 | static int atomic_test_and_set_mask(unsigned long mask, atomic_t *v) | 289 | * @ref: Reference for debug trace event. |
| 426 | { | ||
| 427 | int changed_bits = (atomic_read(v) /*XOR*/^ mask) & mask; | ||
| 428 | atomic_set_mask(mask, v); | ||
| 429 | return changed_bits; | ||
| 430 | } | ||
| 431 | |||
| 432 | /* FIXME: isn't really atomic */ | ||
| 433 | /* | ||
| 434 | * returns the mask which has not been cleared so far, i.e. | ||
| 435 | * 0 if no bit has been changed, !0 if some bit has been changed | ||
| 436 | */ | 290 | */ |
| 437 | static int atomic_test_and_clear_mask(unsigned long mask, atomic_t *v) | 291 | void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, u8 id, void *ref) |
| 438 | { | 292 | { |
| 439 | int changed_bits = atomic_read(v) & mask; | 293 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
| 440 | atomic_clear_mask(mask, v); | 294 | zfcp_erp_port_reopen(port, clear | flags, id, ref); |
| 441 | return changed_bits; | ||
| 442 | } | 295 | } |
| 443 | 296 | ||
| 444 | /** | 297 | /** |
| 445 | * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests | 298 | * zfcp_erp_unit_shutdown - Shutdown unit |
| 299 | * @unit: Unit to shut down. | ||
| 300 | * @clear: Status flags to clear. | ||
| 301 | * @id: Id for debug trace event. | ||
| 302 | * @ref: Reference for debug trace event. | ||
| 446 | */ | 303 | */ |
| 447 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) | 304 | void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, u8 id, void *ref) |
| 448 | { | 305 | { |
| 449 | if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | 306 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
| 450 | &adapter->status)) | 307 | zfcp_erp_unit_reopen(unit, clear | flags, id, ref); |
| 451 | zfcp_rec_dbf_event_adapter(16, NULL, adapter); | ||
| 452 | } | 308 | } |
| 453 | 309 | ||
| 454 | /* | 310 | static void zfcp_erp_port_block(struct zfcp_port *port, int clear) |
| 455 | * function: | ||
| 456 | * | ||
| 457 | * purpose: disable I/O, | ||
| 458 | * return any open requests and clean them up, | ||
| 459 | * aim: no pending and incoming I/O | ||
| 460 | * | ||
| 461 | * returns: | ||
| 462 | */ | ||
| 463 | static void | ||
| 464 | zfcp_erp_port_block(struct zfcp_port *port, int clear_mask) | ||
| 465 | { | 311 | { |
| 466 | zfcp_erp_modify_port_status(port, 17, NULL, | 312 | zfcp_erp_modify_port_status(port, 17, NULL, |
| 467 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, | 313 | ZFCP_STATUS_COMMON_UNBLOCKED | clear, |
| 468 | ZFCP_CLEAR); | 314 | ZFCP_CLEAR); |
| 469 | } | 315 | } |
| 470 | 316 | ||
| 471 | /* | 317 | static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, |
| 472 | * function: | 318 | int clear, u8 id, void *ref) |
| 473 | * | ||
| 474 | * purpose: enable I/O | ||
| 475 | * | ||
| 476 | * returns: | ||
| 477 | */ | ||
| 478 | static void | ||
| 479 | zfcp_erp_port_unblock(struct zfcp_port *port) | ||
| 480 | { | 319 | { |
| 481 | if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | 320 | zfcp_erp_port_block(port, clear); |
| 482 | &port->status)) | ||
| 483 | zfcp_rec_dbf_event_port(18, NULL, port); | ||
| 484 | } | ||
| 485 | 321 | ||
| 486 | /* | 322 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
| 487 | * function: | 323 | return; |
| 488 | * | ||
| 489 | * purpose: disable I/O, | ||
| 490 | * return any open requests and clean them up, | ||
| 491 | * aim: no pending and incoming I/O | ||
| 492 | * | ||
| 493 | * returns: | ||
| 494 | */ | ||
| 495 | static void | ||
| 496 | zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) | ||
| 497 | { | ||
| 498 | zfcp_erp_modify_unit_status(unit, 19, NULL, | ||
| 499 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, | ||
| 500 | ZFCP_CLEAR); | ||
| 501 | } | ||
| 502 | |||
| 503 | /* | ||
| 504 | * function: | ||
| 505 | * | ||
| 506 | * purpose: enable I/O | ||
| 507 | * | ||
| 508 | * returns: | ||
| 509 | */ | ||
| 510 | static void | ||
| 511 | zfcp_erp_unit_unblock(struct zfcp_unit *unit) | ||
| 512 | { | ||
| 513 | if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | ||
| 514 | &unit->status)) | ||
| 515 | zfcp_rec_dbf_event_unit(20, NULL, unit); | ||
| 516 | } | ||
| 517 | |||
| 518 | static void | ||
| 519 | zfcp_erp_action_ready(struct zfcp_erp_action *erp_action) | ||
| 520 | { | ||
| 521 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
| 522 | |||
| 523 | zfcp_erp_action_to_ready(erp_action); | ||
| 524 | up(&adapter->erp_ready_sem); | ||
| 525 | zfcp_rec_dbf_event_thread(2, adapter); | ||
| 526 | } | ||
| 527 | |||
| 528 | /* | ||
| 529 | * function: | ||
| 530 | * | ||
| 531 | * purpose: | ||
| 532 | * | ||
| 533 | * returns: <0 erp_action not found in any list | ||
| 534 | * ZFCP_ERP_ACTION_READY erp_action is in ready list | ||
| 535 | * ZFCP_ERP_ACTION_RUNNING erp_action is in running list | ||
| 536 | * | ||
| 537 | * locks: erp_lock must be held | ||
| 538 | */ | ||
| 539 | static int | ||
| 540 | zfcp_erp_action_exists(struct zfcp_erp_action *erp_action) | ||
| 541 | { | ||
| 542 | int retval = -EINVAL; | ||
| 543 | struct list_head *entry; | ||
| 544 | struct zfcp_erp_action *entry_erp_action; | ||
| 545 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
| 546 | |||
| 547 | /* search in running list */ | ||
| 548 | list_for_each(entry, &adapter->erp_running_head) { | ||
| 549 | entry_erp_action = | ||
| 550 | list_entry(entry, struct zfcp_erp_action, list); | ||
| 551 | if (entry_erp_action == erp_action) { | ||
| 552 | retval = ZFCP_ERP_ACTION_RUNNING; | ||
| 553 | goto out; | ||
| 554 | } | ||
| 555 | } | ||
| 556 | /* search in ready list */ | ||
| 557 | list_for_each(entry, &adapter->erp_ready_head) { | ||
| 558 | entry_erp_action = | ||
| 559 | list_entry(entry, struct zfcp_erp_action, list); | ||
| 560 | if (entry_erp_action == erp_action) { | ||
| 561 | retval = ZFCP_ERP_ACTION_READY; | ||
| 562 | goto out; | ||
| 563 | } | ||
| 564 | } | ||
| 565 | |||
| 566 | out: | ||
| 567 | return retval; | ||
| 568 | } | ||
| 569 | |||
| 570 | /* | ||
| 571 | * purpose: checks current status of action (timed out, dismissed, ...) | ||
| 572 | * and does appropriate preparations (dismiss fsf request, ...) | ||
| 573 | * | ||
| 574 | * locks: called under erp_lock (disabled interrupts) | ||
| 575 | */ | ||
| 576 | static void | ||
| 577 | zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | ||
| 578 | { | ||
| 579 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
| 580 | |||
| 581 | if (erp_action->fsf_req) { | ||
| 582 | /* take lock to ensure that request is not deleted meanwhile */ | ||
| 583 | spin_lock(&adapter->req_list_lock); | ||
| 584 | if (zfcp_reqlist_find_safe(adapter, erp_action->fsf_req) && | ||
| 585 | erp_action->fsf_req->erp_action == erp_action) { | ||
| 586 | /* fsf_req still exists */ | ||
| 587 | /* dismiss fsf_req of timed out/dismissed erp_action */ | ||
| 588 | if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | | ||
| 589 | ZFCP_STATUS_ERP_TIMEDOUT)) { | ||
| 590 | erp_action->fsf_req->status |= | ||
| 591 | ZFCP_STATUS_FSFREQ_DISMISSED; | ||
| 592 | zfcp_rec_dbf_event_action(142, erp_action); | ||
| 593 | } | ||
| 594 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) | ||
| 595 | zfcp_rec_dbf_event_action(143, erp_action); | ||
| 596 | /* | ||
| 597 | * If fsf_req is neither dismissed nor completed | ||
| 598 | * then keep it running asynchronously and don't mess | ||
| 599 | * with the association of erp_action and fsf_req. | ||
| 600 | */ | ||
| 601 | if (erp_action->fsf_req->status & | ||
| 602 | (ZFCP_STATUS_FSFREQ_COMPLETED | | ||
| 603 | ZFCP_STATUS_FSFREQ_DISMISSED)) { | ||
| 604 | /* forget about association between fsf_req | ||
| 605 | and erp_action */ | ||
| 606 | erp_action->fsf_req = NULL; | ||
| 607 | } | ||
| 608 | } else { | ||
| 609 | /* | ||
| 610 | * even if this fsf_req has gone, forget about | ||
| 611 | * association between erp_action and fsf_req | ||
| 612 | */ | ||
| 613 | erp_action->fsf_req = NULL; | ||
| 614 | } | ||
| 615 | spin_unlock(&adapter->req_list_lock); | ||
| 616 | } | ||
| 617 | } | ||
| 618 | 324 | ||
| 619 | /** | 325 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, |
| 620 | * zfcp_erp_async_handler_nolock - complete erp_action | 326 | port->adapter, port, NULL, id, ref); |
| 621 | * | ||
| 622 | * Used for normal completion, time-out, dismissal and failure after | ||
| 623 | * low memory condition. | ||
| 624 | */ | ||
| 625 | static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, | ||
| 626 | unsigned long set_mask) | ||
| 627 | { | ||
| 628 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { | ||
| 629 | erp_action->status |= set_mask; | ||
| 630 | zfcp_erp_action_ready(erp_action); | ||
| 631 | } else { | ||
| 632 | /* action is ready or gone - nothing to do */ | ||
| 633 | } | ||
| 634 | } | 327 | } |
| 635 | 328 | ||
| 636 | /** | 329 | /** |
| 637 | * zfcp_erp_async_handler - wrapper for erp_async_handler_nolock w/ locking | 330 | * zfcp_erp_port_forced_reopen - Forced close of port and open again |
| 331 | * @port: Port to force close and to reopen. | ||
| 332 | * @id: Id for debug trace event. | ||
| 333 | * @ref: Reference for debug trace event. | ||
| 638 | */ | 334 | */ |
| 639 | void zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, | 335 | void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, u8 id, |
| 640 | unsigned long set_mask) | 336 | void *ref) |
| 641 | { | 337 | { |
| 642 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
| 643 | unsigned long flags; | 338 | unsigned long flags; |
| 339 | struct zfcp_adapter *adapter = port->adapter; | ||
| 644 | 340 | ||
| 645 | write_lock_irqsave(&adapter->erp_lock, flags); | 341 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
| 646 | zfcp_erp_async_handler_nolock(erp_action, set_mask); | 342 | write_lock(&adapter->erp_lock); |
| 647 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 343 | _zfcp_erp_port_forced_reopen(port, clear, id, ref); |
| 344 | write_unlock(&adapter->erp_lock); | ||
| 345 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 648 | } | 346 | } |
| 649 | 347 | ||
| 650 | /* | 348 | static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, |
| 651 | * purpose: is called for erp_action which was slept waiting for | 349 | void *ref) |
| 652 | * memory becoming avaliable, | ||
| 653 | * will trigger that this action will be continued | ||
| 654 | */ | ||
| 655 | static void | ||
| 656 | zfcp_erp_memwait_handler(unsigned long data) | ||
| 657 | { | 350 | { |
| 658 | struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; | 351 | zfcp_erp_port_block(port, clear); |
| 659 | |||
| 660 | zfcp_erp_async_handler(erp_action, 0); | ||
| 661 | } | ||
| 662 | 352 | ||
| 663 | /* | 353 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
| 664 | * purpose: is called if an asynchronous erp step timed out, | 354 | /* ensure propagation of failed status to new devices */ |
| 665 | * action gets an appropriate flag and will be processed | 355 | zfcp_erp_port_failed(port, 14, NULL); |
| 666 | * accordingly | 356 | return -EIO; |
| 667 | */ | 357 | } |
| 668 | static void zfcp_erp_timeout_handler(unsigned long data) | ||
| 669 | { | ||
| 670 | struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; | ||
| 671 | 358 | ||
| 672 | zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT); | 359 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, |
| 360 | port->adapter, port, NULL, id, ref); | ||
| 673 | } | 361 | } |
| 674 | 362 | ||
| 675 | /** | 363 | /** |
| 676 | * zfcp_erp_action_dismiss - dismiss an erp_action | 364 | * zfcp_erp_port_reopen - trigger remote port recovery |
| 365 | * @port: port to recover | ||
| 366 | * @clear_mask: flags in port status to be cleared | ||
| 677 | * | 367 | * |
| 678 | * adapter->erp_lock must be held | 368 | * Returns 0 if recovery has been triggered, < 0 if not. |
| 679 | * | ||
| 680 | * Dismissal of an erp_action is usually required if an erp_action of | ||
| 681 | * higher priority is generated. | ||
| 682 | */ | 369 | */ |
| 683 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) | 370 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, void *ref) |
| 684 | { | ||
| 685 | erp_action->status |= ZFCP_STATUS_ERP_DISMISSED; | ||
| 686 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) | ||
| 687 | zfcp_erp_action_ready(erp_action); | ||
| 688 | } | ||
| 689 | |||
| 690 | int | ||
| 691 | zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | ||
| 692 | { | 371 | { |
| 693 | int retval = 0; | 372 | unsigned long flags; |
| 694 | 373 | int retval; | |
| 695 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | 374 | struct zfcp_adapter *adapter = port->adapter; |
| 696 | 375 | ||
| 697 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); | 376 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
| 698 | if (retval < 0) | 377 | write_lock(&adapter->erp_lock); |
| 699 | dev_err(&adapter->ccw_device->dev, | 378 | retval = _zfcp_erp_port_reopen(port, clear, id, ref); |
| 700 | "Creation of ERP thread failed.\n"); | 379 | write_unlock(&adapter->erp_lock); |
| 701 | else { | 380 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
| 702 | wait_event(adapter->erp_thread_wqh, | ||
| 703 | atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, | ||
| 704 | &adapter->status)); | ||
| 705 | } | ||
| 706 | 381 | ||
| 707 | return (retval < 0); | 382 | return retval; |
| 708 | } | 383 | } |
| 709 | 384 | ||
| 710 | /* | 385 | static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) |
| 711 | * function: | ||
| 712 | * | ||
| 713 | * purpose: | ||
| 714 | * | ||
| 715 | * returns: | ||
| 716 | * | ||
| 717 | * context: process (i.e. proc-fs or rmmod/insmod) | ||
| 718 | * | ||
| 719 | * note: The caller of this routine ensures that the specified | ||
| 720 | * adapter has been shut down and that this operation | ||
| 721 | * has been completed. Thus, there are no pending erp_actions | ||
| 722 | * which would need to be handled here. | ||
| 723 | */ | ||
| 724 | int | ||
| 725 | zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | ||
| 726 | { | 386 | { |
| 727 | int retval = 0; | 387 | zfcp_erp_modify_unit_status(unit, 19, NULL, |
| 728 | 388 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, | |
| 729 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); | 389 | ZFCP_CLEAR); |
| 730 | up(&adapter->erp_ready_sem); | ||
| 731 | zfcp_rec_dbf_event_thread_lock(2, adapter); | ||
| 732 | |||
| 733 | wait_event(adapter->erp_thread_wqh, | ||
| 734 | !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, | ||
| 735 | &adapter->status)); | ||
| 736 | |||
| 737 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, | ||
| 738 | &adapter->status); | ||
| 739 | |||
| 740 | return retval; | ||
| 741 | } | 390 | } |
| 742 | 391 | ||
| 743 | /* | 392 | static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id, |
| 744 | * purpose: is run as a kernel thread, | 393 | void *ref) |
| 745 | * goes through list of error recovery actions of associated adapter | ||
| 746 | * and delegates single action to execution | ||
| 747 | * | ||
| 748 | * returns: 0 | ||
| 749 | */ | ||
| 750 | static int | ||
| 751 | zfcp_erp_thread(void *data) | ||
| 752 | { | 394 | { |
| 753 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | 395 | struct zfcp_adapter *adapter = unit->port->adapter; |
| 754 | struct list_head *next; | ||
| 755 | struct zfcp_erp_action *erp_action; | ||
| 756 | unsigned long flags; | ||
| 757 | |||
| 758 | daemonize("zfcperp%s", zfcp_get_busid_by_adapter(adapter)); | ||
| 759 | /* Block all signals */ | ||
| 760 | siginitsetinv(¤t->blocked, 0); | ||
| 761 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
| 762 | wake_up(&adapter->erp_thread_wqh); | ||
| 763 | |||
| 764 | while (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, | ||
| 765 | &adapter->status)) { | ||
| 766 | |||
| 767 | write_lock_irqsave(&adapter->erp_lock, flags); | ||
| 768 | next = adapter->erp_ready_head.next; | ||
| 769 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
| 770 | 396 | ||
| 771 | if (next != &adapter->erp_ready_head) { | 397 | zfcp_erp_unit_block(unit, clear); |
| 772 | erp_action = | ||
| 773 | list_entry(next, struct zfcp_erp_action, list); | ||
| 774 | /* | ||
| 775 | * process action (incl. [re]moving it | ||
| 776 | * from 'ready' queue) | ||
| 777 | */ | ||
| 778 | zfcp_erp_strategy(erp_action); | ||
| 779 | } | ||
| 780 | 398 | ||
| 781 | /* | 399 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
| 782 | * sleep as long as there is nothing to do, i.e. | 400 | return; |
| 783 | * no action in 'ready' queue to be processed and | ||
| 784 | * thread is not to be killed | ||
| 785 | */ | ||
| 786 | zfcp_rec_dbf_event_thread_lock(4, adapter); | ||
| 787 | down_interruptible(&adapter->erp_ready_sem); | ||
| 788 | zfcp_rec_dbf_event_thread_lock(5, adapter); | ||
| 789 | } | ||
| 790 | |||
| 791 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
| 792 | wake_up(&adapter->erp_thread_wqh); | ||
| 793 | 401 | ||
| 794 | return 0; | 402 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, |
| 403 | adapter, unit->port, unit, id, ref); | ||
| 795 | } | 404 | } |
| 796 | 405 | ||
| 797 | /* | 406 | /** |
| 798 | * function: | 407 | * zfcp_erp_unit_reopen - initiate reopen of a unit |
| 799 | * | 408 | * @unit: unit to be reopened |
| 800 | * purpose: drives single error recovery action and schedules higher and | 409 | * @clear_mask: specifies flags in unit status to be cleared |
| 801 | * subordinate actions, if necessary | 410 | * Return: 0 on success, < 0 on error |
| 802 | * | ||
| 803 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 804 | * ZFCP_ERP_SUCCEEDED - action finished successfully (deqd) | ||
| 805 | * ZFCP_ERP_FAILED - action finished unsuccessfully (deqd) | ||
| 806 | * ZFCP_ERP_EXIT - action finished (dequeued), offline | ||
| 807 | * ZFCP_ERP_DISMISSED - action canceled (dequeued) | ||
| 808 | */ | 411 | */ |
| 809 | static int | 412 | void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id, void *ref) |
| 810 | zfcp_erp_strategy(struct zfcp_erp_action *erp_action) | ||
| 811 | { | 413 | { |
| 812 | int retval = 0; | ||
| 813 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
| 814 | struct zfcp_port *port = erp_action->port; | ||
| 815 | struct zfcp_unit *unit = erp_action->unit; | ||
| 816 | int action = erp_action->action; | ||
| 817 | u32 status = erp_action->status; | ||
| 818 | unsigned long flags; | 414 | unsigned long flags; |
| 415 | struct zfcp_port *port = unit->port; | ||
| 416 | struct zfcp_adapter *adapter = port->adapter; | ||
| 819 | 417 | ||
| 820 | /* serialise dismissing, timing out, moving, enqueueing */ | ||
| 821 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 418 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
| 822 | write_lock(&adapter->erp_lock); | 419 | write_lock(&adapter->erp_lock); |
| 823 | 420 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | |
| 824 | /* dequeue dismissed action and leave, if required */ | ||
| 825 | retval = zfcp_erp_strategy_check_action(erp_action, retval); | ||
| 826 | if (retval == ZFCP_ERP_DISMISSED) { | ||
| 827 | goto unlock; | ||
| 828 | } | ||
| 829 | |||
| 830 | /* | ||
| 831 | * move action to 'running' queue before processing it | ||
| 832 | * (to avoid a race condition regarding moving the | ||
| 833 | * action to the 'running' queue and back) | ||
| 834 | */ | ||
| 835 | zfcp_erp_action_to_running(erp_action); | ||
| 836 | |||
| 837 | /* | ||
| 838 | * try to process action as far as possible, | ||
| 839 | * no lock to allow for blocking operations (kmalloc, qdio, ...), | ||
| 840 | * afterwards the lock is required again for the following reasons: | ||
| 841 | * - dequeueing of finished action and enqueueing of | ||
| 842 | * follow-up actions must be atomic so that any other | ||
| 843 | * reopen-routine does not believe there is nothing to do | ||
| 844 | * and that it is safe to enqueue something else, | ||
| 845 | * - we want to force any control thread which is dismissing | ||
| 846 | * actions to finish this before we decide about | ||
| 847 | * necessary steps to be taken here further | ||
| 848 | */ | ||
| 849 | write_unlock(&adapter->erp_lock); | ||
| 850 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 851 | retval = zfcp_erp_strategy_do_action(erp_action); | ||
| 852 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
| 853 | write_lock(&adapter->erp_lock); | ||
| 854 | |||
| 855 | /* | ||
| 856 | * check for dismissed status again to avoid follow-up actions, | ||
| 857 | * failing of targets and so on for dismissed actions, | ||
| 858 | * we go through down() here because there has been an up() | ||
| 859 | */ | ||
| 860 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) | ||
| 861 | retval = ZFCP_ERP_CONTINUES; | ||
| 862 | |||
| 863 | switch (retval) { | ||
| 864 | case ZFCP_ERP_NOMEM: | ||
| 865 | /* no memory to continue immediately, let it sleep */ | ||
| 866 | if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) { | ||
| 867 | ++adapter->erp_low_mem_count; | ||
| 868 | erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; | ||
| 869 | } | ||
| 870 | /* This condition is true if there is no memory available | ||
| 871 | for any erp_action on this adapter. This implies that there | ||
| 872 | are no elements in the memory pool(s) left for erp_actions. | ||
| 873 | This might happen if an erp_action that used a memory pool | ||
| 874 | element was timed out. | ||
| 875 | */ | ||
| 876 | if (adapter->erp_total_count == adapter->erp_low_mem_count) | ||
| 877 | zfcp_erp_adapter_reopen_internal(adapter, 0, 66, NULL); | ||
| 878 | else | ||
| 879 | retval = zfcp_erp_strategy_memwait(erp_action); | ||
| 880 | goto unlock; | ||
| 881 | case ZFCP_ERP_CONTINUES: | ||
| 882 | /* leave since this action runs asynchronously */ | ||
| 883 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { | ||
| 884 | --adapter->erp_low_mem_count; | ||
| 885 | erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; | ||
| 886 | } | ||
| 887 | goto unlock; | ||
| 888 | } | ||
| 889 | /* ok, finished action (whatever its result is) */ | ||
| 890 | |||
| 891 | /* check for unrecoverable targets */ | ||
| 892 | retval = zfcp_erp_strategy_check_target(erp_action, retval); | ||
| 893 | |||
| 894 | /* action must be dequeued (here to allow for further ones) */ | ||
| 895 | zfcp_erp_action_dequeue(erp_action); | ||
| 896 | |||
| 897 | /* | ||
| 898 | * put this target through the erp mill again if someone has | ||
| 899 | * requested to change the status of a target being online | ||
| 900 | * to offline or the other way around | ||
| 901 | * (old retval is preserved if nothing has to be done here) | ||
| 902 | */ | ||
| 903 | retval = zfcp_erp_strategy_statechange(action, status, adapter, | ||
| 904 | port, unit, retval); | ||
| 905 | |||
| 906 | /* | ||
| 907 | * leave if target is in permanent error state or if | ||
| 908 | * action is repeated in order to process state change | ||
| 909 | */ | ||
| 910 | if (retval == ZFCP_ERP_EXIT) { | ||
| 911 | goto unlock; | ||
| 912 | } | ||
| 913 | |||
| 914 | /* trigger follow up actions */ | ||
| 915 | zfcp_erp_strategy_followup_actions(action, adapter, port, unit, retval); | ||
| 916 | |||
| 917 | unlock: | ||
| 918 | write_unlock(&adapter->erp_lock); | 421 | write_unlock(&adapter->erp_lock); |
| 919 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 422 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
| 920 | |||
| 921 | if (retval != ZFCP_ERP_CONTINUES) | ||
| 922 | zfcp_erp_action_cleanup(action, adapter, port, unit, retval); | ||
| 923 | |||
| 924 | /* | ||
| 925 | * a few tasks remain when the erp queues are empty | ||
| 926 | * (don't do that if the last action evaluated was dismissed | ||
| 927 | * since this clearly indicates that there is more to come) : | ||
| 928 | * - close the name server port if it is open yet | ||
| 929 | * (enqueues another [probably] final action) | ||
| 930 | * - otherwise, wake up whoever wants to be woken when we are | ||
| 931 | * done with erp | ||
| 932 | */ | ||
| 933 | if (retval != ZFCP_ERP_DISMISSED) | ||
| 934 | zfcp_erp_strategy_check_queues(adapter); | ||
| 935 | |||
| 936 | return retval; | ||
| 937 | } | 423 | } |
| 938 | 424 | ||
| 939 | /* | 425 | static int status_change_set(unsigned long mask, atomic_t *status) |
| 940 | * function: | ||
| 941 | * | ||
| 942 | * purpose: | ||
| 943 | * | ||
| 944 | * returns: ZFCP_ERP_DISMISSED - if action has been dismissed | ||
| 945 | * retval - otherwise | ||
| 946 | */ | ||
| 947 | static int | ||
| 948 | zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval) | ||
| 949 | { | 426 | { |
| 950 | zfcp_erp_strategy_check_fsfreq(erp_action); | 427 | return (atomic_read(status) ^ mask) & mask; |
| 951 | |||
| 952 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) { | ||
| 953 | zfcp_erp_action_dequeue(erp_action); | ||
| 954 | retval = ZFCP_ERP_DISMISSED; | ||
| 955 | } | ||
| 956 | |||
| 957 | return retval; | ||
| 958 | } | 428 | } |
| 959 | 429 | ||
| 960 | static int | 430 | static int status_change_clear(unsigned long mask, atomic_t *status) |
| 961 | zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) | ||
| 962 | { | 431 | { |
| 963 | int retval = ZFCP_ERP_FAILED; | 432 | return atomic_read(status) & mask; |
| 964 | |||
| 965 | /* | ||
| 966 | * try to execute/continue action as far as possible, | ||
| 967 | * note: no lock in subsequent strategy routines | ||
| 968 | * (this allows these routine to call schedule, e.g. | ||
| 969 | * kmalloc with such flags or qdio_initialize & friends) | ||
| 970 | * Note: in case of timeout, the separate strategies will fail | ||
| 971 | * anyhow. No need for a special action. Even worse, a nameserver | ||
| 972 | * failure would not wake up waiting ports without the call. | ||
| 973 | */ | ||
| 974 | switch (erp_action->action) { | ||
| 975 | |||
| 976 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
| 977 | retval = zfcp_erp_adapter_strategy(erp_action); | ||
| 978 | break; | ||
| 979 | |||
| 980 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
| 981 | retval = zfcp_erp_port_forced_strategy(erp_action); | ||
| 982 | break; | ||
| 983 | |||
| 984 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
| 985 | retval = zfcp_erp_port_strategy(erp_action); | ||
| 986 | break; | ||
| 987 | |||
| 988 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | ||
| 989 | retval = zfcp_erp_unit_strategy(erp_action); | ||
| 990 | break; | ||
| 991 | } | ||
| 992 | |||
| 993 | return retval; | ||
| 994 | } | 433 | } |
| 995 | 434 | ||
| 996 | /* | 435 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) |
| 997 | * function: | ||
| 998 | * | ||
| 999 | * purpose: triggers retry of this action after a certain amount of time | ||
| 1000 | * by means of timer provided by erp_action | ||
| 1001 | * | ||
| 1002 | * returns: ZFCP_ERP_CONTINUES - erp_action sleeps in erp running queue | ||
| 1003 | */ | ||
| 1004 | static int | ||
| 1005 | zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) | ||
| 1006 | { | 436 | { |
| 1007 | int retval = ZFCP_ERP_CONTINUES; | 437 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) |
| 1008 | 438 | zfcp_rec_dbf_event_adapter(16, NULL, adapter); | |
| 1009 | init_timer(&erp_action->timer); | 439 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); |
| 1010 | erp_action->timer.function = zfcp_erp_memwait_handler; | ||
| 1011 | erp_action->timer.data = (unsigned long) erp_action; | ||
| 1012 | erp_action->timer.expires = jiffies + ZFCP_ERP_MEMWAIT_TIMEOUT; | ||
| 1013 | add_timer(&erp_action->timer); | ||
| 1014 | |||
| 1015 | return retval; | ||
| 1016 | } | 440 | } |
| 1017 | 441 | ||
| 1018 | /* | 442 | static void zfcp_erp_port_unblock(struct zfcp_port *port) |
| 1019 | * function: zfcp_erp_adapter_failed | ||
| 1020 | * | ||
| 1021 | * purpose: sets the adapter and all underlying devices to ERP_FAILED | ||
| 1022 | * | ||
| 1023 | */ | ||
| 1024 | void | ||
| 1025 | zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref) | ||
| 1026 | { | 443 | { |
| 1027 | zfcp_erp_modify_adapter_status(adapter, id, ref, | 444 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) |
| 1028 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 445 | zfcp_rec_dbf_event_port(18, NULL, port); |
| 1029 | dev_err(&adapter->ccw_device->dev, "Adapter ERP failed.\n"); | 446 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); |
| 1030 | } | 447 | } |
| 1031 | 448 | ||
| 1032 | /* | 449 | static void zfcp_erp_unit_unblock(struct zfcp_unit *unit) |
| 1033 | * function: zfcp_erp_port_failed | ||
| 1034 | * | ||
| 1035 | * purpose: sets the port and all underlying devices to ERP_FAILED | ||
| 1036 | * | ||
| 1037 | */ | ||
| 1038 | void | ||
| 1039 | zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref) | ||
| 1040 | { | 450 | { |
| 1041 | zfcp_erp_modify_port_status(port, id, ref, | 451 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status)) |
| 1042 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 452 | zfcp_rec_dbf_event_unit(20, NULL, unit); |
| 1043 | 453 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status); | |
| 1044 | if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) | ||
| 1045 | dev_err(&port->adapter->ccw_device->dev, | ||
| 1046 | "Port ERP failed for WKA port d_id=0x%06x.\n", | ||
| 1047 | port->d_id); | ||
| 1048 | else | ||
| 1049 | dev_err(&port->adapter->ccw_device->dev, | ||
| 1050 | "Port ERP failed for port wwpn=0x%016Lx.\n", | ||
| 1051 | port->wwpn); | ||
| 1052 | } | 454 | } |
| 1053 | 455 | ||
| 1054 | /* | 456 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) |
| 1055 | * function: zfcp_erp_unit_failed | ||
| 1056 | * | ||
| 1057 | * purpose: sets the unit to ERP_FAILED | ||
| 1058 | * | ||
| 1059 | */ | ||
| 1060 | void | ||
| 1061 | zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref) | ||
| 1062 | { | 457 | { |
| 1063 | zfcp_erp_modify_unit_status(unit, id, ref, | 458 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); |
| 1064 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 459 | zfcp_rec_dbf_event_action(145, erp_action); |
| 1065 | |||
| 1066 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
| 1067 | "Unit ERP failed for unit 0x%016Lx on port 0x%016Lx.\n", | ||
| 1068 | unit->fcp_lun, unit->port->wwpn); | ||
| 1069 | } | 460 | } |
| 1070 | 461 | ||
| 1071 | /* | 462 | static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) |
| 1072 | * function: zfcp_erp_strategy_check_target | ||
| 1073 | * | ||
| 1074 | * purpose: increments the erp action count on the device currently in | ||
| 1075 | * recovery if the action failed or resets the count in case of | ||
| 1076 | * success. If a maximum count is exceeded the device is marked | ||
| 1077 | * as ERP_FAILED. | ||
| 1078 | * The 'blocked' state of a target which has been recovered | ||
| 1079 | * successfully is reset. | ||
| 1080 | * | ||
| 1081 | * returns: ZFCP_ERP_CONTINUES - action continues (not considered) | ||
| 1082 | * ZFCP_ERP_SUCCEEDED - action finished successfully | ||
| 1083 | * ZFCP_ERP_EXIT - action failed and will not continue | ||
| 1084 | */ | ||
| 1085 | static int | ||
| 1086 | zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result) | ||
| 1087 | { | 463 | { |
| 1088 | struct zfcp_adapter *adapter = erp_action->adapter; | 464 | struct zfcp_adapter *adapter = act->adapter; |
| 1089 | struct zfcp_port *port = erp_action->port; | ||
| 1090 | struct zfcp_unit *unit = erp_action->unit; | ||
| 1091 | |||
| 1092 | switch (erp_action->action) { | ||
| 1093 | 465 | ||
| 1094 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 466 | if (!act->fsf_req) |
| 1095 | result = zfcp_erp_strategy_check_unit(unit, result); | 467 | return; |
| 1096 | break; | ||
| 1097 | |||
| 1098 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
| 1099 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
| 1100 | result = zfcp_erp_strategy_check_port(port, result); | ||
| 1101 | break; | ||
| 1102 | |||
| 1103 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
| 1104 | result = zfcp_erp_strategy_check_adapter(adapter, result); | ||
| 1105 | break; | ||
| 1106 | } | ||
| 1107 | 468 | ||
| 1108 | return result; | 469 | spin_lock(&adapter->req_list_lock); |
| 470 | if (zfcp_reqlist_find_safe(adapter, act->fsf_req) && | ||
| 471 | act->fsf_req->erp_action == act) { | ||
| 472 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | | ||
| 473 | ZFCP_STATUS_ERP_TIMEDOUT)) { | ||
| 474 | act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; | ||
| 475 | zfcp_rec_dbf_event_action(142, act); | ||
| 476 | } | ||
| 477 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | ||
| 478 | zfcp_rec_dbf_event_action(143, act); | ||
| 479 | if (act->fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED | | ||
| 480 | ZFCP_STATUS_FSFREQ_DISMISSED)) | ||
| 481 | act->fsf_req = NULL; | ||
| 482 | } else | ||
| 483 | act->fsf_req = NULL; | ||
| 484 | spin_unlock(&adapter->req_list_lock); | ||
| 1109 | } | 485 | } |
| 1110 | 486 | ||
| 1111 | static int | 487 | /** |
| 1112 | zfcp_erp_strategy_statechange(int action, | 488 | * zfcp_erp_notify - Trigger ERP action. |
| 1113 | u32 status, | 489 | * @erp_action: ERP action to continue. |
| 1114 | struct zfcp_adapter *adapter, | 490 | * @set_mask: ERP action status flags to set. |
| 1115 | struct zfcp_port *port, | 491 | */ |
| 1116 | struct zfcp_unit *unit, int retval) | 492 | void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask) |
| 1117 | { | 493 | { |
| 1118 | switch (action) { | 494 | struct zfcp_adapter *adapter = erp_action->adapter; |
| 1119 | 495 | unsigned long flags; | |
| 1120 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
| 1121 | if (zfcp_erp_strategy_statechange_detected(&adapter->status, | ||
| 1122 | status)) { | ||
| 1123 | zfcp_erp_adapter_reopen_internal(adapter, | ||
| 1124 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
| 1125 | 67, NULL); | ||
| 1126 | retval = ZFCP_ERP_EXIT; | ||
| 1127 | } | ||
| 1128 | break; | ||
| 1129 | |||
| 1130 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
| 1131 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
| 1132 | if (zfcp_erp_strategy_statechange_detected(&port->status, | ||
| 1133 | status)) { | ||
| 1134 | zfcp_erp_port_reopen_internal(port, | ||
| 1135 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
| 1136 | 68, NULL); | ||
| 1137 | retval = ZFCP_ERP_EXIT; | ||
| 1138 | } | ||
| 1139 | break; | ||
| 1140 | 496 | ||
| 1141 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 497 | write_lock_irqsave(&adapter->erp_lock, flags); |
| 1142 | if (zfcp_erp_strategy_statechange_detected(&unit->status, | 498 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { |
| 1143 | status)) { | 499 | erp_action->status |= set_mask; |
| 1144 | zfcp_erp_unit_reopen_internal(unit, | 500 | zfcp_erp_action_ready(erp_action); |
| 1145 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
| 1146 | 69, NULL); | ||
| 1147 | retval = ZFCP_ERP_EXIT; | ||
| 1148 | } | ||
| 1149 | break; | ||
| 1150 | } | 501 | } |
| 1151 | 502 | write_unlock_irqrestore(&adapter->erp_lock, flags); | |
| 1152 | return retval; | ||
| 1153 | } | 503 | } |
| 1154 | 504 | ||
| 1155 | static int | 505 | /** |
| 1156 | zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) | 506 | * zfcp_erp_timeout_handler - Trigger ERP action from timed out ERP request |
| 507 | * @data: ERP action (from timer data) | ||
| 508 | */ | ||
| 509 | void zfcp_erp_timeout_handler(unsigned long data) | ||
| 1157 | { | 510 | { |
| 1158 | return | 511 | struct zfcp_erp_action *act = (struct zfcp_erp_action *) data; |
| 1159 | /* take it online */ | 512 | zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT); |
| 1160 | (atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) && | ||
| 1161 | (ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)) || | ||
| 1162 | /* take it offline */ | ||
| 1163 | (!atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) && | ||
| 1164 | !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)); | ||
| 1165 | } | 513 | } |
| 1166 | 514 | ||
| 1167 | static int | 515 | static void zfcp_erp_memwait_handler(unsigned long data) |
| 1168 | zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) | ||
| 1169 | { | 516 | { |
| 1170 | switch (result) { | 517 | zfcp_erp_notify((struct zfcp_erp_action *)data, 0); |
| 1171 | case ZFCP_ERP_SUCCEEDED : | ||
| 1172 | atomic_set(&unit->erp_counter, 0); | ||
| 1173 | zfcp_erp_unit_unblock(unit); | ||
| 1174 | break; | ||
| 1175 | case ZFCP_ERP_FAILED : | ||
| 1176 | atomic_inc(&unit->erp_counter); | ||
| 1177 | if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) | ||
| 1178 | zfcp_erp_unit_failed(unit, 21, NULL); | ||
| 1179 | break; | ||
| 1180 | case ZFCP_ERP_EXIT : | ||
| 1181 | /* nothing */ | ||
| 1182 | break; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { | ||
| 1186 | zfcp_erp_unit_block(unit, 0); /* for ZFCP_ERP_SUCCEEDED */ | ||
| 1187 | result = ZFCP_ERP_EXIT; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | return result; | ||
| 1191 | } | 518 | } |
| 1192 | 519 | ||
| 1193 | static int | 520 | static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) |
| 1194 | zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) | ||
| 1195 | { | 521 | { |
| 1196 | switch (result) { | 522 | init_timer(&erp_action->timer); |
| 1197 | case ZFCP_ERP_SUCCEEDED : | 523 | erp_action->timer.function = zfcp_erp_memwait_handler; |
| 1198 | atomic_set(&port->erp_counter, 0); | 524 | erp_action->timer.data = (unsigned long) erp_action; |
| 1199 | zfcp_erp_port_unblock(port); | 525 | erp_action->timer.expires = jiffies + HZ; |
| 1200 | break; | 526 | add_timer(&erp_action->timer); |
| 1201 | case ZFCP_ERP_FAILED : | ||
| 1202 | if (atomic_test_mask(ZFCP_STATUS_COMMON_NOESC, &port->status)) { | ||
| 1203 | zfcp_erp_port_block(port, 0); | ||
| 1204 | result = ZFCP_ERP_EXIT; | ||
| 1205 | } | ||
| 1206 | atomic_inc(&port->erp_counter); | ||
| 1207 | if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) | ||
| 1208 | zfcp_erp_port_failed(port, 22, NULL); | ||
| 1209 | break; | ||
| 1210 | case ZFCP_ERP_EXIT : | ||
| 1211 | /* nothing */ | ||
| 1212 | break; | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { | ||
| 1216 | zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */ | ||
| 1217 | result = ZFCP_ERP_EXIT; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | return result; | ||
| 1221 | } | 527 | } |
| 1222 | 528 | ||
| 1223 | static int | 529 | static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, |
| 1224 | zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result) | 530 | int clear, u8 id, void *ref) |
| 1225 | { | 531 | { |
| 1226 | switch (result) { | 532 | struct zfcp_port *port; |
| 1227 | case ZFCP_ERP_SUCCEEDED : | ||
| 1228 | atomic_set(&adapter->erp_counter, 0); | ||
| 1229 | zfcp_erp_adapter_unblock(adapter); | ||
| 1230 | break; | ||
| 1231 | case ZFCP_ERP_FAILED : | ||
| 1232 | atomic_inc(&adapter->erp_counter); | ||
| 1233 | if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) | ||
| 1234 | zfcp_erp_adapter_failed(adapter, 23, NULL); | ||
| 1235 | break; | ||
| 1236 | case ZFCP_ERP_EXIT : | ||
| 1237 | /* nothing */ | ||
| 1238 | break; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { | ||
| 1242 | zfcp_erp_adapter_block(adapter, 0); /* for ZFCP_ERP_SUCCEEDED */ | ||
| 1243 | result = ZFCP_ERP_EXIT; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | return result; | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | struct zfcp_erp_add_work { | ||
| 1250 | struct zfcp_unit *unit; | ||
| 1251 | struct work_struct work; | ||
| 1252 | }; | ||
| 1253 | 533 | ||
| 1254 | /** | 534 | list_for_each_entry(port, &adapter->port_list_head, list) |
| 1255 | * zfcp_erp_scsi_scan | 535 | if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)) |
| 1256 | * @data: pointer to a struct zfcp_erp_add_work | 536 | _zfcp_erp_port_reopen(port, clear, id, ref); |
| 1257 | * | ||
| 1258 | * Registers a logical unit with the SCSI stack. | ||
| 1259 | */ | ||
| 1260 | static void zfcp_erp_scsi_scan(struct work_struct *work) | ||
| 1261 | { | ||
| 1262 | struct zfcp_erp_add_work *p = | ||
| 1263 | container_of(work, struct zfcp_erp_add_work, work); | ||
| 1264 | struct zfcp_unit *unit = p->unit; | ||
| 1265 | struct fc_rport *rport = unit->port->rport; | ||
| 1266 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, | ||
| 1267 | unit->scsi_lun, 0); | ||
| 1268 | atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | ||
| 1269 | zfcp_unit_put(unit); | ||
| 1270 | kfree(p); | ||
| 1271 | } | 537 | } |
| 1272 | 538 | ||
| 1273 | /** | 539 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id, |
| 1274 | * zfcp_erp_schedule_work | 540 | void *ref) |
| 1275 | * @unit: pointer to unit which should be registered with SCSI stack | ||
| 1276 | * | ||
| 1277 | * Schedules work which registers a unit with the SCSI stack | ||
| 1278 | */ | ||
| 1279 | static void | ||
| 1280 | zfcp_erp_schedule_work(struct zfcp_unit *unit) | ||
| 1281 | { | 541 | { |
| 1282 | struct zfcp_erp_add_work *p; | 542 | struct zfcp_unit *unit; |
| 1283 | |||
| 1284 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 1285 | if (!p) { | ||
| 1286 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
| 1287 | "Out of resources. Could not register unit 0x%016Lx " | ||
| 1288 | "on port 0x%016Lx with SCSI stack.\n", | ||
| 1289 | unit->fcp_lun, unit->port->wwpn); | ||
| 1290 | return; | ||
| 1291 | } | ||
| 1292 | 543 | ||
| 1293 | zfcp_unit_get(unit); | 544 | list_for_each_entry(unit, &port->unit_list_head, list) |
| 1294 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | 545 | _zfcp_erp_unit_reopen(unit, clear, id, ref); |
| 1295 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); | ||
| 1296 | p->unit = unit; | ||
| 1297 | schedule_work(&p->work); | ||
| 1298 | } | 546 | } |
| 1299 | 547 | ||
| 1300 | /* | 548 | static void zfcp_erp_strategy_followup_actions(struct zfcp_erp_action *act) |
| 1301 | * function: | ||
| 1302 | * | ||
| 1303 | * purpose: remaining things in good cases, | ||
| 1304 | * escalation in bad cases | ||
| 1305 | * | ||
| 1306 | * returns: | ||
| 1307 | */ | ||
| 1308 | static int | ||
| 1309 | zfcp_erp_strategy_followup_actions(int action, | ||
| 1310 | struct zfcp_adapter *adapter, | ||
| 1311 | struct zfcp_port *port, | ||
| 1312 | struct zfcp_unit *unit, int status) | ||
| 1313 | { | 549 | { |
| 550 | struct zfcp_adapter *adapter = act->adapter; | ||
| 551 | struct zfcp_port *port = act->port; | ||
| 552 | struct zfcp_unit *unit = act->unit; | ||
| 553 | u32 status = act->status; | ||
| 554 | |||
| 1314 | /* initiate follow-up actions depending on success of finished action */ | 555 | /* initiate follow-up actions depending on success of finished action */ |
| 1315 | switch (action) { | 556 | switch (act->action) { |
| 1316 | 557 | ||
| 1317 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 558 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
| 1318 | if (status == ZFCP_ERP_SUCCEEDED) | 559 | if (status == ZFCP_ERP_SUCCEEDED) |
| 1319 | zfcp_erp_port_reopen_all_internal(adapter, 0, 70, NULL); | 560 | _zfcp_erp_port_reopen_all(adapter, 0, 70, NULL); |
| 1320 | else | 561 | else |
| 1321 | zfcp_erp_adapter_reopen_internal(adapter, 0, 71, NULL); | 562 | _zfcp_erp_adapter_reopen(adapter, 0, 71, NULL); |
| 1322 | break; | 563 | break; |
| 1323 | 564 | ||
| 1324 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 565 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 1325 | if (status == ZFCP_ERP_SUCCEEDED) | 566 | if (status == ZFCP_ERP_SUCCEEDED) |
| 1326 | zfcp_erp_port_reopen_internal(port, 0, 72, NULL); | 567 | _zfcp_erp_port_reopen(port, 0, 72, NULL); |
| 1327 | else | 568 | else |
| 1328 | zfcp_erp_adapter_reopen_internal(adapter, 0, 73, NULL); | 569 | _zfcp_erp_adapter_reopen(adapter, 0, 73, NULL); |
| 1329 | break; | 570 | break; |
| 1330 | 571 | ||
| 1331 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 572 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 1332 | if (status == ZFCP_ERP_SUCCEEDED) | 573 | if (status == ZFCP_ERP_SUCCEEDED) |
| 1333 | zfcp_erp_unit_reopen_all_internal(port, 0, 74, NULL); | 574 | _zfcp_erp_unit_reopen_all(port, 0, 74, NULL); |
| 1334 | else | 575 | else |
| 1335 | zfcp_erp_port_forced_reopen_internal(port, 0, 75, NULL); | 576 | _zfcp_erp_port_forced_reopen(port, 0, 75, NULL); |
| 1336 | break; | 577 | break; |
| 1337 | 578 | ||
| 1338 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 579 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
| 1339 | /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */ | ||
| 1340 | if (status != ZFCP_ERP_SUCCEEDED) | 580 | if (status != ZFCP_ERP_SUCCEEDED) |
| 1341 | zfcp_erp_port_reopen_internal(unit->port, 0, 76, NULL); | 581 | _zfcp_erp_port_reopen(unit->port, 0, 76, NULL); |
| 1342 | break; | 582 | break; |
| 1343 | } | 583 | } |
| 1344 | |||
| 1345 | return 0; | ||
| 1346 | } | 584 | } |
| 1347 | 585 | ||
| 1348 | static int | 586 | static void zfcp_erp_wakeup(struct zfcp_adapter *adapter) |
| 1349 | zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter) | ||
| 1350 | { | 587 | { |
| 1351 | unsigned long flags; | 588 | unsigned long flags; |
| 1352 | 589 | ||
| @@ -1360,1104 +597,622 @@ zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter) | |||
| 1360 | } | 597 | } |
| 1361 | read_unlock(&adapter->erp_lock); | 598 | read_unlock(&adapter->erp_lock); |
| 1362 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 599 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
| 1363 | |||
| 1364 | return 0; | ||
| 1365 | } | 600 | } |
| 1366 | 601 | ||
| 1367 | /** | 602 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) |
| 1368 | * zfcp_erp_wait - wait for completion of error recovery on an adapter | ||
| 1369 | * @adapter: adapter for which to wait for completion of its error recovery | ||
| 1370 | * Return: 0 | ||
| 1371 | */ | ||
| 1372 | int | ||
| 1373 | zfcp_erp_wait(struct zfcp_adapter *adapter) | ||
| 1374 | { | 603 | { |
| 1375 | int retval = 0; | 604 | if (zfcp_qdio_open(act->adapter)) |
| 1376 | 605 | return ZFCP_ERP_FAILED; | |
| 1377 | wait_event(adapter->erp_done_wqh, | 606 | init_waitqueue_head(&act->adapter->request_wq); |
| 1378 | !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | 607 | atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status); |
| 1379 | &adapter->status)); | 608 | return ZFCP_ERP_SUCCEEDED; |
| 1380 | |||
| 1381 | return retval; | ||
| 1382 | } | 609 | } |
| 1383 | 610 | ||
| 1384 | void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id, | 611 | static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) |
| 1385 | void *ref, u32 mask, int set_or_clear) | ||
| 1386 | { | 612 | { |
| 1387 | struct zfcp_port *port; | 613 | struct zfcp_port *port; |
| 1388 | u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS; | 614 | port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0, |
| 1389 | 615 | adapter->peer_d_id); | |
| 1390 | if (set_or_clear == ZFCP_SET) { | 616 | if (IS_ERR(port)) /* error or port already attached */ |
| 1391 | changed = atomic_test_and_set_mask(mask, &adapter->status); | 617 | return; |
| 1392 | } else { | 618 | _zfcp_erp_port_reopen(port, 0, 150, NULL); |
| 1393 | changed = atomic_test_and_clear_mask(mask, &adapter->status); | ||
| 1394 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
| 1395 | atomic_set(&adapter->erp_counter, 0); | ||
| 1396 | } | ||
| 1397 | if (changed) | ||
| 1398 | zfcp_rec_dbf_event_adapter(id, ref, adapter); | ||
| 1399 | |||
| 1400 | /* Deal with all underlying devices, only pass common_mask */ | ||
| 1401 | if (common_mask) | ||
| 1402 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
| 1403 | zfcp_erp_modify_port_status(port, id, ref, common_mask, | ||
| 1404 | set_or_clear); | ||
| 1405 | } | 619 | } |
| 1406 | 620 | ||
| 1407 | /* | 621 | static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) |
| 1408 | * function: zfcp_erp_modify_port_status | ||
| 1409 | * | ||
| 1410 | * purpose: sets the port and all underlying devices to ERP_FAILED | ||
| 1411 | * | ||
| 1412 | */ | ||
| 1413 | void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref, | ||
| 1414 | u32 mask, int set_or_clear) | ||
| 1415 | { | 622 | { |
| 1416 | struct zfcp_unit *unit; | 623 | int retries; |
| 1417 | u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS; | 624 | int sleep = 1; |
| 1418 | 625 | struct zfcp_adapter *adapter = erp_action->adapter; | |
| 1419 | if (set_or_clear == ZFCP_SET) { | ||
| 1420 | changed = atomic_test_and_set_mask(mask, &port->status); | ||
| 1421 | } else { | ||
| 1422 | changed = atomic_test_and_clear_mask(mask, &port->status); | ||
| 1423 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
| 1424 | atomic_set(&port->erp_counter, 0); | ||
| 1425 | } | ||
| 1426 | if (changed) | ||
| 1427 | zfcp_rec_dbf_event_port(id, ref, port); | ||
| 1428 | |||
| 1429 | /* Modify status of all underlying devices, only pass common mask */ | ||
| 1430 | if (common_mask) | ||
| 1431 | list_for_each_entry(unit, &port->unit_list_head, list) | ||
| 1432 | zfcp_erp_modify_unit_status(unit, id, ref, common_mask, | ||
| 1433 | set_or_clear); | ||
| 1434 | } | ||
| 1435 | 626 | ||
| 1436 | /* | 627 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); |
| 1437 | * function: zfcp_erp_modify_unit_status | ||
| 1438 | * | ||
| 1439 | * purpose: sets the unit to ERP_FAILED | ||
| 1440 | * | ||
| 1441 | */ | ||
| 1442 | void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref, | ||
| 1443 | u32 mask, int set_or_clear) | ||
| 1444 | { | ||
| 1445 | u32 changed; | ||
| 1446 | 628 | ||
| 1447 | if (set_or_clear == ZFCP_SET) { | 629 | for (retries = 7; retries; retries--) { |
| 1448 | changed = atomic_test_and_set_mask(mask, &unit->status); | 630 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, |
| 1449 | } else { | 631 | &adapter->status); |
| 1450 | changed = atomic_test_and_clear_mask(mask, &unit->status); | 632 | write_lock_irq(&adapter->erp_lock); |
| 1451 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) { | 633 | zfcp_erp_action_to_running(erp_action); |
| 1452 | atomic_set(&unit->erp_counter, 0); | 634 | write_unlock_irq(&adapter->erp_lock); |
| 635 | if (zfcp_fsf_exchange_config_data(erp_action)) { | ||
| 636 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | ||
| 637 | &adapter->status); | ||
| 638 | return ZFCP_ERP_FAILED; | ||
| 1453 | } | 639 | } |
| 1454 | } | ||
| 1455 | if (changed) | ||
| 1456 | zfcp_rec_dbf_event_unit(id, ref, unit); | ||
| 1457 | } | ||
| 1458 | 640 | ||
| 1459 | /* | 641 | zfcp_rec_dbf_event_thread_lock(6, adapter); |
| 1460 | * function: | 642 | down(&adapter->erp_ready_sem); |
| 1461 | * | 643 | zfcp_rec_dbf_event_thread_lock(7, adapter); |
| 1462 | * purpose: Wrappper for zfcp_erp_port_reopen_all_internal | 644 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) |
| 1463 | * used to ensure the correct locking | 645 | break; |
| 1464 | * | ||
| 1465 | * returns: 0 - initiated action successfully | ||
| 1466 | * <0 - failed to initiate action | ||
| 1467 | */ | ||
| 1468 | int zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask, | ||
| 1469 | u8 id, void *ref) | ||
| 1470 | { | ||
| 1471 | int retval; | ||
| 1472 | unsigned long flags; | ||
| 1473 | |||
| 1474 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
| 1475 | write_lock(&adapter->erp_lock); | ||
| 1476 | retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask, id, | ||
| 1477 | ref); | ||
| 1478 | write_unlock(&adapter->erp_lock); | ||
| 1479 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 1480 | |||
| 1481 | return retval; | ||
| 1482 | } | ||
| 1483 | 646 | ||
| 1484 | static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, | 647 | if (!(atomic_read(&adapter->status) & |
| 1485 | int clear_mask, u8 id, void *ref) | 648 | ZFCP_STATUS_ADAPTER_HOST_CON_INIT)) |
| 1486 | { | 649 | break; |
| 1487 | int retval = 0; | ||
| 1488 | struct zfcp_port *port; | ||
| 1489 | 650 | ||
| 1490 | list_for_each_entry(port, &adapter->port_list_head, list) | 651 | ssleep(sleep); |
| 1491 | if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) | 652 | sleep *= 2; |
| 1492 | zfcp_erp_port_reopen_internal(port, clear_mask, id, | 653 | } |
| 1493 | ref); | ||
| 1494 | 654 | ||
| 1495 | return retval; | 655 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, |
| 1496 | } | 656 | &adapter->status); |
| 1497 | 657 | ||
| 1498 | /* | 658 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK)) |
| 1499 | * function: | 659 | return ZFCP_ERP_FAILED; |
| 1500 | * | ||
| 1501 | * purpose: | ||
| 1502 | * | ||
| 1503 | * returns: FIXME | ||
| 1504 | */ | ||
| 1505 | static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, | ||
| 1506 | int clear_mask, u8 id, void *ref) | ||
| 1507 | { | ||
| 1508 | int retval = 0; | ||
| 1509 | struct zfcp_unit *unit; | ||
| 1510 | 660 | ||
| 1511 | list_for_each_entry(unit, &port->unit_list_head, list) | 661 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) |
| 1512 | zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref); | 662 | zfcp_erp_enqueue_ptp_port(adapter); |
| 1513 | 663 | ||
| 1514 | return retval; | 664 | return ZFCP_ERP_SUCCEEDED; |
| 1515 | } | 665 | } |
| 1516 | 666 | ||
| 1517 | /* | 667 | static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) |
| 1518 | * function: | ||
| 1519 | * | ||
| 1520 | * purpose: this routine executes the 'Reopen Adapter' action | ||
| 1521 | * (the entire action is processed synchronously, since | ||
| 1522 | * there are no actions which might be run concurrently | ||
| 1523 | * per definition) | ||
| 1524 | * | ||
| 1525 | * returns: ZFCP_ERP_SUCCEEDED - action finished successfully | ||
| 1526 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 1527 | */ | ||
| 1528 | static int | ||
| 1529 | zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action) | ||
| 1530 | { | 668 | { |
| 1531 | int retval; | 669 | int ret; |
| 1532 | 670 | struct zfcp_adapter *adapter = act->adapter; | |
| 1533 | retval = zfcp_erp_adapter_strategy_close(erp_action); | ||
| 1534 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | ||
| 1535 | retval = ZFCP_ERP_EXIT; | ||
| 1536 | else | ||
| 1537 | retval = zfcp_erp_adapter_strategy_open(erp_action); | ||
| 1538 | 671 | ||
| 1539 | if (retval == ZFCP_ERP_FAILED) | 672 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); |
| 1540 | ssleep(ZFCP_TYPE2_RECOVERY_TIME); | ||
| 1541 | 673 | ||
| 1542 | return retval; | 674 | write_lock_irq(&adapter->erp_lock); |
| 1543 | } | 675 | zfcp_erp_action_to_running(act); |
| 676 | write_unlock_irq(&adapter->erp_lock); | ||
| 1544 | 677 | ||
| 1545 | /* | 678 | ret = zfcp_fsf_exchange_port_data(act); |
| 1546 | * function: | 679 | if (ret == -EOPNOTSUPP) |
| 1547 | * | 680 | return ZFCP_ERP_SUCCEEDED; |
| 1548 | * purpose: | 681 | if (ret) |
| 1549 | * | 682 | return ZFCP_ERP_FAILED; |
| 1550 | * returns: ZFCP_ERP_SUCCEEDED - action finished successfully | ||
| 1551 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 1552 | */ | ||
| 1553 | static int | ||
| 1554 | zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *erp_action) | ||
| 1555 | { | ||
| 1556 | int retval; | ||
| 1557 | 683 | ||
| 1558 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, | 684 | zfcp_rec_dbf_event_thread_lock(8, adapter); |
| 1559 | &erp_action->adapter->status); | 685 | down(&adapter->erp_ready_sem); |
| 1560 | retval = zfcp_erp_adapter_strategy_generic(erp_action, 1); | 686 | zfcp_rec_dbf_event_thread_lock(9, adapter); |
| 1561 | atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, | 687 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
| 1562 | &erp_action->adapter->status); | 688 | return ZFCP_ERP_FAILED; |
| 1563 | 689 | ||
| 1564 | return retval; | 690 | return ZFCP_ERP_SUCCEEDED; |
| 1565 | } | 691 | } |
| 1566 | 692 | ||
| 1567 | /* | 693 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act) |
| 1568 | * function: | ||
| 1569 | * | ||
| 1570 | * purpose: | ||
| 1571 | * | ||
| 1572 | * returns: ZFCP_ERP_SUCCEEDED - action finished successfully | ||
| 1573 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 1574 | */ | ||
| 1575 | static int | ||
| 1576 | zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *erp_action) | ||
| 1577 | { | 694 | { |
| 1578 | int retval; | 695 | if (zfcp_erp_adapter_strat_fsf_xconf(act) == ZFCP_ERP_FAILED) |
| 696 | return ZFCP_ERP_FAILED; | ||
| 1579 | 697 | ||
| 1580 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, | 698 | if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED) |
| 1581 | &erp_action->adapter->status); | 699 | return ZFCP_ERP_FAILED; |
| 1582 | retval = zfcp_erp_adapter_strategy_generic(erp_action, 0); | ||
| 1583 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, | ||
| 1584 | &erp_action->adapter->status); | ||
| 1585 | 700 | ||
| 1586 | return retval; | 701 | atomic_set(&act->adapter->stat_miss, 16); |
| 702 | if (zfcp_status_read_refill(act->adapter)) | ||
| 703 | return ZFCP_ERP_FAILED; | ||
| 704 | |||
| 705 | return ZFCP_ERP_SUCCEEDED; | ||
| 1587 | } | 706 | } |
| 1588 | 707 | ||
| 1589 | /* | 708 | static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act, |
| 1590 | * function: zfcp_register_adapter | 709 | int close) |
| 1591 | * | ||
| 1592 | * purpose: allocate the irq associated with this devno and register | ||
| 1593 | * the FSF adapter with the SCSI stack | ||
| 1594 | * | ||
| 1595 | * returns: | ||
| 1596 | */ | ||
| 1597 | static int | ||
| 1598 | zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close) | ||
| 1599 | { | 710 | { |
| 1600 | int retval = ZFCP_ERP_SUCCEEDED; | 711 | int retval = ZFCP_ERP_SUCCEEDED; |
| 712 | struct zfcp_adapter *adapter = act->adapter; | ||
| 1601 | 713 | ||
| 1602 | if (close) | 714 | if (close) |
| 1603 | goto close_only; | 715 | goto close_only; |
| 1604 | 716 | ||
| 1605 | retval = zfcp_erp_adapter_strategy_open_qdio(erp_action); | 717 | retval = zfcp_erp_adapter_strategy_open_qdio(act); |
| 1606 | if (retval != ZFCP_ERP_SUCCEEDED) | 718 | if (retval != ZFCP_ERP_SUCCEEDED) |
| 1607 | goto failed_qdio; | 719 | goto failed_qdio; |
| 1608 | 720 | ||
| 1609 | retval = zfcp_erp_adapter_strategy_open_fsf(erp_action); | 721 | retval = zfcp_erp_adapter_strategy_open_fsf(act); |
| 1610 | if (retval != ZFCP_ERP_SUCCEEDED) | 722 | if (retval != ZFCP_ERP_SUCCEEDED) |
| 1611 | goto failed_openfcp; | 723 | goto failed_openfcp; |
| 1612 | 724 | ||
| 1613 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &erp_action->adapter->status); | 725 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &act->adapter->status); |
| 1614 | schedule_work(&erp_action->adapter->scan_work); | 726 | schedule_work(&act->adapter->scan_work); |
| 1615 | goto out; | 727 | |
| 728 | return ZFCP_ERP_SUCCEEDED; | ||
| 1616 | 729 | ||
| 1617 | close_only: | 730 | close_only: |
| 1618 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, | 731 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, |
| 1619 | &erp_action->adapter->status); | 732 | &act->adapter->status); |
| 1620 | 733 | ||
| 1621 | failed_openfcp: | 734 | failed_openfcp: |
| 1622 | zfcp_close_fsf(erp_action->adapter); | 735 | /* close queues to ensure that buffers are not accessed by adapter */ |
| 736 | zfcp_qdio_close(adapter); | ||
| 737 | zfcp_fsf_req_dismiss_all(adapter); | ||
| 738 | adapter->fsf_req_seq_no = 0; | ||
| 739 | /* all ports and units are closed */ | ||
| 740 | zfcp_erp_modify_adapter_status(adapter, 24, NULL, | ||
| 741 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | ||
| 1623 | failed_qdio: | 742 | failed_qdio: |
| 1624 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | | 743 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | |
| 1625 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 744 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | |
| 1626 | ZFCP_STATUS_ADAPTER_XPORT_OK, | 745 | ZFCP_STATUS_ADAPTER_XPORT_OK, |
| 1627 | &erp_action->adapter->status); | 746 | &act->adapter->status); |
| 1628 | out: | ||
| 1629 | return retval; | 747 | return retval; |
| 1630 | } | 748 | } |
| 1631 | 749 | ||
| 1632 | /* | 750 | static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act) |
| 1633 | * function: zfcp_qdio_init | ||
| 1634 | * | ||
| 1635 | * purpose: setup QDIO operation for specified adapter | ||
| 1636 | * | ||
| 1637 | * returns: 0 - successful setup | ||
| 1638 | * !0 - failed setup | ||
| 1639 | */ | ||
| 1640 | static int | ||
| 1641 | zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) | ||
| 1642 | { | 751 | { |
| 1643 | struct zfcp_adapter *adapter = erp_action->adapter; | 752 | int retval; |
| 1644 | 753 | ||
| 1645 | if (zfcp_qdio_open(adapter)) | 754 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status); |
| 1646 | return ZFCP_ERP_FAILED; | 755 | zfcp_erp_adapter_strategy_generic(act, 1); /* close */ |
| 756 | atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status); | ||
| 757 | if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | ||
| 758 | return ZFCP_ERP_EXIT; | ||
| 1647 | 759 | ||
| 1648 | /* initialize waitqueue used to wait for free SBALs in requests queue */ | 760 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status); |
| 1649 | init_waitqueue_head(&adapter->request_wq); | 761 | retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */ |
| 762 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status); | ||
| 1650 | 763 | ||
| 1651 | /* ok, we did it - skip all cleanups for different failures */ | 764 | if (retval == ZFCP_ERP_FAILED) |
| 1652 | atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); | 765 | ssleep(8); |
| 1653 | return ZFCP_ERP_SUCCEEDED; | ||
| 1654 | } | ||
| 1655 | 766 | ||
| 767 | return retval; | ||
| 768 | } | ||
| 1656 | 769 | ||
| 1657 | static int | 770 | static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act) |
| 1658 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) | ||
| 1659 | { | 771 | { |
| 1660 | int retval; | 772 | int retval; |
| 1661 | 773 | ||
| 1662 | retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); | 774 | retval = zfcp_fsf_close_physical_port(act); |
| 1663 | if (retval == ZFCP_ERP_FAILED) | 775 | if (retval == -ENOMEM) |
| 1664 | return ZFCP_ERP_FAILED; | 776 | return ZFCP_ERP_NOMEM; |
| 1665 | 777 | act->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING; | |
| 1666 | retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | 778 | if (retval) |
| 1667 | if (retval == ZFCP_ERP_FAILED) | ||
| 1668 | return ZFCP_ERP_FAILED; | 779 | return ZFCP_ERP_FAILED; |
| 1669 | 780 | ||
| 1670 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); | 781 | return ZFCP_ERP_CONTINUES; |
| 1671 | } | 782 | } |
| 1672 | 783 | ||
| 1673 | static void zfcp_erp_open_ptp_port(struct zfcp_adapter *adapter) | 784 | static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) |
| 1674 | { | 785 | { |
| 1675 | struct zfcp_port *port; | 786 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | |
| 1676 | port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0, | 787 | ZFCP_STATUS_COMMON_CLOSING | |
| 1677 | adapter->peer_d_id); | 788 | ZFCP_STATUS_COMMON_ACCESS_DENIED | |
| 1678 | if (IS_ERR(port)) /* error or port already attached */ | 789 | ZFCP_STATUS_PORT_DID_DID | |
| 1679 | return; | 790 | ZFCP_STATUS_PORT_PHYS_CLOSING | |
| 1680 | zfcp_erp_port_reopen_internal(port, 0, 150, NULL); | 791 | ZFCP_STATUS_PORT_INVALID_WWPN, |
| 792 | &port->status); | ||
| 1681 | } | 793 | } |
| 1682 | 794 | ||
| 1683 | static int | 795 | static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action) |
| 1684 | zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | ||
| 1685 | { | 796 | { |
| 1686 | int retries; | 797 | struct zfcp_port *port = erp_action->port; |
| 1687 | int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP; | 798 | int status = atomic_read(&port->status); |
| 1688 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
| 1689 | |||
| 1690 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); | ||
| 1691 | 799 | ||
| 1692 | for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) { | 800 | switch (erp_action->step) { |
| 1693 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | 801 | case ZFCP_ERP_STEP_UNINITIALIZED: |
| 1694 | &adapter->status); | 802 | zfcp_erp_port_strategy_clearstati(port); |
| 1695 | write_lock_irq(&adapter->erp_lock); | 803 | if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) && |
| 1696 | zfcp_erp_action_to_running(erp_action); | 804 | (status & ZFCP_STATUS_COMMON_OPEN)) |
| 1697 | write_unlock_irq(&adapter->erp_lock); | 805 | return zfcp_erp_port_forced_strategy_close(erp_action); |
| 1698 | if (zfcp_fsf_exchange_config_data(erp_action)) { | 806 | else |
| 1699 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | ||
| 1700 | &adapter->status); | ||
| 1701 | return ZFCP_ERP_FAILED; | 807 | return ZFCP_ERP_FAILED; |
| 1702 | } | ||
| 1703 | |||
| 1704 | /* | ||
| 1705 | * Why this works: | ||
| 1706 | * Both the normal completion handler as well as the timeout | ||
| 1707 | * handler will do an 'up' when the 'exchange config data' | ||
| 1708 | * request completes or times out. Thus, the signal to go on | ||
| 1709 | * won't be lost utilizing this semaphore. | ||
| 1710 | * Furthermore, this 'adapter_reopen' action is | ||
| 1711 | * guaranteed to be the only action being there (highest action | ||
| 1712 | * which prevents other actions from being created). | ||
| 1713 | * Resulting from that, the wake signal recognized here | ||
| 1714 | * _must_ be the one belonging to the 'exchange config | ||
| 1715 | * data' request. | ||
| 1716 | */ | ||
| 1717 | zfcp_rec_dbf_event_thread_lock(6, adapter); | ||
| 1718 | down(&adapter->erp_ready_sem); | ||
| 1719 | zfcp_rec_dbf_event_thread_lock(7, adapter); | ||
| 1720 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) | ||
| 1721 | break; | ||
| 1722 | |||
| 1723 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | ||
| 1724 | &adapter->status)) | ||
| 1725 | break; | ||
| 1726 | 808 | ||
| 1727 | /* sleep a little bit before retry */ | 809 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: |
| 1728 | ssleep(sleep); | 810 | if (status & ZFCP_STATUS_PORT_PHYS_OPEN) |
| 1729 | sleep *= 2; | 811 | return ZFCP_ERP_SUCCEEDED; |
| 1730 | } | 812 | } |
| 1731 | 813 | return ZFCP_ERP_FAILED; | |
| 1732 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | ||
| 1733 | &adapter->status); | ||
| 1734 | |||
| 1735 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, | ||
| 1736 | &adapter->status)) | ||
| 1737 | return ZFCP_ERP_FAILED; | ||
| 1738 | |||
| 1739 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) | ||
| 1740 | zfcp_erp_open_ptp_port(adapter); | ||
| 1741 | |||
| 1742 | return ZFCP_ERP_SUCCEEDED; | ||
| 1743 | } | 814 | } |
| 1744 | 815 | ||
| 1745 | static int | 816 | static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action) |
| 1746 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | ||
| 1747 | { | 817 | { |
| 1748 | int ret; | 818 | int retval; |
| 1749 | struct zfcp_adapter *adapter; | ||
| 1750 | |||
| 1751 | adapter = erp_action->adapter; | ||
| 1752 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
| 1753 | |||
| 1754 | write_lock_irq(&adapter->erp_lock); | ||
| 1755 | zfcp_erp_action_to_running(erp_action); | ||
| 1756 | write_unlock_irq(&adapter->erp_lock); | ||
| 1757 | 819 | ||
| 1758 | ret = zfcp_fsf_exchange_port_data(erp_action); | 820 | retval = zfcp_fsf_close_port(erp_action); |
| 1759 | if (ret == -EOPNOTSUPP) { | 821 | if (retval == -ENOMEM) |
| 1760 | return ZFCP_ERP_SUCCEEDED; | 822 | return ZFCP_ERP_NOMEM; |
| 1761 | } else if (ret) { | 823 | erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING; |
| 824 | if (retval) | ||
| 1762 | return ZFCP_ERP_FAILED; | 825 | return ZFCP_ERP_FAILED; |
| 1763 | } | 826 | return ZFCP_ERP_CONTINUES; |
| 1764 | |||
| 1765 | ret = ZFCP_ERP_SUCCEEDED; | ||
| 1766 | zfcp_rec_dbf_event_thread_lock(8, adapter); | ||
| 1767 | down(&adapter->erp_ready_sem); | ||
| 1768 | zfcp_rec_dbf_event_thread_lock(9, adapter); | ||
| 1769 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) | ||
| 1770 | ret = ZFCP_ERP_FAILED; | ||
| 1771 | |||
| 1772 | return ret; | ||
| 1773 | } | 827 | } |
| 1774 | 828 | ||
| 1775 | static int | 829 | static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) |
| 1776 | zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action | ||
| 1777 | *erp_action) | ||
| 1778 | { | 830 | { |
| 1779 | struct zfcp_adapter *adapter = erp_action->adapter; | 831 | int retval; |
| 1780 | 832 | ||
| 1781 | atomic_set(&adapter->stat_miss, 16); | 833 | retval = zfcp_fsf_open_port(erp_action); |
| 1782 | return zfcp_status_read_refill(adapter); | 834 | if (retval == -ENOMEM) |
| 835 | return ZFCP_ERP_NOMEM; | ||
| 836 | erp_action->step = ZFCP_ERP_STEP_PORT_OPENING; | ||
| 837 | if (retval) | ||
| 838 | return ZFCP_ERP_FAILED; | ||
| 839 | return ZFCP_ERP_CONTINUES; | ||
| 1783 | } | 840 | } |
| 1784 | 841 | ||
| 1785 | /* | 842 | static void zfcp_erp_port_strategy_open_ns_wake(struct zfcp_erp_action *ns_act) |
| 1786 | * function: | ||
| 1787 | * | ||
| 1788 | * purpose: this routine executes the 'Reopen Physical Port' action | ||
| 1789 | * | ||
| 1790 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 1791 | * ZFCP_ERP_SUCCEEDED - action finished successfully | ||
| 1792 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 1793 | */ | ||
| 1794 | static int | ||
| 1795 | zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action) | ||
| 1796 | { | 843 | { |
| 1797 | int retval = ZFCP_ERP_FAILED; | 844 | unsigned long flags; |
| 1798 | struct zfcp_port *port = erp_action->port; | 845 | struct zfcp_adapter *adapter = ns_act->adapter; |
| 1799 | 846 | struct zfcp_erp_action *act, *tmp; | |
| 1800 | switch (erp_action->step) { | 847 | int status; |
| 1801 | |||
| 1802 | /* | ||
| 1803 | * FIXME: | ||
| 1804 | * the ULP spec. begs for waiting for oustanding commands | ||
| 1805 | */ | ||
| 1806 | case ZFCP_ERP_STEP_UNINITIALIZED: | ||
| 1807 | zfcp_erp_port_strategy_clearstati(port); | ||
| 1808 | /* | ||
| 1809 | * it would be sufficient to test only the normal open flag | ||
| 1810 | * since the phys. open flag cannot be set if the normal | ||
| 1811 | * open flag is unset - however, this is for readabilty ... | ||
| 1812 | */ | ||
| 1813 | if (atomic_test_mask((ZFCP_STATUS_PORT_PHYS_OPEN | | ||
| 1814 | ZFCP_STATUS_COMMON_OPEN), | ||
| 1815 | &port->status)) { | ||
| 1816 | retval = | ||
| 1817 | zfcp_erp_port_forced_strategy_close(erp_action); | ||
| 1818 | } else | ||
| 1819 | retval = ZFCP_ERP_FAILED; | ||
| 1820 | break; | ||
| 1821 | 848 | ||
| 1822 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | 849 | read_lock_irqsave(&adapter->erp_lock, flags); |
| 1823 | if (atomic_test_mask(ZFCP_STATUS_PORT_PHYS_OPEN, | 850 | list_for_each_entry_safe(act, tmp, &adapter->erp_running_head, list) { |
| 1824 | &port->status)) { | 851 | if (act->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) { |
| 1825 | retval = ZFCP_ERP_FAILED; | 852 | status = atomic_read(&adapter->nameserver_port->status); |
| 1826 | } else | 853 | if (status & ZFCP_STATUS_COMMON_ERP_FAILED) |
| 1827 | retval = ZFCP_ERP_SUCCEEDED; | 854 | zfcp_erp_port_failed(act->port, 27, NULL); |
| 1828 | break; | 855 | zfcp_erp_action_ready(act); |
| 856 | } | ||
| 1829 | } | 857 | } |
| 1830 | 858 | read_unlock_irqrestore(&adapter->erp_lock, flags); | |
| 1831 | return retval; | ||
| 1832 | } | 859 | } |
| 1833 | 860 | ||
| 1834 | /* | 861 | static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *act) |
| 1835 | * function: | ||
| 1836 | * | ||
| 1837 | * purpose: this routine executes the 'Reopen Port' action | ||
| 1838 | * | ||
| 1839 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 1840 | * ZFCP_ERP_SUCCEEDED - action finished successfully | ||
| 1841 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 1842 | */ | ||
| 1843 | static int | ||
| 1844 | zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) | ||
| 1845 | { | 862 | { |
| 1846 | int retval = ZFCP_ERP_FAILED; | 863 | int retval; |
| 1847 | struct zfcp_port *port = erp_action->port; | ||
| 1848 | |||
| 1849 | switch (erp_action->step) { | ||
| 1850 | 864 | ||
| 1851 | /* | 865 | switch (act->step) { |
| 1852 | * FIXME: | ||
| 1853 | * the ULP spec. begs for waiting for oustanding commands | ||
| 1854 | */ | ||
| 1855 | case ZFCP_ERP_STEP_UNINITIALIZED: | 866 | case ZFCP_ERP_STEP_UNINITIALIZED: |
| 1856 | zfcp_erp_port_strategy_clearstati(port); | 867 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: |
| 1857 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) { | ||
| 1858 | retval = zfcp_erp_port_strategy_close(erp_action); | ||
| 1859 | goto out; | ||
| 1860 | } /* else it's already closed, open it */ | ||
| 1861 | break; | ||
| 1862 | |||
| 1863 | case ZFCP_ERP_STEP_PORT_CLOSING: | 868 | case ZFCP_ERP_STEP_PORT_CLOSING: |
| 1864 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) { | 869 | return zfcp_erp_port_strategy_open_port(act); |
| 870 | |||
| 871 | case ZFCP_ERP_STEP_PORT_OPENING: | ||
| 872 | if (atomic_read(&act->port->status) & ZFCP_STATUS_COMMON_OPEN) | ||
| 873 | retval = ZFCP_ERP_SUCCEEDED; | ||
| 874 | else | ||
| 1865 | retval = ZFCP_ERP_FAILED; | 875 | retval = ZFCP_ERP_FAILED; |
| 1866 | goto out; | 876 | /* this is needed anyway */ |
| 1867 | } /* else it's closed now, open it */ | 877 | zfcp_erp_port_strategy_open_ns_wake(act); |
| 1868 | break; | 878 | return retval; |
| 1869 | } | ||
| 1870 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | ||
| 1871 | retval = ZFCP_ERP_EXIT; | ||
| 1872 | else | ||
| 1873 | retval = zfcp_erp_port_strategy_open(erp_action); | ||
| 1874 | 879 | ||
| 1875 | out: | 880 | default: |
| 1876 | return retval; | 881 | return ZFCP_ERP_FAILED; |
| 882 | } | ||
| 1877 | } | 883 | } |
| 1878 | 884 | ||
| 1879 | static int | 885 | static int zfcp_erp_port_strategy_open_lookup(struct zfcp_erp_action *act) |
| 1880 | zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action) | ||
| 1881 | { | 886 | { |
| 1882 | int retval; | 887 | int retval; |
| 1883 | 888 | ||
| 1884 | if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, | 889 | retval = zfcp_fc_ns_gid_pn_request(act); |
| 1885 | &erp_action->port->status)) | 890 | if (retval == -ENOMEM) |
| 1886 | retval = zfcp_erp_port_strategy_open_nameserver(erp_action); | 891 | return ZFCP_ERP_NOMEM; |
| 1887 | else | 892 | act->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; |
| 1888 | retval = zfcp_erp_port_strategy_open_common(erp_action); | 893 | if (retval) |
| 1889 | 894 | return ZFCP_ERP_FAILED; | |
| 1890 | return retval; | 895 | return ZFCP_ERP_CONTINUES; |
| 1891 | } | 896 | } |
| 1892 | 897 | ||
| 1893 | static int | 898 | static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) |
| 1894 | zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) | ||
| 1895 | { | 899 | { |
| 1896 | int retval = 0; | 900 | struct zfcp_adapter *adapter = act->adapter; |
| 1897 | struct zfcp_adapter *adapter = erp_action->adapter; | 901 | struct zfcp_port *port = act->port; |
| 1898 | struct zfcp_port *port = erp_action->port; | ||
| 1899 | 902 | ||
| 1900 | switch (erp_action->step) { | 903 | if (port->wwpn != adapter->peer_wwpn) { |
| 904 | dev_err(&adapter->ccw_device->dev, | ||
| 905 | "Failed to open port 0x%016Lx, " | ||
| 906 | "Peer WWPN 0x%016Lx does not " | ||
| 907 | "match.\n", port->wwpn, | ||
| 908 | adapter->peer_wwpn); | ||
| 909 | zfcp_erp_port_failed(port, 25, NULL); | ||
| 910 | return ZFCP_ERP_FAILED; | ||
| 911 | } | ||
| 912 | port->d_id = adapter->peer_d_id; | ||
| 913 | atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); | ||
| 914 | return zfcp_erp_port_strategy_open_port(act); | ||
| 915 | } | ||
| 1901 | 916 | ||
| 917 | static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) | ||
| 918 | { | ||
| 919 | struct zfcp_adapter *adapter = act->adapter; | ||
| 920 | struct zfcp_port *port = act->port; | ||
| 921 | struct zfcp_port *ns_port = adapter->nameserver_port; | ||
| 922 | int p_status = atomic_read(&port->status); | ||
| 923 | |||
| 924 | switch (act->step) { | ||
| 1902 | case ZFCP_ERP_STEP_UNINITIALIZED: | 925 | case ZFCP_ERP_STEP_UNINITIALIZED: |
| 1903 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | 926 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: |
| 1904 | case ZFCP_ERP_STEP_PORT_CLOSING: | 927 | case ZFCP_ERP_STEP_PORT_CLOSING: |
| 1905 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) { | 928 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) |
| 1906 | if (port->wwpn != adapter->peer_wwpn) { | 929 | return zfcp_erp_open_ptp_port(act); |
| 1907 | dev_err(&adapter->ccw_device->dev, | 930 | if (!ns_port) { |
| 1908 | "Failed to open port 0x%016Lx, " | ||
| 1909 | "Peer WWPN 0x%016Lx does not match.\n", | ||
| 1910 | port->wwpn, adapter->peer_wwpn); | ||
| 1911 | zfcp_erp_port_failed(port, 25, NULL); | ||
| 1912 | retval = ZFCP_ERP_FAILED; | ||
| 1913 | break; | ||
| 1914 | } | ||
| 1915 | port->d_id = adapter->peer_d_id; | ||
| 1916 | atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); | ||
| 1917 | retval = zfcp_erp_port_strategy_open_port(erp_action); | ||
| 1918 | break; | ||
| 1919 | } | ||
| 1920 | |||
| 1921 | if (!adapter->nameserver_port) { | ||
| 1922 | dev_err(&adapter->ccw_device->dev, | 931 | dev_err(&adapter->ccw_device->dev, |
| 1923 | "Nameserver port unavailable.\n"); | 932 | "Nameserver port unavailable.\n"); |
| 1924 | retval = ZFCP_ERP_FAILED; | 933 | return ZFCP_ERP_FAILED; |
| 1925 | break; | ||
| 1926 | } | 934 | } |
| 1927 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | 935 | if (!(atomic_read(&ns_port->status) & |
| 1928 | &adapter->nameserver_port->status)) { | 936 | ZFCP_STATUS_COMMON_UNBLOCKED)) { |
| 1929 | /* nameserver port may live again */ | 937 | /* nameserver port may live again */ |
| 1930 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, | 938 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, |
| 1931 | &adapter->nameserver_port->status); | 939 | &ns_port->status); |
| 1932 | if (zfcp_erp_port_reopen(adapter->nameserver_port, 0, | 940 | if (zfcp_erp_port_reopen(ns_port, 0, 77, act) >= 0) { |
| 1933 | 77, erp_action) >= 0) { | 941 | act->step = ZFCP_ERP_STEP_NAMESERVER_OPEN; |
| 1934 | erp_action->step = | 942 | return ZFCP_ERP_CONTINUES; |
| 1935 | ZFCP_ERP_STEP_NAMESERVER_OPEN; | 943 | } |
| 1936 | retval = ZFCP_ERP_CONTINUES; | 944 | return ZFCP_ERP_FAILED; |
| 1937 | } else | ||
| 1938 | retval = ZFCP_ERP_FAILED; | ||
| 1939 | break; | ||
| 1940 | } | 945 | } |
| 1941 | /* else nameserver port is already open, fall through */ | 946 | /* else nameserver port is already open, fall through */ |
| 1942 | case ZFCP_ERP_STEP_NAMESERVER_OPEN: | 947 | case ZFCP_ERP_STEP_NAMESERVER_OPEN: |
| 1943 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, | 948 | if (!(atomic_read(&ns_port->status) & ZFCP_STATUS_COMMON_OPEN)) |
| 1944 | &adapter->nameserver_port->status)) | 949 | return ZFCP_ERP_FAILED; |
| 1945 | retval = ZFCP_ERP_FAILED; | 950 | return zfcp_erp_port_strategy_open_lookup(act); |
| 1946 | else | ||
| 1947 | retval = zfcp_erp_port_strategy_open_common_lookup | ||
| 1948 | (erp_action); | ||
| 1949 | break; | ||
| 1950 | 951 | ||
| 1951 | case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: | 952 | case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: |
| 1952 | if (!atomic_test_mask(ZFCP_STATUS_PORT_DID_DID, &port->status)) { | 953 | if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { |
| 1953 | if (atomic_test_mask | 954 | if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { |
| 1954 | (ZFCP_STATUS_PORT_INVALID_WWPN, &port->status)) { | ||
| 1955 | zfcp_erp_port_failed(port, 26, NULL); | 955 | zfcp_erp_port_failed(port, 26, NULL); |
| 1956 | retval = ZFCP_ERP_EXIT; | 956 | return ZFCP_ERP_EXIT; |
| 1957 | } else | 957 | } |
| 1958 | retval = ZFCP_ERP_FAILED; | 958 | return ZFCP_ERP_FAILED; |
| 1959 | } else | 959 | } |
| 1960 | retval = zfcp_erp_port_strategy_open_port(erp_action); | 960 | return zfcp_erp_port_strategy_open_port(act); |
| 1961 | break; | ||
| 1962 | 961 | ||
| 1963 | case ZFCP_ERP_STEP_PORT_OPENING: | 962 | case ZFCP_ERP_STEP_PORT_OPENING: |
| 1964 | /* D_ID might have changed during open */ | 963 | /* D_ID might have changed during open */ |
| 1965 | if (atomic_test_mask((ZFCP_STATUS_COMMON_OPEN | | 964 | if ((p_status & ZFCP_STATUS_COMMON_OPEN) && |
| 1966 | ZFCP_STATUS_PORT_DID_DID), | 965 | (p_status & ZFCP_STATUS_PORT_DID_DID)) |
| 1967 | &port->status)) | 966 | return ZFCP_ERP_SUCCEEDED; |
| 1968 | retval = ZFCP_ERP_SUCCEEDED; | 967 | /* fall through otherwise */ |
| 1969 | else | ||
| 1970 | retval = ZFCP_ERP_FAILED; | ||
| 1971 | break; | ||
| 1972 | |||
| 1973 | default: | ||
| 1974 | /* unknown erp step */ | ||
| 1975 | retval = ZFCP_ERP_FAILED; | ||
| 1976 | } | 968 | } |
| 969 | return ZFCP_ERP_FAILED; | ||
| 970 | } | ||
| 1977 | 971 | ||
| 1978 | return retval; | 972 | static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *act) |
| 973 | { | ||
| 974 | if (atomic_read(&act->port->status) & (ZFCP_STATUS_PORT_WKA)) | ||
| 975 | return zfcp_erp_port_strategy_open_nameserver(act); | ||
| 976 | return zfcp_erp_port_strategy_open_common(act); | ||
| 1979 | } | 977 | } |
| 1980 | 978 | ||
| 1981 | static int | 979 | static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) |
| 1982 | zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action) | ||
| 1983 | { | 980 | { |
| 1984 | int retval; | ||
| 1985 | struct zfcp_port *port = erp_action->port; | 981 | struct zfcp_port *port = erp_action->port; |
| 1986 | 982 | ||
| 1987 | switch (erp_action->step) { | 983 | switch (erp_action->step) { |
| 1988 | |||
| 1989 | case ZFCP_ERP_STEP_UNINITIALIZED: | 984 | case ZFCP_ERP_STEP_UNINITIALIZED: |
| 1990 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | 985 | zfcp_erp_port_strategy_clearstati(port); |
| 1991 | case ZFCP_ERP_STEP_PORT_CLOSING: | 986 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN) |
| 1992 | retval = zfcp_erp_port_strategy_open_port(erp_action); | 987 | return zfcp_erp_port_strategy_close(erp_action); |
| 1993 | break; | 988 | break; |
| 1994 | 989 | ||
| 1995 | case ZFCP_ERP_STEP_PORT_OPENING: | 990 | case ZFCP_ERP_STEP_PORT_CLOSING: |
| 1996 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) | 991 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN) |
| 1997 | retval = ZFCP_ERP_SUCCEEDED; | 992 | return ZFCP_ERP_FAILED; |
| 1998 | else | ||
| 1999 | retval = ZFCP_ERP_FAILED; | ||
| 2000 | /* this is needed anyway (dont care for retval of wakeup) */ | ||
| 2001 | zfcp_erp_port_strategy_open_nameserver_wakeup(erp_action); | ||
| 2002 | break; | 993 | break; |
| 2003 | |||
| 2004 | default: | ||
| 2005 | /* unknown erp step */ | ||
| 2006 | retval = ZFCP_ERP_FAILED; | ||
| 2007 | } | 994 | } |
| 995 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | ||
| 996 | return ZFCP_ERP_EXIT; | ||
| 997 | else | ||
| 998 | return zfcp_erp_port_strategy_open(erp_action); | ||
| 2008 | 999 | ||
| 2009 | return retval; | 1000 | return ZFCP_ERP_FAILED; |
| 2010 | } | ||
| 2011 | |||
| 2012 | /* | ||
| 2013 | * function: | ||
| 2014 | * | ||
| 2015 | * purpose: makes the erp thread continue with reopen (physical) port | ||
| 2016 | * actions which have been paused until the name server port | ||
| 2017 | * is opened (or failed) | ||
| 2018 | * | ||
| 2019 | * returns: 0 (a kind of void retval, its not used) | ||
| 2020 | */ | ||
| 2021 | static int | ||
| 2022 | zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action | ||
| 2023 | *ns_erp_action) | ||
| 2024 | { | ||
| 2025 | int retval = 0; | ||
| 2026 | unsigned long flags; | ||
| 2027 | struct zfcp_adapter *adapter = ns_erp_action->adapter; | ||
| 2028 | struct zfcp_erp_action *erp_action, *tmp; | ||
| 2029 | |||
| 2030 | read_lock_irqsave(&adapter->erp_lock, flags); | ||
| 2031 | list_for_each_entry_safe(erp_action, tmp, &adapter->erp_running_head, | ||
| 2032 | list) { | ||
| 2033 | if (erp_action->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) { | ||
| 2034 | if (atomic_test_mask( | ||
| 2035 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
| 2036 | &adapter->nameserver_port->status)) | ||
| 2037 | zfcp_erp_port_failed(erp_action->port, 27, | ||
| 2038 | NULL); | ||
| 2039 | zfcp_erp_action_ready(erp_action); | ||
| 2040 | } | ||
| 2041 | } | ||
| 2042 | read_unlock_irqrestore(&adapter->erp_lock, flags); | ||
| 2043 | |||
| 2044 | return retval; | ||
| 2045 | } | ||
| 2046 | |||
| 2047 | /* | ||
| 2048 | * function: | ||
| 2049 | * | ||
| 2050 | * purpose: | ||
| 2051 | * | ||
| 2052 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 2053 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 2054 | */ | ||
| 2055 | static int | ||
| 2056 | zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action) | ||
| 2057 | { | ||
| 2058 | int retval; | ||
| 2059 | |||
| 2060 | retval = zfcp_fsf_close_physical_port(erp_action); | ||
| 2061 | if (retval == -ENOMEM) { | ||
| 2062 | retval = ZFCP_ERP_NOMEM; | ||
| 2063 | goto out; | ||
| 2064 | } | ||
| 2065 | erp_action->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING; | ||
| 2066 | if (retval != 0) { | ||
| 2067 | /* could not send 'open', fail */ | ||
| 2068 | retval = ZFCP_ERP_FAILED; | ||
| 2069 | goto out; | ||
| 2070 | } | ||
| 2071 | retval = ZFCP_ERP_CONTINUES; | ||
| 2072 | out: | ||
| 2073 | return retval; | ||
| 2074 | } | 1001 | } |
| 2075 | 1002 | ||
| 2076 | static int | 1003 | static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) |
| 2077 | zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) | ||
| 2078 | { | 1004 | { |
| 2079 | int retval = 0; | ||
| 2080 | |||
| 2081 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | | 1005 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | |
| 2082 | ZFCP_STATUS_COMMON_CLOSING | | 1006 | ZFCP_STATUS_COMMON_CLOSING | |
| 2083 | ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1007 | ZFCP_STATUS_COMMON_ACCESS_DENIED | |
| 2084 | ZFCP_STATUS_PORT_DID_DID | | 1008 | ZFCP_STATUS_UNIT_SHARED | |
| 2085 | ZFCP_STATUS_PORT_PHYS_CLOSING | | 1009 | ZFCP_STATUS_UNIT_READONLY, |
| 2086 | ZFCP_STATUS_PORT_INVALID_WWPN, | 1010 | &unit->status); |
| 2087 | &port->status); | ||
| 2088 | return retval; | ||
| 2089 | } | ||
| 2090 | |||
| 2091 | /* | ||
| 2092 | * function: | ||
| 2093 | * | ||
| 2094 | * purpose: | ||
| 2095 | * | ||
| 2096 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 2097 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 2098 | */ | ||
| 2099 | static int | ||
| 2100 | zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action) | ||
| 2101 | { | ||
| 2102 | int retval; | ||
| 2103 | |||
| 2104 | retval = zfcp_fsf_close_port(erp_action); | ||
| 2105 | if (retval == -ENOMEM) { | ||
| 2106 | retval = ZFCP_ERP_NOMEM; | ||
| 2107 | goto out; | ||
| 2108 | } | ||
| 2109 | erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING; | ||
| 2110 | if (retval != 0) { | ||
| 2111 | /* could not send 'close', fail */ | ||
| 2112 | retval = ZFCP_ERP_FAILED; | ||
| 2113 | goto out; | ||
| 2114 | } | ||
| 2115 | retval = ZFCP_ERP_CONTINUES; | ||
| 2116 | out: | ||
| 2117 | return retval; | ||
| 2118 | } | 1011 | } |
| 2119 | 1012 | ||
| 2120 | /* | 1013 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) |
| 2121 | * function: | ||
| 2122 | * | ||
| 2123 | * purpose: | ||
| 2124 | * | ||
| 2125 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 2126 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 2127 | */ | ||
| 2128 | static int | ||
| 2129 | zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) | ||
| 2130 | { | 1014 | { |
| 2131 | int retval; | 1015 | int retval = zfcp_fsf_close_unit(erp_action); |
| 2132 | 1016 | if (retval == -ENOMEM) | |
| 2133 | retval = zfcp_fsf_open_port(erp_action); | 1017 | return ZFCP_ERP_NOMEM; |
| 2134 | if (retval == -ENOMEM) { | 1018 | erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING; |
| 2135 | retval = ZFCP_ERP_NOMEM; | 1019 | if (retval) |
| 2136 | goto out; | 1020 | return ZFCP_ERP_FAILED; |
| 2137 | } | 1021 | return ZFCP_ERP_CONTINUES; |
| 2138 | erp_action->step = ZFCP_ERP_STEP_PORT_OPENING; | ||
| 2139 | if (retval != 0) { | ||
| 2140 | /* could not send 'open', fail */ | ||
| 2141 | retval = ZFCP_ERP_FAILED; | ||
| 2142 | goto out; | ||
| 2143 | } | ||
| 2144 | retval = ZFCP_ERP_CONTINUES; | ||
| 2145 | out: | ||
| 2146 | return retval; | ||
| 2147 | } | 1022 | } |
| 2148 | 1023 | ||
| 2149 | /* | 1024 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) |
| 2150 | * function: | ||
| 2151 | * | ||
| 2152 | * purpose: | ||
| 2153 | * | ||
| 2154 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 2155 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 2156 | */ | ||
| 2157 | static int | ||
| 2158 | zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action) | ||
| 2159 | { | 1025 | { |
| 2160 | int retval; | 1026 | int retval = zfcp_fsf_open_unit(erp_action); |
| 2161 | 1027 | if (retval == -ENOMEM) | |
| 2162 | retval = zfcp_fc_ns_gid_pn_request(erp_action); | 1028 | return ZFCP_ERP_NOMEM; |
| 2163 | if (retval == -ENOMEM) { | 1029 | erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING; |
| 2164 | retval = ZFCP_ERP_NOMEM; | 1030 | if (retval) |
| 2165 | goto out; | 1031 | return ZFCP_ERP_FAILED; |
| 2166 | } | 1032 | return ZFCP_ERP_CONTINUES; |
| 2167 | erp_action->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; | ||
| 2168 | if (retval != 0) { | ||
| 2169 | /* could not send nameserver request, fail */ | ||
| 2170 | retval = ZFCP_ERP_FAILED; | ||
| 2171 | goto out; | ||
| 2172 | } | ||
| 2173 | retval = ZFCP_ERP_CONTINUES; | ||
| 2174 | out: | ||
| 2175 | return retval; | ||
| 2176 | } | 1033 | } |
| 2177 | 1034 | ||
| 2178 | /* | 1035 | static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) |
| 2179 | * function: | ||
| 2180 | * | ||
| 2181 | * purpose: this routine executes the 'Reopen Unit' action | ||
| 2182 | * currently no retries | ||
| 2183 | * | ||
| 2184 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 2185 | * ZFCP_ERP_SUCCEEDED - action finished successfully | ||
| 2186 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 2187 | */ | ||
| 2188 | static int | ||
| 2189 | zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) | ||
| 2190 | { | 1036 | { |
| 2191 | int retval = ZFCP_ERP_FAILED; | ||
| 2192 | struct zfcp_unit *unit = erp_action->unit; | 1037 | struct zfcp_unit *unit = erp_action->unit; |
| 2193 | 1038 | ||
| 2194 | switch (erp_action->step) { | 1039 | switch (erp_action->step) { |
| 2195 | |||
| 2196 | /* | ||
| 2197 | * FIXME: | ||
| 2198 | * the ULP spec. begs for waiting for oustanding commands | ||
| 2199 | */ | ||
| 2200 | case ZFCP_ERP_STEP_UNINITIALIZED: | 1040 | case ZFCP_ERP_STEP_UNINITIALIZED: |
| 2201 | zfcp_erp_unit_strategy_clearstati(unit); | 1041 | zfcp_erp_unit_strategy_clearstati(unit); |
| 2202 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) { | 1042 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) |
| 2203 | retval = zfcp_erp_unit_strategy_close(erp_action); | 1043 | return zfcp_erp_unit_strategy_close(erp_action); |
| 2204 | break; | 1044 | /* already closed, fall through */ |
| 2205 | } | ||
| 2206 | /* else it's already closed, fall through */ | ||
| 2207 | case ZFCP_ERP_STEP_UNIT_CLOSING: | 1045 | case ZFCP_ERP_STEP_UNIT_CLOSING: |
| 2208 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) | 1046 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) |
| 2209 | retval = ZFCP_ERP_FAILED; | 1047 | return ZFCP_ERP_FAILED; |
| 2210 | else | 1048 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) |
| 2211 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | 1049 | return ZFCP_ERP_EXIT; |
| 2212 | retval = ZFCP_ERP_EXIT; | 1050 | return zfcp_erp_unit_strategy_open(erp_action); |
| 2213 | else | ||
| 2214 | retval = | ||
| 2215 | zfcp_erp_unit_strategy_open(erp_action); | ||
| 2216 | break; | ||
| 2217 | 1051 | ||
| 2218 | case ZFCP_ERP_STEP_UNIT_OPENING: | 1052 | case ZFCP_ERP_STEP_UNIT_OPENING: |
| 2219 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) | 1053 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) |
| 2220 | retval = ZFCP_ERP_SUCCEEDED; | 1054 | return ZFCP_ERP_SUCCEEDED; |
| 2221 | else | ||
| 2222 | retval = ZFCP_ERP_FAILED; | ||
| 2223 | break; | ||
| 2224 | } | 1055 | } |
| 2225 | 1056 | return ZFCP_ERP_FAILED; | |
| 2226 | return retval; | ||
| 2227 | } | 1057 | } |
| 2228 | 1058 | ||
| 2229 | static int | 1059 | static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) |
| 2230 | zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) | ||
| 2231 | { | 1060 | { |
| 2232 | int retval = 0; | 1061 | switch (result) { |
| 2233 | 1062 | case ZFCP_ERP_SUCCEEDED : | |
| 2234 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | | 1063 | atomic_set(&unit->erp_counter, 0); |
| 2235 | ZFCP_STATUS_COMMON_CLOSING | | 1064 | zfcp_erp_unit_unblock(unit); |
| 2236 | ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1065 | break; |
| 2237 | ZFCP_STATUS_UNIT_SHARED | | 1066 | case ZFCP_ERP_FAILED : |
| 2238 | ZFCP_STATUS_UNIT_READONLY, | 1067 | atomic_inc(&unit->erp_counter); |
| 2239 | &unit->status); | 1068 | if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) |
| 1069 | zfcp_erp_unit_failed(unit, 21, NULL); | ||
| 1070 | break; | ||
| 1071 | } | ||
| 2240 | 1072 | ||
| 2241 | return retval; | 1073 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
| 1074 | zfcp_erp_unit_block(unit, 0); | ||
| 1075 | result = ZFCP_ERP_EXIT; | ||
| 1076 | } | ||
| 1077 | return result; | ||
| 2242 | } | 1078 | } |
| 2243 | 1079 | ||
| 2244 | /* | 1080 | static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) |
| 2245 | * function: | ||
| 2246 | * | ||
| 2247 | * purpose: | ||
| 2248 | * | ||
| 2249 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 2250 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 2251 | */ | ||
| 2252 | static int | ||
| 2253 | zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) | ||
| 2254 | { | 1081 | { |
| 2255 | int retval; | 1082 | switch (result) { |
| 1083 | case ZFCP_ERP_SUCCEEDED : | ||
| 1084 | atomic_set(&port->erp_counter, 0); | ||
| 1085 | zfcp_erp_port_unblock(port); | ||
| 1086 | break; | ||
| 2256 | 1087 | ||
| 2257 | retval = zfcp_fsf_close_unit(erp_action); | 1088 | case ZFCP_ERP_FAILED : |
| 2258 | if (retval == -ENOMEM) { | 1089 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) { |
| 2259 | retval = ZFCP_ERP_NOMEM; | 1090 | zfcp_erp_port_block(port, 0); |
| 2260 | goto out; | 1091 | result = ZFCP_ERP_EXIT; |
| 2261 | } | 1092 | } |
| 2262 | erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING; | 1093 | atomic_inc(&port->erp_counter); |
| 2263 | if (retval != 0) { | 1094 | if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) |
| 2264 | /* could not send 'close', fail */ | 1095 | zfcp_erp_port_failed(port, 22, NULL); |
| 2265 | retval = ZFCP_ERP_FAILED; | 1096 | break; |
| 2266 | goto out; | ||
| 2267 | } | 1097 | } |
| 2268 | retval = ZFCP_ERP_CONTINUES; | ||
| 2269 | 1098 | ||
| 2270 | out: | 1099 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
| 2271 | return retval; | 1100 | zfcp_erp_port_block(port, 0); |
| 1101 | result = ZFCP_ERP_EXIT; | ||
| 1102 | } | ||
| 1103 | return result; | ||
| 2272 | } | 1104 | } |
| 2273 | 1105 | ||
| 2274 | /* | 1106 | static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, |
| 2275 | * function: | 1107 | int result) |
| 2276 | * | ||
| 2277 | * purpose: | ||
| 2278 | * | ||
| 2279 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
| 2280 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
| 2281 | */ | ||
| 2282 | static int | ||
| 2283 | zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) | ||
| 2284 | { | 1108 | { |
| 2285 | int retval; | 1109 | switch (result) { |
| 1110 | case ZFCP_ERP_SUCCEEDED : | ||
| 1111 | atomic_set(&adapter->erp_counter, 0); | ||
| 1112 | zfcp_erp_adapter_unblock(adapter); | ||
| 1113 | break; | ||
| 2286 | 1114 | ||
| 2287 | retval = zfcp_fsf_open_unit(erp_action); | 1115 | case ZFCP_ERP_FAILED : |
| 2288 | if (retval == -ENOMEM) { | 1116 | atomic_inc(&adapter->erp_counter); |
| 2289 | retval = ZFCP_ERP_NOMEM; | 1117 | if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) |
| 2290 | goto out; | 1118 | zfcp_erp_adapter_failed(adapter, 23, NULL); |
| 1119 | break; | ||
| 2291 | } | 1120 | } |
| 2292 | erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING; | 1121 | |
| 2293 | if (retval != 0) { | 1122 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
| 2294 | /* could not send 'open', fail */ | 1123 | zfcp_erp_adapter_block(adapter, 0); |
| 2295 | retval = ZFCP_ERP_FAILED; | 1124 | result = ZFCP_ERP_EXIT; |
| 2296 | goto out; | ||
| 2297 | } | 1125 | } |
| 2298 | retval = ZFCP_ERP_CONTINUES; | 1126 | return result; |
| 2299 | out: | ||
| 2300 | return retval; | ||
| 2301 | } | 1127 | } |
| 2302 | 1128 | ||
| 2303 | void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req) | 1129 | static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, |
| 1130 | int result) | ||
| 2304 | { | 1131 | { |
| 2305 | BUG_ON(!fsf_req->erp_action); | 1132 | struct zfcp_adapter *adapter = erp_action->adapter; |
| 2306 | fsf_req->timer.function = zfcp_erp_timeout_handler; | 1133 | struct zfcp_port *port = erp_action->port; |
| 2307 | fsf_req->timer.data = (unsigned long) fsf_req->erp_action; | 1134 | struct zfcp_unit *unit = erp_action->unit; |
| 2308 | fsf_req->timer.expires = jiffies + ZFCP_ERP_FSFREQ_TIMEOUT; | ||
| 2309 | add_timer(&fsf_req->timer); | ||
| 2310 | } | ||
| 2311 | |||
| 2312 | /* | ||
| 2313 | * function: | ||
| 2314 | * | ||
| 2315 | * purpose: enqueue the specified error recovery action, if needed | ||
| 2316 | * | ||
| 2317 | * returns: | ||
| 2318 | */ | ||
| 2319 | static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, | ||
| 2320 | struct zfcp_port *port, | ||
| 2321 | struct zfcp_unit *unit, u8 id, void *ref) | ||
| 2322 | { | ||
| 2323 | int retval = 1, need = want; | ||
| 2324 | struct zfcp_erp_action *erp_action = NULL; | ||
| 2325 | u32 status = 0; | ||
| 2326 | 1135 | ||
| 2327 | /* | 1136 | switch (erp_action->action) { |
| 2328 | * We need some rules here which check whether we really need | ||
| 2329 | * this action or whether we should just drop it. | ||
| 2330 | * E.g. if there is a unfinished 'Reopen Port' request then we drop a | ||
| 2331 | * 'Reopen Unit' request for an associated unit since we can't | ||
| 2332 | * satisfy this request now. A 'Reopen Port' action will trigger | ||
| 2333 | * 'Reopen Unit' actions when it completes. | ||
| 2334 | * Thus, there are only actions in the queue which can immediately be | ||
| 2335 | * executed. This makes the processing of the action queue more | ||
| 2336 | * efficient. | ||
| 2337 | */ | ||
| 2338 | |||
| 2339 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, | ||
| 2340 | &adapter->status)) | ||
| 2341 | return -EIO; | ||
| 2342 | 1137 | ||
| 2343 | /* check whether we really need this */ | ||
| 2344 | switch (want) { | ||
| 2345 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1138 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
| 2346 | if (atomic_test_mask | 1139 | result = zfcp_erp_strategy_check_unit(unit, result); |
| 2347 | (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) { | 1140 | break; |
| 2348 | goto out; | ||
| 2349 | } | ||
| 2350 | if (!atomic_test_mask | ||
| 2351 | (ZFCP_STATUS_COMMON_RUNNING, &port->status) || | ||
| 2352 | atomic_test_mask | ||
| 2353 | (ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { | ||
| 2354 | goto out; | ||
| 2355 | } | ||
| 2356 | if (!atomic_test_mask | ||
| 2357 | (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) | ||
| 2358 | need = ZFCP_ERP_ACTION_REOPEN_PORT; | ||
| 2359 | /* fall through !!! */ | ||
| 2360 | |||
| 2361 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
| 2362 | if (atomic_test_mask | ||
| 2363 | (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) { | ||
| 2364 | goto out; | ||
| 2365 | } | ||
| 2366 | /* fall through !!! */ | ||
| 2367 | 1141 | ||
| 2368 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1142 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 2369 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1143 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 2370 | &port->status)) | 1144 | result = zfcp_erp_strategy_check_port(port, result); |
| 2371 | goto out; | 1145 | break; |
| 2372 | if (!atomic_test_mask | ||
| 2373 | (ZFCP_STATUS_COMMON_RUNNING, &adapter->status) || | ||
| 2374 | atomic_test_mask | ||
| 2375 | (ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { | ||
| 2376 | goto out; | ||
| 2377 | } | ||
| 2378 | if (!atomic_test_mask | ||
| 2379 | (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) | ||
| 2380 | need = ZFCP_ERP_ACTION_REOPEN_ADAPTER; | ||
| 2381 | /* fall through !!! */ | ||
| 2382 | 1146 | ||
| 2383 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1147 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
| 2384 | if (atomic_test_mask | 1148 | result = zfcp_erp_strategy_check_adapter(adapter, result); |
| 2385 | (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) { | ||
| 2386 | goto out; | ||
| 2387 | } | ||
| 2388 | break; | 1149 | break; |
| 2389 | |||
| 2390 | default: | ||
| 2391 | /* unknown erp action */ | ||
| 2392 | goto out; | ||
| 2393 | } | 1150 | } |
| 1151 | return result; | ||
| 1152 | } | ||
| 2394 | 1153 | ||
| 2395 | /* mark adapter to have some error recovery pending */ | 1154 | static int zfcp_erp_strat_change_det(atomic_t *target_status, u32 erp_status) |
| 2396 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); | 1155 | { |
| 1156 | int status = atomic_read(target_status); | ||
| 2397 | 1157 | ||
| 2398 | /* setup error recovery action */ | 1158 | if ((status & ZFCP_STATUS_COMMON_RUNNING) && |
| 2399 | switch (need) { | 1159 | (erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY)) |
| 1160 | return 1; /* take it online */ | ||
| 2400 | 1161 | ||
| 2401 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1162 | if (!(status & ZFCP_STATUS_COMMON_RUNNING) && |
| 2402 | zfcp_unit_get(unit); | 1163 | !(erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY)) |
| 2403 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); | 1164 | return 1; /* take it offline */ |
| 2404 | erp_action = &unit->erp_action; | 1165 | |
| 2405 | if (!atomic_test_mask | 1166 | return 0; |
| 2406 | (ZFCP_STATUS_COMMON_RUNNING, &unit->status)) | 1167 | } |
| 2407 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 1168 | |
| 1169 | static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | ||
| 1170 | { | ||
| 1171 | int action = act->action; | ||
| 1172 | struct zfcp_adapter *adapter = act->adapter; | ||
| 1173 | struct zfcp_port *port = act->port; | ||
| 1174 | struct zfcp_unit *unit = act->unit; | ||
| 1175 | u32 erp_status = act->status; | ||
| 1176 | |||
| 1177 | switch (action) { | ||
| 1178 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
| 1179 | if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { | ||
| 1180 | _zfcp_erp_adapter_reopen(adapter, | ||
| 1181 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
| 1182 | 67, NULL); | ||
| 1183 | return ZFCP_ERP_EXIT; | ||
| 1184 | } | ||
| 2408 | break; | 1185 | break; |
| 2409 | 1186 | ||
| 2410 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
| 2411 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1187 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 2412 | zfcp_port_get(port); | 1188 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 2413 | zfcp_erp_action_dismiss_port(port); | 1189 | if (zfcp_erp_strat_change_det(&port->status, erp_status)) { |
| 2414 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); | 1190 | _zfcp_erp_port_reopen(port, |
| 2415 | erp_action = &port->erp_action; | 1191 | ZFCP_STATUS_COMMON_ERP_FAILED, |
| 2416 | if (!atomic_test_mask | 1192 | 68, NULL); |
| 2417 | (ZFCP_STATUS_COMMON_RUNNING, &port->status)) | 1193 | return ZFCP_ERP_EXIT; |
| 2418 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 1194 | } |
| 2419 | break; | 1195 | break; |
| 2420 | 1196 | ||
| 2421 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1197 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
| 2422 | zfcp_adapter_get(adapter); | 1198 | if (zfcp_erp_strat_change_det(&unit->status, erp_status)) { |
| 2423 | zfcp_erp_action_dismiss_adapter(adapter); | 1199 | _zfcp_erp_unit_reopen(unit, |
| 2424 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); | 1200 | ZFCP_STATUS_COMMON_ERP_FAILED, |
| 2425 | erp_action = &adapter->erp_action; | 1201 | 69, NULL); |
| 2426 | if (!atomic_test_mask | 1202 | return ZFCP_ERP_EXIT; |
| 2427 | (ZFCP_STATUS_COMMON_RUNNING, &adapter->status)) | 1203 | } |
| 2428 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | ||
| 2429 | break; | 1204 | break; |
| 2430 | } | 1205 | } |
| 2431 | 1206 | return ret; | |
| 2432 | memset(erp_action, 0, sizeof (struct zfcp_erp_action)); | ||
| 2433 | erp_action->adapter = adapter; | ||
| 2434 | erp_action->port = port; | ||
| 2435 | erp_action->unit = unit; | ||
| 2436 | erp_action->action = need; | ||
| 2437 | erp_action->status = status; | ||
| 2438 | |||
| 2439 | ++adapter->erp_total_count; | ||
| 2440 | |||
| 2441 | /* finally put it into 'ready' queue and kick erp thread */ | ||
| 2442 | list_add_tail(&erp_action->list, &adapter->erp_ready_head); | ||
| 2443 | up(&adapter->erp_ready_sem); | ||
| 2444 | zfcp_rec_dbf_event_thread(1, adapter); | ||
| 2445 | retval = 0; | ||
| 2446 | out: | ||
| 2447 | zfcp_rec_dbf_event_trigger(id, ref, want, need, erp_action, | ||
| 2448 | adapter, port, unit); | ||
| 2449 | return retval; | ||
| 2450 | } | 1207 | } |
| 2451 | 1208 | ||
| 2452 | static int | 1209 | static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) |
| 2453 | zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | ||
| 2454 | { | 1210 | { |
| 2455 | int retval = 0; | ||
| 2456 | struct zfcp_adapter *adapter = erp_action->adapter; | 1211 | struct zfcp_adapter *adapter = erp_action->adapter; |
| 2457 | 1212 | ||
| 2458 | --adapter->erp_total_count; | 1213 | adapter->erp_total_count--; |
| 2459 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { | 1214 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { |
| 2460 | --adapter->erp_low_mem_count; | 1215 | adapter->erp_low_mem_count--; |
| 2461 | erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; | 1216 | erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; |
| 2462 | } | 1217 | } |
| 2463 | 1218 | ||
| @@ -2469,140 +1224,458 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | |||
| 2469 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1224 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
| 2470 | &erp_action->unit->status); | 1225 | &erp_action->unit->status); |
| 2471 | break; | 1226 | break; |
| 1227 | |||
| 2472 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1228 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 2473 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1229 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 2474 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1230 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
| 2475 | &erp_action->port->status); | 1231 | &erp_action->port->status); |
| 2476 | break; | 1232 | break; |
| 1233 | |||
| 2477 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1234 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
| 2478 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1235 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
| 2479 | &erp_action->adapter->status); | 1236 | &erp_action->adapter->status); |
| 2480 | break; | 1237 | break; |
| 2481 | default: | ||
| 2482 | /* bug */ | ||
| 2483 | break; | ||
| 2484 | } | 1238 | } |
| 2485 | return retval; | ||
| 2486 | } | 1239 | } |
| 2487 | 1240 | ||
| 2488 | /** | 1241 | struct zfcp_erp_add_work { |
| 2489 | * zfcp_erp_action_cleanup | 1242 | struct zfcp_unit *unit; |
| 2490 | * | 1243 | struct work_struct work; |
| 2491 | * Register unit with scsi stack if appropriate and fix reference counts. | 1244 | }; |
| 2492 | * Note: Temporary units are not registered with scsi stack. | 1245 | |
| 2493 | */ | 1246 | static void zfcp_erp_scsi_scan(struct work_struct *work) |
| 2494 | static void | ||
| 2495 | zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, | ||
| 2496 | struct zfcp_port *port, struct zfcp_unit *unit, | ||
| 2497 | int result) | ||
| 2498 | { | 1247 | { |
| 2499 | switch (action) { | 1248 | struct zfcp_erp_add_work *p = |
| 1249 | container_of(work, struct zfcp_erp_add_work, work); | ||
| 1250 | struct zfcp_unit *unit = p->unit; | ||
| 1251 | struct fc_rport *rport = unit->port->rport; | ||
| 1252 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, | ||
| 1253 | unit->scsi_lun, 0); | ||
| 1254 | atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | ||
| 1255 | zfcp_unit_put(unit); | ||
| 1256 | kfree(p); | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | static void zfcp_erp_schedule_work(struct zfcp_unit *unit) | ||
| 1260 | { | ||
| 1261 | struct zfcp_erp_add_work *p; | ||
| 1262 | |||
| 1263 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 1264 | if (!p) { | ||
| 1265 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
| 1266 | "Out of resources. Could not register unit " | ||
| 1267 | "0x%016Lx on port 0x%016Lx with SCSI stack.\n", | ||
| 1268 | unit->fcp_lun, unit->port->wwpn); | ||
| 1269 | return; | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | zfcp_unit_get(unit); | ||
| 1273 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | ||
| 1274 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); | ||
| 1275 | p->unit = unit; | ||
| 1276 | schedule_work(&p->work); | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | static void zfcp_erp_rport_register(struct zfcp_port *port) | ||
| 1280 | { | ||
| 1281 | struct fc_rport_identifiers ids; | ||
| 1282 | ids.node_name = port->wwnn; | ||
| 1283 | ids.port_name = port->wwpn; | ||
| 1284 | ids.port_id = port->d_id; | ||
| 1285 | ids.roles = FC_RPORT_ROLE_FCP_TARGET; | ||
| 1286 | port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); | ||
| 1287 | if (!port->rport) { | ||
| 1288 | dev_err(&port->adapter->ccw_device->dev, | ||
| 1289 | "Failed registration of rport " | ||
| 1290 | "0x%016Lx.\n", port->wwpn); | ||
| 1291 | return; | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | scsi_target_unblock(&port->rport->dev); | ||
| 1295 | port->rport->maxframe_size = port->maxframe_size; | ||
| 1296 | port->rport->supported_classes = port->supported_classes; | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | static void zfcp_erp_rports_del(struct zfcp_adapter *adapter) | ||
| 1300 | { | ||
| 1301 | struct zfcp_port *port; | ||
| 1302 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
| 1303 | if (port->rport && !(atomic_read(&port->status) & | ||
| 1304 | ZFCP_STATUS_PORT_WKA)) { | ||
| 1305 | fc_remote_port_delete(port->rport); | ||
| 1306 | port->rport = NULL; | ||
| 1307 | } | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | ||
| 1311 | { | ||
| 1312 | struct zfcp_adapter *adapter = act->adapter; | ||
| 1313 | struct zfcp_port *port = act->port; | ||
| 1314 | struct zfcp_unit *unit = act->unit; | ||
| 1315 | |||
| 1316 | switch (act->action) { | ||
| 2500 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1317 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
| 2501 | if ((result == ZFCP_ERP_SUCCEEDED) | 1318 | if ((result == ZFCP_ERP_SUCCEEDED) && |
| 2502 | && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, | 1319 | !unit->device && port->rport) { |
| 2503 | &unit->status)) | ||
| 2504 | && !unit->device | ||
| 2505 | && port->rport) { | ||
| 2506 | atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, | 1320 | atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, |
| 2507 | &unit->status); | 1321 | &unit->status); |
| 2508 | if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, | 1322 | if (!(atomic_read(&unit->status) & |
| 2509 | &unit->status) == 0) | 1323 | ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)) |
| 2510 | zfcp_erp_schedule_work(unit); | 1324 | zfcp_erp_schedule_work(unit); |
| 2511 | } | 1325 | } |
| 2512 | zfcp_unit_put(unit); | 1326 | zfcp_unit_put(unit); |
| 2513 | break; | 1327 | break; |
| 1328 | |||
| 2514 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1329 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 2515 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1330 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 2516 | if (atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, | 1331 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN) { |
| 2517 | &port->status)) { | ||
| 2518 | zfcp_port_put(port); | 1332 | zfcp_port_put(port); |
| 2519 | break; | 1333 | return; |
| 2520 | } | ||
| 2521 | |||
| 2522 | if ((result == ZFCP_ERP_SUCCEEDED) | ||
| 2523 | && !port->rport) { | ||
| 2524 | struct fc_rport_identifiers ids; | ||
| 2525 | ids.node_name = port->wwnn; | ||
| 2526 | ids.port_name = port->wwpn; | ||
| 2527 | ids.port_id = port->d_id; | ||
| 2528 | ids.roles = FC_RPORT_ROLE_FCP_TARGET; | ||
| 2529 | port->rport = | ||
| 2530 | fc_remote_port_add(adapter->scsi_host, 0, &ids); | ||
| 2531 | if (!port->rport) | ||
| 2532 | dev_err(&adapter->ccw_device->dev, | ||
| 2533 | "Failed registration of rport " | ||
| 2534 | "0x%016Lx.\n", port->wwpn); | ||
| 2535 | else { | ||
| 2536 | scsi_target_unblock(&port->rport->dev); | ||
| 2537 | port->rport->maxframe_size = port->maxframe_size; | ||
| 2538 | port->rport->supported_classes = | ||
| 2539 | port->supported_classes; | ||
| 2540 | } | ||
| 2541 | } | 1334 | } |
| 1335 | if ((result == ZFCP_ERP_SUCCEEDED) && !port->rport) | ||
| 1336 | zfcp_erp_rport_register(port); | ||
| 2542 | if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { | 1337 | if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { |
| 2543 | fc_remote_port_delete(port->rport); | 1338 | fc_remote_port_delete(port->rport); |
| 2544 | port->rport = NULL; | 1339 | port->rport = NULL; |
| 2545 | } | 1340 | } |
| 2546 | zfcp_port_put(port); | 1341 | zfcp_port_put(port); |
| 2547 | break; | 1342 | break; |
| 1343 | |||
| 2548 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1344 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
| 2549 | if (result != ZFCP_ERP_SUCCEEDED) { | 1345 | if (result != ZFCP_ERP_SUCCEEDED) |
| 2550 | list_for_each_entry(port, &adapter->port_list_head, list) | 1346 | zfcp_erp_rports_del(adapter); |
| 2551 | if (port->rport && | ||
| 2552 | !atomic_test_mask(ZFCP_STATUS_PORT_WKA, | ||
| 2553 | &port->status)) { | ||
| 2554 | fc_remote_port_delete(port->rport); | ||
| 2555 | port->rport = NULL; | ||
| 2556 | } | ||
| 2557 | } | ||
| 2558 | zfcp_adapter_put(adapter); | 1347 | zfcp_adapter_put(adapter); |
| 2559 | break; | 1348 | break; |
| 2560 | default: | ||
| 2561 | break; | ||
| 2562 | } | 1349 | } |
| 2563 | } | 1350 | } |
| 2564 | 1351 | ||
| 1352 | static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) | ||
| 1353 | { | ||
| 1354 | switch (erp_action->action) { | ||
| 1355 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
| 1356 | return zfcp_erp_adapter_strategy(erp_action); | ||
| 1357 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
| 1358 | return zfcp_erp_port_forced_strategy(erp_action); | ||
| 1359 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
| 1360 | return zfcp_erp_port_strategy(erp_action); | ||
| 1361 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | ||
| 1362 | return zfcp_erp_unit_strategy(erp_action); | ||
| 1363 | } | ||
| 1364 | return ZFCP_ERP_FAILED; | ||
| 1365 | } | ||
| 2565 | 1366 | ||
| 2566 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | 1367 | static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) |
| 2567 | { | 1368 | { |
| 2568 | struct zfcp_port *port; | 1369 | int retval; |
| 1370 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
| 1371 | unsigned long flags; | ||
| 2569 | 1372 | ||
| 2570 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) | 1373 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
| 2571 | zfcp_erp_action_dismiss(&adapter->erp_action); | 1374 | write_lock(&adapter->erp_lock); |
| 2572 | else | 1375 | |
| 2573 | list_for_each_entry(port, &adapter->port_list_head, list) | 1376 | zfcp_erp_strategy_check_fsfreq(erp_action); |
| 2574 | zfcp_erp_action_dismiss_port(port); | 1377 | |
| 1378 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) { | ||
| 1379 | zfcp_erp_action_dequeue(erp_action); | ||
| 1380 | retval = ZFCP_ERP_DISMISSED; | ||
| 1381 | goto unlock; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | zfcp_erp_action_to_running(erp_action); | ||
| 1385 | |||
| 1386 | /* no lock to allow for blocking operations */ | ||
| 1387 | write_unlock(&adapter->erp_lock); | ||
| 1388 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 1389 | retval = zfcp_erp_strategy_do_action(erp_action); | ||
| 1390 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
| 1391 | write_lock(&adapter->erp_lock); | ||
| 1392 | |||
| 1393 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) | ||
| 1394 | retval = ZFCP_ERP_CONTINUES; | ||
| 1395 | |||
| 1396 | switch (retval) { | ||
| 1397 | case ZFCP_ERP_NOMEM: | ||
| 1398 | if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) { | ||
| 1399 | ++adapter->erp_low_mem_count; | ||
| 1400 | erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; | ||
| 1401 | } | ||
| 1402 | if (adapter->erp_total_count == adapter->erp_low_mem_count) | ||
| 1403 | _zfcp_erp_adapter_reopen(adapter, 0, 66, NULL); | ||
| 1404 | else { | ||
| 1405 | zfcp_erp_strategy_memwait(erp_action); | ||
| 1406 | retval = ZFCP_ERP_CONTINUES; | ||
| 1407 | } | ||
| 1408 | goto unlock; | ||
| 1409 | |||
| 1410 | case ZFCP_ERP_CONTINUES: | ||
| 1411 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { | ||
| 1412 | --adapter->erp_low_mem_count; | ||
| 1413 | erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; | ||
| 1414 | } | ||
| 1415 | goto unlock; | ||
| 1416 | } | ||
| 1417 | |||
| 1418 | retval = zfcp_erp_strategy_check_target(erp_action, retval); | ||
| 1419 | zfcp_erp_action_dequeue(erp_action); | ||
| 1420 | retval = zfcp_erp_strategy_statechange(erp_action, retval); | ||
| 1421 | if (retval == ZFCP_ERP_EXIT) | ||
| 1422 | goto unlock; | ||
| 1423 | zfcp_erp_strategy_followup_actions(erp_action); | ||
| 1424 | |||
| 1425 | unlock: | ||
| 1426 | write_unlock(&adapter->erp_lock); | ||
| 1427 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 1428 | |||
| 1429 | if (retval != ZFCP_ERP_CONTINUES) | ||
| 1430 | zfcp_erp_action_cleanup(erp_action, retval); | ||
| 1431 | |||
| 1432 | return retval; | ||
| 2575 | } | 1433 | } |
| 2576 | 1434 | ||
| 2577 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) | 1435 | static int zfcp_erp_thread(void *data) |
| 2578 | { | 1436 | { |
| 2579 | struct zfcp_unit *unit; | 1437 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; |
| 1438 | struct list_head *next; | ||
| 1439 | struct zfcp_erp_action *act; | ||
| 1440 | unsigned long flags; | ||
| 2580 | 1441 | ||
| 2581 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) | 1442 | daemonize("zfcperp%s", adapter->ccw_device->dev.bus_id); |
| 2582 | zfcp_erp_action_dismiss(&port->erp_action); | 1443 | /* Block all signals */ |
| 1444 | siginitsetinv(¤t->blocked, 0); | ||
| 1445 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
| 1446 | wake_up(&adapter->erp_thread_wqh); | ||
| 1447 | |||
| 1448 | while (!(atomic_read(&adapter->status) & | ||
| 1449 | ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) { | ||
| 1450 | write_lock_irqsave(&adapter->erp_lock, flags); | ||
| 1451 | next = adapter->erp_ready_head.next; | ||
| 1452 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
| 1453 | |||
| 1454 | if (next != &adapter->erp_ready_head) { | ||
| 1455 | act = list_entry(next, struct zfcp_erp_action, list); | ||
| 1456 | |||
| 1457 | /* there is more to come after dismission, no notify */ | ||
| 1458 | if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED) | ||
| 1459 | zfcp_erp_wakeup(adapter); | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | zfcp_rec_dbf_event_thread(4, adapter); | ||
| 1463 | down_interruptible(&adapter->erp_ready_sem); | ||
| 1464 | zfcp_rec_dbf_event_thread(5, adapter); | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
| 1468 | wake_up(&adapter->erp_thread_wqh); | ||
| 1469 | |||
| 1470 | return 0; | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | /** | ||
| 1474 | * zfcp_erp_thread_setup - Start ERP thread for adapter | ||
| 1475 | * @adapter: Adapter to start the ERP thread for | ||
| 1476 | * | ||
| 1477 | * Returns 0 on success or error code from kernel_thread() | ||
| 1478 | */ | ||
| 1479 | int zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | ||
| 1480 | { | ||
| 1481 | int retval; | ||
| 1482 | |||
| 1483 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
| 1484 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); | ||
| 1485 | if (retval < 0) { | ||
| 1486 | dev_err(&adapter->ccw_device->dev, | ||
| 1487 | "Creation of ERP thread failed.\n"); | ||
| 1488 | return retval; | ||
| 1489 | } | ||
| 1490 | wait_event(adapter->erp_thread_wqh, | ||
| 1491 | atomic_read(&adapter->status) & | ||
| 1492 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP); | ||
| 1493 | return 0; | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | /** | ||
| 1497 | * zfcp_erp_thread_kill - Stop ERP thread. | ||
| 1498 | * @adapter: Adapter where the ERP thread should be stopped. | ||
| 1499 | * | ||
| 1500 | * The caller of this routine ensures that the specified adapter has | ||
| 1501 | * been shut down and that this operation has been completed. Thus, | ||
| 1502 | * there are no pending erp_actions which would need to be handled | ||
| 1503 | * here. | ||
| 1504 | */ | ||
| 1505 | void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | ||
| 1506 | { | ||
| 1507 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); | ||
| 1508 | up(&adapter->erp_ready_sem); | ||
| 1509 | zfcp_rec_dbf_event_thread_lock(2, adapter); | ||
| 1510 | |||
| 1511 | wait_event(adapter->erp_thread_wqh, | ||
| 1512 | !(atomic_read(&adapter->status) & | ||
| 1513 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP)); | ||
| 1514 | |||
| 1515 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, | ||
| 1516 | &adapter->status); | ||
| 1517 | } | ||
| 1518 | |||
| 1519 | /** | ||
| 1520 | * zfcp_erp_adapter_failed - Set adapter status to failed. | ||
| 1521 | * @adapter: Failed adapter. | ||
| 1522 | * @id: Event id for debug trace. | ||
| 1523 | * @ref: Reference for debug trace. | ||
| 1524 | */ | ||
| 1525 | void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref) | ||
| 1526 | { | ||
| 1527 | zfcp_erp_modify_adapter_status(adapter, id, ref, | ||
| 1528 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
| 1529 | dev_err(&adapter->ccw_device->dev, "Adapter ERP failed.\n"); | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | /** | ||
| 1533 | * zfcp_erp_port_failed - Set port status to failed. | ||
| 1534 | * @port: Failed port. | ||
| 1535 | * @id: Event id for debug trace. | ||
| 1536 | * @ref: Reference for debug trace. | ||
| 1537 | */ | ||
| 1538 | void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref) | ||
| 1539 | { | ||
| 1540 | zfcp_erp_modify_port_status(port, id, ref, | ||
| 1541 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
| 1542 | |||
| 1543 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA) | ||
| 1544 | dev_err(&port->adapter->ccw_device->dev, | ||
| 1545 | "Port ERP failed for WKA port d_id=0x%06x.\n", | ||
| 1546 | port->d_id); | ||
| 2583 | else | 1547 | else |
| 2584 | list_for_each_entry(unit, &port->unit_list_head, list) | 1548 | dev_err(&port->adapter->ccw_device->dev, |
| 2585 | zfcp_erp_action_dismiss_unit(unit); | 1549 | "Port ERP failed for port wwpn=0x%016Lx.\n", |
| 1550 | port->wwpn); | ||
| 2586 | } | 1551 | } |
| 2587 | 1552 | ||
| 2588 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) | 1553 | /** |
| 1554 | * zfcp_erp_unit_failed - Set unit status to failed. | ||
| 1555 | * @unit: Failed unit. | ||
| 1556 | * @id: Event id for debug trace. | ||
| 1557 | * @ref: Reference for debug trace. | ||
| 1558 | */ | ||
| 1559 | void zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref) | ||
| 2589 | { | 1560 | { |
| 2590 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) | 1561 | zfcp_erp_modify_unit_status(unit, id, ref, |
| 2591 | zfcp_erp_action_dismiss(&unit->erp_action); | 1562 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); |
| 1563 | |||
| 1564 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
| 1565 | "Unit ERP failed for unit 0x%016Lx on port 0x%016Lx.\n", | ||
| 1566 | unit->fcp_lun, unit->port->wwpn); | ||
| 2592 | } | 1567 | } |
| 2593 | 1568 | ||
| 2594 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | 1569 | /** |
| 1570 | * zfcp_erp_wait - wait for completion of error recovery on an adapter | ||
| 1571 | * @adapter: adapter for which to wait for completion of its error recovery | ||
| 1572 | */ | ||
| 1573 | void zfcp_erp_wait(struct zfcp_adapter *adapter) | ||
| 2595 | { | 1574 | { |
| 2596 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); | 1575 | wait_event(adapter->erp_done_wqh, |
| 2597 | zfcp_rec_dbf_event_action(145, erp_action); | 1576 | !(atomic_read(&adapter->status) & |
| 1577 | ZFCP_STATUS_ADAPTER_ERP_PENDING)); | ||
| 1578 | } | ||
| 1579 | |||
| 1580 | /** | ||
| 1581 | * zfcp_erp_modify_adapter_status - change adapter status bits | ||
| 1582 | * @adapter: adapter to change the status | ||
| 1583 | * @id: id for the debug trace | ||
| 1584 | * @ref: reference for the debug trace | ||
| 1585 | * @mask: status bits to change | ||
| 1586 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
| 1587 | * | ||
| 1588 | * Changes in common status bits are propagated to attached ports and units. | ||
| 1589 | */ | ||
| 1590 | void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id, | ||
| 1591 | void *ref, u32 mask, int set_or_clear) | ||
| 1592 | { | ||
| 1593 | struct zfcp_port *port; | ||
| 1594 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | ||
| 1595 | |||
| 1596 | if (set_or_clear == ZFCP_SET) { | ||
| 1597 | if (status_change_set(mask, &adapter->status)) | ||
| 1598 | zfcp_rec_dbf_event_adapter(id, ref, adapter); | ||
| 1599 | atomic_set_mask(mask, &adapter->status); | ||
| 1600 | } else { | ||
| 1601 | if (status_change_clear(mask, &adapter->status)) | ||
| 1602 | zfcp_rec_dbf_event_adapter(id, ref, adapter); | ||
| 1603 | atomic_clear_mask(mask, &adapter->status); | ||
| 1604 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
| 1605 | atomic_set(&adapter->erp_counter, 0); | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | if (common_mask) | ||
| 1609 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
| 1610 | zfcp_erp_modify_port_status(port, id, ref, common_mask, | ||
| 1611 | set_or_clear); | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | /** | ||
| 1615 | * zfcp_erp_modify_port_status - change port status bits | ||
| 1616 | * @port: port to change the status bits | ||
| 1617 | * @id: id for the debug trace | ||
| 1618 | * @ref: reference for the debug trace | ||
| 1619 | * @mask: status bits to change | ||
| 1620 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
| 1621 | * | ||
| 1622 | * Changes in common status bits are propagated to attached units. | ||
| 1623 | */ | ||
| 1624 | void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref, | ||
| 1625 | u32 mask, int set_or_clear) | ||
| 1626 | { | ||
| 1627 | struct zfcp_unit *unit; | ||
| 1628 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | ||
| 1629 | |||
| 1630 | if (set_or_clear == ZFCP_SET) { | ||
| 1631 | if (status_change_set(mask, &port->status)) | ||
| 1632 | zfcp_rec_dbf_event_port(id, ref, port); | ||
| 1633 | atomic_set_mask(mask, &port->status); | ||
| 1634 | } else { | ||
| 1635 | if (status_change_clear(mask, &port->status)) | ||
| 1636 | zfcp_rec_dbf_event_port(id, ref, port); | ||
| 1637 | atomic_clear_mask(mask, &port->status); | ||
| 1638 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
| 1639 | atomic_set(&port->erp_counter, 0); | ||
| 1640 | } | ||
| 1641 | |||
| 1642 | if (common_mask) | ||
| 1643 | list_for_each_entry(unit, &port->unit_list_head, list) | ||
| 1644 | zfcp_erp_modify_unit_status(unit, id, ref, common_mask, | ||
| 1645 | set_or_clear); | ||
| 2598 | } | 1646 | } |
| 2599 | 1647 | ||
| 2600 | static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) | 1648 | /** |
| 1649 | * zfcp_erp_modify_unit_status - change unit status bits | ||
| 1650 | * @unit: unit to change the status bits | ||
| 1651 | * @id: id for the debug trace | ||
| 1652 | * @ref: reference for the debug trace | ||
| 1653 | * @mask: status bits to change | ||
| 1654 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
| 1655 | */ | ||
| 1656 | void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref, | ||
| 1657 | u32 mask, int set_or_clear) | ||
| 2601 | { | 1658 | { |
| 2602 | list_move(&erp_action->list, &erp_action->adapter->erp_ready_head); | 1659 | if (set_or_clear == ZFCP_SET) { |
| 2603 | zfcp_rec_dbf_event_action(146, erp_action); | 1660 | if (status_change_set(mask, &unit->status)) |
| 1661 | zfcp_rec_dbf_event_unit(id, ref, unit); | ||
| 1662 | atomic_set_mask(mask, &unit->status); | ||
| 1663 | } else { | ||
| 1664 | if (status_change_clear(mask, &unit->status)) | ||
| 1665 | zfcp_rec_dbf_event_unit(id, ref, unit); | ||
| 1666 | atomic_clear_mask(mask, &unit->status); | ||
| 1667 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) { | ||
| 1668 | atomic_set(&unit->erp_counter, 0); | ||
| 1669 | } | ||
| 1670 | } | ||
| 2604 | } | 1671 | } |
| 2605 | 1672 | ||
| 1673 | /** | ||
| 1674 | * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP | ||
| 1675 | * @port: The "boxed" port. | ||
| 1676 | * @id: The debug trace id. | ||
| 1677 | * @id: Reference for the debug trace. | ||
| 1678 | */ | ||
| 2606 | void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref) | 1679 | void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref) |
| 2607 | { | 1680 | { |
| 2608 | unsigned long flags; | 1681 | unsigned long flags; |
| @@ -2614,6 +1687,12 @@ void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref) | |||
| 2614 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1687 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
| 2615 | } | 1688 | } |
| 2616 | 1689 | ||
| 1690 | /** | ||
| 1691 | * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP | ||
| 1692 | * @port: The "boxed" unit. | ||
| 1693 | * @id: The debug trace id. | ||
| 1694 | * @id: Reference for the debug trace. | ||
| 1695 | */ | ||
| 2617 | void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref) | 1696 | void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref) |
| 2618 | { | 1697 | { |
| 2619 | zfcp_erp_modify_unit_status(unit, id, ref, | 1698 | zfcp_erp_modify_unit_status(unit, id, ref, |
| @@ -2621,6 +1700,15 @@ void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref) | |||
| 2621 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1700 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
| 2622 | } | 1701 | } |
| 2623 | 1702 | ||
| 1703 | /** | ||
| 1704 | * zfcp_erp_port_access_denied - Adapter denied access to port. | ||
| 1705 | * @port: port where access has been denied | ||
| 1706 | * @id: id for debug trace | ||
| 1707 | * @ref: reference for debug trace | ||
| 1708 | * | ||
| 1709 | * Since the adapter has denied access, stop using the port and the | ||
| 1710 | * attached units. | ||
| 1711 | */ | ||
| 2624 | void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref) | 1712 | void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref) |
| 2625 | { | 1713 | { |
| 2626 | unsigned long flags; | 1714 | unsigned long flags; |
| @@ -2632,6 +1720,14 @@ void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref) | |||
| 2632 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 1720 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
| 2633 | } | 1721 | } |
| 2634 | 1722 | ||
| 1723 | /** | ||
| 1724 | * zfcp_erp_unit_access_denied - Adapter denied access to unit. | ||
| 1725 | * @unit: unit where access has been denied | ||
| 1726 | * @id: id for debug trace | ||
| 1727 | * @ref: reference for debug trace | ||
| 1728 | * | ||
| 1729 | * Since the adapter has denied access, stop using the unit. | ||
| 1730 | */ | ||
| 2635 | void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref) | 1731 | void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref) |
| 2636 | { | 1732 | { |
| 2637 | zfcp_erp_modify_unit_status(unit, id, ref, | 1733 | zfcp_erp_modify_unit_status(unit, id, ref, |
| @@ -2639,33 +1735,26 @@ void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref) | |||
| 2639 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); | 1735 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); |
| 2640 | } | 1736 | } |
| 2641 | 1737 | ||
| 2642 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id, | 1738 | static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, |
| 2643 | void *ref) | 1739 | void *ref) |
| 2644 | { | 1740 | { |
| 2645 | struct zfcp_port *port; | 1741 | int status = atomic_read(&unit->status); |
| 2646 | unsigned long flags; | 1742 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | |
| 2647 | 1743 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) | |
| 2648 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
| 2649 | return; | 1744 | return; |
| 2650 | 1745 | ||
| 2651 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1746 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
| 2652 | if (adapter->nameserver_port) | ||
| 2653 | zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref); | ||
| 2654 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
| 2655 | if (port != adapter->nameserver_port) | ||
| 2656 | zfcp_erp_port_access_changed(port, id, ref); | ||
| 2657 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 2658 | } | 1747 | } |
| 2659 | 1748 | ||
| 2660 | void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, void *ref) | 1749 | static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, |
| 1750 | void *ref) | ||
| 2661 | { | 1751 | { |
| 2662 | struct zfcp_unit *unit; | 1752 | struct zfcp_unit *unit; |
| 1753 | int status = atomic_read(&port->status); | ||
| 2663 | 1754 | ||
| 2664 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, | 1755 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | |
| 2665 | &port->status) && | 1756 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { |
| 2666 | !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED, | 1757 | if (!(status & ZFCP_STATUS_PORT_WKA)) |
| 2667 | &port->status)) { | ||
| 2668 | if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) | ||
| 2669 | list_for_each_entry(unit, &port->unit_list_head, list) | 1758 | list_for_each_entry(unit, &port->unit_list_head, list) |
| 2670 | zfcp_erp_unit_access_changed(unit, id, ref); | 1759 | zfcp_erp_unit_access_changed(unit, id, ref); |
| 2671 | return; | 1760 | return; |
| @@ -2674,13 +1763,26 @@ void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, void *ref) | |||
| 2674 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1763 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
| 2675 | } | 1764 | } |
| 2676 | 1765 | ||
| 2677 | void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, void *ref) | 1766 | /** |
| 1767 | * zfcp_erp_adapter_access_changed - Process change in adapter ACT | ||
| 1768 | * @adapter: Adapter where the Access Control Table (ACT) changed | ||
| 1769 | * @id: Id for debug trace | ||
| 1770 | * @ref: Reference for debug trace | ||
| 1771 | */ | ||
| 1772 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id, | ||
| 1773 | void *ref) | ||
| 2678 | { | 1774 | { |
| 2679 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, | 1775 | struct zfcp_port *port; |
| 2680 | &unit->status) && | 1776 | unsigned long flags; |
| 2681 | !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED, | 1777 | |
| 2682 | &unit->status)) | 1778 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) |
| 2683 | return; | 1779 | return; |
| 2684 | 1780 | ||
| 2685 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1781 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
| 1782 | if (adapter->nameserver_port) | ||
| 1783 | zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref); | ||
| 1784 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
| 1785 | if (port != adapter->nameserver_port) | ||
| 1786 | zfcp_erp_port_access_changed(port, id, ref); | ||
| 1787 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
| 2686 | } | 1788 | } |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 2845693413fb..13eb0a67da66 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
| @@ -67,8 +67,6 @@ extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *, | |||
| 67 | struct fsf_qtcb_bottom_port *); | 67 | struct fsf_qtcb_bottom_port *); |
| 68 | extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | 68 | extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, |
| 69 | struct zfcp_fsf_cfdc *fsf_cfdc); | 69 | struct zfcp_fsf_cfdc *fsf_cfdc); |
| 70 | extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long); | ||
| 71 | extern void zfcp_erp_start_timer(struct zfcp_fsf_req *); | ||
| 72 | extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); | 70 | extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); |
| 73 | extern int zfcp_fsf_status_read(struct zfcp_adapter *); | 71 | extern int zfcp_fsf_status_read(struct zfcp_adapter *); |
| 74 | extern int zfcp_status_read_refill(struct zfcp_adapter *adapter); | 72 | extern int zfcp_status_read_refill(struct zfcp_adapter *adapter); |
| @@ -103,37 +101,34 @@ extern struct fc_function_template zfcp_transport_functions; | |||
| 103 | /******************************** ERP ****************************************/ | 101 | /******************************** ERP ****************************************/ |
| 104 | extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u8, void *, | 102 | extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u8, void *, |
| 105 | u32, int); | 103 | u32, int); |
| 106 | extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, u8, void *); | 104 | extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, u8, void *); |
| 107 | extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, u8, void *); | 105 | extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, u8, void *); |
| 108 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, u8, void *); | 106 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, u8, void *); |
| 109 | 107 | ||
| 110 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, u8, void *, u32, | 108 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, u8, void *, u32, |
| 111 | int); | 109 | int); |
| 112 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int, u8, void *); | 110 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int, u8, void *); |
| 113 | extern int zfcp_erp_port_shutdown(struct zfcp_port *, int, u8, void *); | 111 | extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, u8, void *); |
| 114 | extern int zfcp_erp_port_forced_reopen(struct zfcp_port *, int, u8, void *); | 112 | extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, u8, void *); |
| 115 | extern void zfcp_erp_port_failed(struct zfcp_port *, u8, void *); | 113 | extern void zfcp_erp_port_failed(struct zfcp_port *, u8, void *); |
| 116 | extern int zfcp_erp_port_reopen_all(struct zfcp_adapter *, int, u8, void *); | ||
| 117 | 114 | ||
| 118 | extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u8, void *, u32, | 115 | extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u8, void *, u32, |
| 119 | int); | 116 | int); |
| 120 | extern int zfcp_erp_unit_reopen(struct zfcp_unit *, int, u8, void *); | 117 | extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, u8, void *); |
| 121 | extern int zfcp_erp_unit_shutdown(struct zfcp_unit *, int, u8, void *); | 118 | extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, u8, void *); |
| 122 | extern void zfcp_erp_unit_failed(struct zfcp_unit *, u8, void *); | 119 | extern void zfcp_erp_unit_failed(struct zfcp_unit *, u8, void *); |
| 123 | 120 | ||
| 124 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); | 121 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); |
| 125 | extern int zfcp_erp_thread_kill(struct zfcp_adapter *); | 122 | extern void zfcp_erp_thread_kill(struct zfcp_adapter *); |
| 126 | extern int zfcp_erp_wait(struct zfcp_adapter *); | 123 | extern void zfcp_erp_wait(struct zfcp_adapter *); |
| 127 | extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); | 124 | extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long); |
| 128 | 125 | ||
| 129 | extern void zfcp_erp_port_boxed(struct zfcp_port *, u8 id, void *ref); | 126 | extern void zfcp_erp_port_boxed(struct zfcp_port *, u8 id, void *ref); |
| 130 | extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8 id, void *ref); | 127 | extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8 id, void *ref); |
| 131 | extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8 id, void *ref); | 128 | extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8 id, void *ref); |
| 132 | extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8 id, void *ref); | 129 | extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8 id, void *ref); |
| 133 | extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *); | 130 | extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *); |
| 134 | extern void zfcp_erp_port_access_changed(struct zfcp_port *, u8, void *); | 131 | extern void zfcp_erp_timeout_handler(unsigned long); |
| 135 | extern void zfcp_erp_unit_access_changed(struct zfcp_unit *, u8, void *); | ||
| 136 | |||
| 137 | /******************************** AUX ****************************************/ | 132 | /******************************** AUX ****************************************/ |
| 138 | extern void zfcp_sg_free_table(struct scatterlist *sg, int count); | 133 | extern void zfcp_sg_free_table(struct scatterlist *sg, int count); |
| 139 | extern int zfcp_sg_setup_table(struct scatterlist *sg, int count); | 134 | extern int zfcp_sg_setup_table(struct scatterlist *sg, int count); |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e6d815593b49..19c1ca913874 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
| @@ -8,6 +8,31 @@ | |||
| 8 | 8 | ||
| 9 | #include "zfcp_ext.h" | 9 | #include "zfcp_ext.h" |
| 10 | 10 | ||
| 11 | static void zfcp_fsf_request_timeout_handler(unsigned long data) | ||
| 12 | { | ||
| 13 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | ||
| 14 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62, | ||
| 15 | NULL); | ||
| 16 | } | ||
| 17 | |||
| 18 | static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, | ||
| 19 | unsigned long timeout) | ||
| 20 | { | ||
| 21 | fsf_req->timer.function = zfcp_fsf_request_timeout_handler; | ||
| 22 | fsf_req->timer.data = (unsigned long) fsf_req->adapter; | ||
| 23 | fsf_req->timer.expires = jiffies + timeout; | ||
| 24 | add_timer(&fsf_req->timer); | ||
| 25 | } | ||
| 26 | |||
| 27 | static void zfcp_fsf_start_erp_timer(struct zfcp_fsf_req *fsf_req) | ||
| 28 | { | ||
| 29 | BUG_ON(!fsf_req->erp_action); | ||
| 30 | fsf_req->timer.function = zfcp_erp_timeout_handler; | ||
| 31 | fsf_req->timer.data = (unsigned long) fsf_req->erp_action; | ||
| 32 | fsf_req->timer.expires = jiffies + 30 * HZ; | ||
| 33 | add_timer(&fsf_req->timer); | ||
| 34 | } | ||
| 35 | |||
| 11 | /* association between FSF command and FSF QTCB type */ | 36 | /* association between FSF command and FSF QTCB type */ |
| 12 | static u32 fsf_qtcb_type[] = { | 37 | static u32 fsf_qtcb_type[] = { |
| 13 | [FSF_QTCB_FCP_CMND] = FSF_IO_COMMAND, | 38 | [FSF_QTCB_FCP_CMND] = FSF_IO_COMMAND, |
| @@ -485,7 +510,7 @@ void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) | |||
| 485 | req->handler(req); | 510 | req->handler(req); |
| 486 | 511 | ||
| 487 | if (req->erp_action) | 512 | if (req->erp_action) |
| 488 | zfcp_erp_async_handler(req->erp_action, 0); | 513 | zfcp_erp_notify(req->erp_action, 0); |
| 489 | req->status |= ZFCP_STATUS_FSFREQ_COMPLETED; | 514 | req->status |= ZFCP_STATUS_FSFREQ_COMPLETED; |
| 490 | 515 | ||
| 491 | if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) | 516 | if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) |
| @@ -1108,7 +1133,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
| 1108 | if (erp_action) { | 1133 | if (erp_action) { |
| 1109 | erp_action->fsf_req = req; | 1134 | erp_action->fsf_req = req; |
| 1110 | req->erp_action = erp_action; | 1135 | req->erp_action = erp_action; |
| 1111 | zfcp_erp_start_timer(req); | 1136 | zfcp_fsf_start_erp_timer(req); |
| 1112 | } else | 1137 | } else |
| 1113 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 1138 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
| 1114 | 1139 | ||
| @@ -1263,7 +1288,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
| 1263 | req->handler = zfcp_fsf_exchange_config_data_handler; | 1288 | req->handler = zfcp_fsf_exchange_config_data_handler; |
| 1264 | erp_action->fsf_req = req; | 1289 | erp_action->fsf_req = req; |
| 1265 | 1290 | ||
| 1266 | zfcp_erp_start_timer(req); | 1291 | zfcp_fsf_start_erp_timer(req); |
| 1267 | retval = zfcp_fsf_req_send(req); | 1292 | retval = zfcp_fsf_req_send(req); |
| 1268 | if (retval) { | 1293 | if (retval) { |
| 1269 | zfcp_fsf_req_free(req); | 1294 | zfcp_fsf_req_free(req); |
| @@ -1353,7 +1378,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) | |||
| 1353 | req->erp_action = erp_action; | 1378 | req->erp_action = erp_action; |
| 1354 | erp_action->fsf_req = req; | 1379 | erp_action->fsf_req = req; |
| 1355 | 1380 | ||
| 1356 | zfcp_erp_start_timer(req); | 1381 | zfcp_fsf_start_erp_timer(req); |
| 1357 | retval = zfcp_fsf_req_send(req); | 1382 | retval = zfcp_fsf_req_send(req); |
| 1358 | if (retval) { | 1383 | if (retval) { |
| 1359 | zfcp_fsf_req_free(req); | 1384 | zfcp_fsf_req_free(req); |
| @@ -1530,7 +1555,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
| 1530 | erp_action->fsf_req = req; | 1555 | erp_action->fsf_req = req; |
| 1531 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); | 1556 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); |
| 1532 | 1557 | ||
| 1533 | zfcp_erp_start_timer(req); | 1558 | zfcp_fsf_start_erp_timer(req); |
| 1534 | retval = zfcp_fsf_req_send(req); | 1559 | retval = zfcp_fsf_req_send(req); |
| 1535 | if (retval) { | 1560 | if (retval) { |
| 1536 | zfcp_fsf_req_free(req); | 1561 | zfcp_fsf_req_free(req); |
| @@ -1601,7 +1626,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
| 1601 | erp_action->fsf_req = req; | 1626 | erp_action->fsf_req = req; |
| 1602 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); | 1627 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); |
| 1603 | 1628 | ||
| 1604 | zfcp_erp_start_timer(req); | 1629 | zfcp_fsf_start_erp_timer(req); |
| 1605 | retval = zfcp_fsf_req_send(req); | 1630 | retval = zfcp_fsf_req_send(req); |
| 1606 | if (retval) { | 1631 | if (retval) { |
| 1607 | zfcp_fsf_req_free(req); | 1632 | zfcp_fsf_req_free(req); |
| @@ -1699,7 +1724,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
| 1699 | atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, | 1724 | atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, |
| 1700 | &erp_action->port->status); | 1725 | &erp_action->port->status); |
| 1701 | 1726 | ||
| 1702 | zfcp_erp_start_timer(req); | 1727 | zfcp_fsf_start_erp_timer(req); |
| 1703 | retval = zfcp_fsf_req_send(req); | 1728 | retval = zfcp_fsf_req_send(req); |
| 1704 | if (retval) { | 1729 | if (retval) { |
| 1705 | zfcp_fsf_req_free(req); | 1730 | zfcp_fsf_req_free(req); |
| @@ -1878,7 +1903,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
| 1878 | 1903 | ||
| 1879 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); | 1904 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); |
| 1880 | 1905 | ||
| 1881 | zfcp_erp_start_timer(req); | 1906 | zfcp_fsf_start_erp_timer(req); |
| 1882 | retval = zfcp_fsf_req_send(req); | 1907 | retval = zfcp_fsf_req_send(req); |
| 1883 | if (retval) { | 1908 | if (retval) { |
| 1884 | zfcp_fsf_req_free(req); | 1909 | zfcp_fsf_req_free(req); |
| @@ -1963,7 +1988,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
| 1963 | erp_action->fsf_req = req; | 1988 | erp_action->fsf_req = req; |
| 1964 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); | 1989 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); |
| 1965 | 1990 | ||
| 1966 | zfcp_erp_start_timer(req); | 1991 | zfcp_fsf_start_erp_timer(req); |
| 1967 | retval = zfcp_fsf_req_send(req); | 1992 | retval = zfcp_fsf_req_send(req); |
| 1968 | if (retval) { | 1993 | if (retval) { |
| 1969 | zfcp_fsf_req_free(req); | 1994 | zfcp_fsf_req_free(req); |
