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