blob: feb1fda33d256c121e412b224aa750df1c351d10 [file] [log] [blame]
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001/*
Andreas Herrmann4a9d2d82006-05-22 18:14:08 +02002 * This file is part of the zfcp device driver for
3 * FCP adapters for IBM System z9 and zSeries.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Andreas Herrmann4a9d2d82006-05-22 18:14:08 +02005 * (C) Copyright IBM Corp. 2002, 2006
Swen Schillig41fa2ad2007-09-07 09:15:31 +02006 *
7 * This program is free software; you can redistribute it and/or modify
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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21
22#define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include "zfcp_ext.h"
25
Andreas Herrmann64b29a132005-06-13 13:18:56 +020026static int zfcp_erp_adisc(struct zfcp_port *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070027static void zfcp_erp_adisc_handler(unsigned long);
28
Martin Peschke9467a9b2008-03-27 14:22:03 +010029static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int, u8,
30 u64);
31static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int, u8,
32 u64);
33static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int, u8, u64);
34static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int, u8, u64);
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Martin Peschke9467a9b2008-03-27 14:22:03 +010036static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int, u8,
37 u64);
38static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int, u8, u64);
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40static void zfcp_erp_adapter_block(struct zfcp_adapter *, int);
41static void zfcp_erp_adapter_unblock(struct zfcp_adapter *);
42static void zfcp_erp_port_block(struct zfcp_port *, int);
43static void zfcp_erp_port_unblock(struct zfcp_port *);
44static void zfcp_erp_unit_block(struct zfcp_unit *, int);
45static void zfcp_erp_unit_unblock(struct zfcp_unit *);
46
47static int zfcp_erp_thread(void *);
48
49static int zfcp_erp_strategy(struct zfcp_erp_action *);
50
51static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *);
52static int zfcp_erp_strategy_memwait(struct zfcp_erp_action *);
53static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *, int);
54static int zfcp_erp_strategy_check_unit(struct zfcp_unit *, int);
55static int zfcp_erp_strategy_check_port(struct zfcp_port *, int);
56static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *, int);
57static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *,
58 struct zfcp_port *,
59 struct zfcp_unit *, int);
Heiko Carstens364c8552007-10-12 16:11:35 +020060static int zfcp_erp_strategy_statechange_detected(atomic_t *, u32);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *,
62 struct zfcp_port *,
63 struct zfcp_unit *, int);
64static int zfcp_erp_strategy_check_queues(struct zfcp_adapter *);
65static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int);
66
67static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *);
68static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int);
69static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);
71static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);
72static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);
73static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *);
Maxim Shchetyninaef4a982005-09-13 21:51:16 +020074static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075static int zfcp_erp_adapter_strategy_open_fsf_statusread(
76 struct zfcp_erp_action *);
77
78static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *);
79static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *);
80
81static int zfcp_erp_port_strategy(struct zfcp_erp_action *);
82static int zfcp_erp_port_strategy_clearstati(struct zfcp_port *);
83static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *);
84static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *);
85static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *);
86static int zfcp_erp_port_strategy_open_nameserver_wakeup(
87 struct zfcp_erp_action *);
88static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *);
89static int zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *);
90static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *);
91
92static int zfcp_erp_unit_strategy(struct zfcp_erp_action *);
93static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *);
94static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *);
95static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *);
96
Andreas Herrmann81654282006-09-18 22:30:36 +020097static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +020098static void zfcp_erp_action_dismiss_port(struct zfcp_port *);
99static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
100static void zfcp_erp_action_dismiss(struct zfcp_erp_action *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *,
Martin Peschke9467a9b2008-03-27 14:22:03 +0100103 struct zfcp_port *, struct zfcp_unit *,
104 u8 id, u64 ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105static int zfcp_erp_action_dequeue(struct zfcp_erp_action *);
106static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *,
107 struct zfcp_port *, struct zfcp_unit *,
108 int);
109
110static void zfcp_erp_action_ready(struct zfcp_erp_action *);
111static int zfcp_erp_action_exists(struct zfcp_erp_action *);
112
Heiko Carstens364c8552007-10-12 16:11:35 +0200113static void zfcp_erp_action_to_ready(struct zfcp_erp_action *);
114static void zfcp_erp_action_to_running(struct zfcp_erp_action *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
116static void zfcp_erp_memwait_handler(unsigned long);
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200117
118/**
119 * zfcp_close_qdio - close qdio queues for an adapter
120 */
121static void zfcp_close_qdio(struct zfcp_adapter *adapter)
122{
123 struct zfcp_qdio_queue *req_queue;
124 int first, count;
125
126 if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
127 return;
128
129 /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
130 req_queue = &adapter->request_queue;
131 write_lock_irq(&req_queue->queue_lock);
132 atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
133 write_unlock_irq(&req_queue->queue_lock);
134
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200135 while (qdio_shutdown(adapter->ccw_device,
136 QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
Christof Schmitt18edcdb2007-11-05 12:37:45 +0100137 ssleep(1);
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200138
139 /* cleanup used outbound sbals */
140 count = atomic_read(&req_queue->free_count);
141 if (count < QDIO_MAX_BUFFERS_PER_Q) {
142 first = (req_queue->free_index+count) % QDIO_MAX_BUFFERS_PER_Q;
143 count = QDIO_MAX_BUFFERS_PER_Q - count;
144 zfcp_qdio_zero_sbals(req_queue->buffer, first, count);
145 }
146 req_queue->free_index = 0;
147 atomic_set(&req_queue->free_count, 0);
148 req_queue->distance_from_int = 0;
149 adapter->response_queue.free_index = 0;
150 atomic_set(&adapter->response_queue.free_count, 0);
151}
152
153/**
154 * zfcp_close_fsf - stop FSF operations for an adapter
155 *
156 * Dismiss and cleanup all pending fsf_reqs (this wakes up all initiators of
157 * requests waiting for completion; especially this returns SCSI commands
158 * with error state).
159 */
160static void zfcp_close_fsf(struct zfcp_adapter *adapter)
161{
162 /* close queues to ensure that buffers are not accessed by adapter */
163 zfcp_close_qdio(adapter);
164 zfcp_fsf_req_dismiss_all(adapter);
165 /* reset FSF request sequence number */
166 adapter->fsf_req_seq_no = 0;
167 /* all ports and units are closed */
Martin Peschke698ec0162008-03-27 14:22:02 +0100168 zfcp_erp_modify_adapter_status(adapter, 24, 0,
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200169 ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
170}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
172/**
173 * zfcp_fsf_request_timeout_handler - called if a request timed out
174 * @data: pointer to adapter for handler function
175 *
176 * This function needs to be called if requests (ELS, Generic Service,
177 * or SCSI commands) exceed a certain time limit. The assumption is
178 * that after the time limit the adapter get stuck. So we trigger a reopen of
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200179 * the adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 */
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200181static void zfcp_fsf_request_timeout_handler(unsigned long data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182{
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200183 struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
Martin Peschke9467a9b2008-03-27 14:22:03 +0100184 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185}
186
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200187void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188{
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200189 fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
190 fsf_req->timer.data = (unsigned long) fsf_req->adapter;
Christof Schmitt9e3738f2007-03-28 14:20:40 +0200191 fsf_req->timer.expires = jiffies + timeout;
Andreas Herrmann2abbe862006-09-18 22:29:56 +0200192 add_timer(&fsf_req->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193}
194
195/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200196 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 *
198 * purpose: called if an adapter failed,
199 * initiates adapter recovery which is done
200 * asynchronously
201 *
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200202 * returns: 0 - initiated action successfully
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 * <0 - failed to initiate action
204 */
Martin Peschke9467a9b2008-03-27 14:22:03 +0100205static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter,
206 int clear_mask, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207{
208 int retval;
209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 ZFCP_LOG_DEBUG("reopen adapter %s\n",
211 zfcp_get_busid_by_adapter(adapter));
212
213 zfcp_erp_adapter_block(adapter, clear_mask);
214
215 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) {
216 ZFCP_LOG_DEBUG("skipped reopen of failed adapter %s\n",
217 zfcp_get_busid_by_adapter(adapter));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 /* ensure propagation of failed status to new devices */
Martin Peschke698ec0162008-03-27 14:22:02 +0100219 zfcp_erp_adapter_failed(adapter, 13, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 retval = -EIO;
221 goto out;
222 }
223 retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
Martin Peschke9467a9b2008-03-27 14:22:03 +0100224 adapter, NULL, NULL, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 out:
227 return retval;
228}
229
230/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200231 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 *
233 * purpose: Wrappper for zfcp_erp_adapter_reopen_internal
234 * used to ensure the correct locking
235 *
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200236 * returns: 0 - initiated action successfully
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 * <0 - failed to initiate action
238 */
Martin Peschke9467a9b2008-03-27 14:22:03 +0100239int zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask,
240 u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241{
242 int retval;
243 unsigned long flags;
244
245 read_lock_irqsave(&zfcp_data.config_lock, flags);
246 write_lock(&adapter->erp_lock);
Martin Peschke9467a9b2008-03-27 14:22:03 +0100247 retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 write_unlock(&adapter->erp_lock);
249 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
250
251 return retval;
252}
253
Martin Peschke9467a9b2008-03-27 14:22:03 +0100254int zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask,
255 u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256{
257 int retval;
258
259 retval = zfcp_erp_adapter_reopen(adapter,
260 ZFCP_STATUS_COMMON_RUNNING |
261 ZFCP_STATUS_COMMON_ERP_FAILED |
Martin Peschke9467a9b2008-03-27 14:22:03 +0100262 clear_mask, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
264 return retval;
265}
266
Martin Peschke9467a9b2008-03-27 14:22:03 +0100267int zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask, u8 id,
268 u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
270 int retval;
271
272 retval = zfcp_erp_port_reopen(port,
273 ZFCP_STATUS_COMMON_RUNNING |
274 ZFCP_STATUS_COMMON_ERP_FAILED |
Martin Peschke9467a9b2008-03-27 14:22:03 +0100275 clear_mask, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
277 return retval;
278}
279
Martin Peschke9467a9b2008-03-27 14:22:03 +0100280int zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask, u8 id,
281 u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282{
283 int retval;
284
285 retval = zfcp_erp_unit_reopen(unit,
286 ZFCP_STATUS_COMMON_RUNNING |
287 ZFCP_STATUS_COMMON_ERP_FAILED |
Martin Peschke9467a9b2008-03-27 14:22:03 +0100288 clear_mask, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
290 return retval;
291}
292
293
294/**
295 * zfcp_erp_adisc - send ADISC ELS command
Andreas Herrmann64b29a132005-06-13 13:18:56 +0200296 * @port: port structure
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 */
Heiko Carstens2b67fc42007-02-05 21:16:47 +0100298static int
Andreas Herrmann64b29a132005-06-13 13:18:56 +0200299zfcp_erp_adisc(struct zfcp_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300{
Andreas Herrmann64b29a132005-06-13 13:18:56 +0200301 struct zfcp_adapter *adapter = port->adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 struct zfcp_send_els *send_els;
303 struct zfcp_ls_adisc *adisc;
304 void *address = NULL;
305 int retval = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Andreas Herrmannec4081c2006-05-22 18:17:30 +0200307 send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 if (send_els == NULL)
309 goto nomem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
Jens Axboe73fc4f02007-10-23 09:17:53 +0200311 send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 if (send_els->req == NULL)
313 goto nomem;
Jens Axboe73fc4f02007-10-23 09:17:53 +0200314 sg_init_table(send_els->req, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
Jens Axboe73fc4f02007-10-23 09:17:53 +0200316 send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 if (send_els->resp == NULL)
318 goto nomem;
Jens Axboe73fc4f02007-10-23 09:17:53 +0200319 sg_init_table(send_els->resp, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
321 address = (void *) get_zeroed_page(GFP_ATOMIC);
322 if (address == NULL)
323 goto nomem;
324
Jens Axboe642f1492007-10-24 11:20:47 +0200325 zfcp_address_to_sg(address, send_els->req, sizeof(struct zfcp_ls_adisc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 address += PAGE_SIZE >> 1;
Jens Axboe642f1492007-10-24 11:20:47 +0200327 zfcp_address_to_sg(address, send_els->resp, sizeof(struct zfcp_ls_adisc_acc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 send_els->req_count = send_els->resp_count = 1;
329
330 send_els->adapter = adapter;
Andreas Herrmann64b29a132005-06-13 13:18:56 +0200331 send_els->port = port;
332 send_els->d_id = port->d_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 send_els->handler = zfcp_erp_adisc_handler;
334 send_els->handler_data = (unsigned long) send_els;
335
336 adisc = zfcp_sg_to_address(send_els->req);
337 send_els->ls_code = adisc->code = ZFCP_LS_ADISC;
338
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports
340 without FC-AL-2 capability, so we don't set it */
Andreas Herrmann13e1e1f2005-09-19 16:56:17 +0200341 adisc->wwpn = fc_host_port_name(adapter->scsi_host);
342 adisc->wwnn = fc_host_node_name(adapter->scsi_host);
343 adisc->nport_id = fc_host_port_id(adapter->scsi_host);
Christof Schmitt1d589ed2007-05-08 11:14:41 +0200344 ZFCP_LOG_INFO("ADISC request from s_id 0x%06x to d_id 0x%06x "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
Christof Schmitt1d589ed2007-05-08 11:14:41 +0200346 "hard_nport_id=0x%06x, nport_id=0x%06x)\n",
Andreas Herrmann13e1e1f2005-09-19 16:56:17 +0200347 adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 (wwn_t) adisc->wwnn, adisc->hard_nport_id,
349 adisc->nport_id);
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 retval = zfcp_fsf_send_els(send_els);
352 if (retval != 0) {
353 ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
Christof Schmitt1d589ed2007-05-08 11:14:41 +0200354 "0x%06x on adapter %s\n", send_els->d_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 zfcp_get_busid_by_adapter(adapter));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 goto freemem;
357 }
358
359 goto out;
360
361 nomem:
362 retval = -ENOMEM;
363 freemem:
364 if (address != NULL)
Jens Axboe73fc4f02007-10-23 09:17:53 +0200365 __free_pages(sg_page(send_els->req), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 if (send_els != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 kfree(send_els->req);
368 kfree(send_els->resp);
369 kfree(send_els);
370 }
371 out:
372 return retval;
373}
374
375
376/**
377 * zfcp_erp_adisc_handler - handler for ADISC ELS command
378 * @data: pointer to struct zfcp_send_els
379 *
380 * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered.
381 */
Heiko Carstens2b67fc42007-02-05 21:16:47 +0100382static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383zfcp_erp_adisc_handler(unsigned long data)
384{
385 struct zfcp_send_els *send_els;
386 struct zfcp_port *port;
387 struct zfcp_adapter *adapter;
Andreas Herrmann13e1e1f2005-09-19 16:56:17 +0200388 u32 d_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 struct zfcp_ls_adisc_acc *adisc;
390
391 send_els = (struct zfcp_send_els *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 adapter = send_els->adapter;
Andreas Herrmann64b29a132005-06-13 13:18:56 +0200393 port = send_els->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 d_id = send_els->d_id;
395
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 /* request rejected or timed out */
397 if (send_els->status != 0) {
398 ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
399 "force physical port reopen "
Christof Schmitt1d589ed2007-05-08 11:14:41 +0200400 "(adapter %s, port d_id=0x%06x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 zfcp_get_busid_by_adapter(adapter), d_id);
Martin Peschke9467a9b2008-03-27 14:22:03 +0100402 if (zfcp_erp_port_forced_reopen(port, 0, 63, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 ZFCP_LOG_NORMAL("failed reopen of port "
404 "(adapter %s, wwpn=0x%016Lx)\n",
405 zfcp_get_busid_by_port(port),
406 port->wwpn);
407 goto out;
408 }
409
410 adisc = zfcp_sg_to_address(send_els->resp);
411
Christof Schmitt1d589ed2007-05-08 11:14:41 +0200412 ZFCP_LOG_INFO("ADISC response from d_id 0x%06x to s_id "
413 "0x%06x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
414 "hard_nport_id=0x%06x, nport_id=0x%06x)\n",
Andreas Herrmann13e1e1f2005-09-19 16:56:17 +0200415 d_id, fc_host_port_id(adapter->scsi_host),
416 (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn,
417 adisc->hard_nport_id, adisc->nport_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
419 /* set wwnn for port */
420 if (port->wwnn == 0)
421 port->wwnn = adisc->wwnn;
422
423 if (port->wwpn != adisc->wwpn) {
424 ZFCP_LOG_NORMAL("d_id assignment changed, reopening "
425 "port (adapter %s, wwpn=0x%016Lx, "
426 "adisc_resp_wwpn=0x%016Lx)\n",
427 zfcp_get_busid_by_port(port),
428 port->wwpn, (wwn_t) adisc->wwpn);
Martin Peschke9467a9b2008-03-27 14:22:03 +0100429 if (zfcp_erp_port_reopen(port, 0, 64, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 ZFCP_LOG_NORMAL("failed reopen of port "
431 "(adapter %s, wwpn=0x%016Lx)\n",
432 zfcp_get_busid_by_port(port),
433 port->wwpn);
434 }
435
436 out:
437 zfcp_port_put(port);
Jens Axboe73fc4f02007-10-23 09:17:53 +0200438 __free_pages(sg_page(send_els->req), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 kfree(send_els->req);
440 kfree(send_els->resp);
441 kfree(send_els);
442}
443
444
445/**
446 * zfcp_test_link - lightweight link test procedure
447 * @port: port to be tested
448 *
449 * Test status of a link to a remote port using the ELS command ADISC.
450 */
451int
452zfcp_test_link(struct zfcp_port *port)
453{
454 int retval;
455
456 zfcp_port_get(port);
Andreas Herrmann64b29a132005-06-13 13:18:56 +0200457 retval = zfcp_erp_adisc(port);
Christof Schmitt3f0ca622007-12-20 12:30:25 +0100458 if (retval != 0 && retval != -EBUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 zfcp_port_put(port);
460 ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
461 "on adapter %s\n ", port->wwpn,
462 zfcp_get_busid_by_port(port));
Martin Peschke9467a9b2008-03-27 14:22:03 +0100463 retval = zfcp_erp_port_forced_reopen(port, 0, 65, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 if (retval != 0) {
465 ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx "
466 "on adapter %s failed\n", port->wwpn,
467 zfcp_get_busid_by_port(port));
468 retval = -EPERM;
469 }
470 }
471
472 return retval;
473}
474
475
476/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200477 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 *
479 * purpose: called if a port failed to be opened normally
480 * initiates Forced Reopen recovery which is done
481 * asynchronously
482 *
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200483 * returns: 0 - initiated action successfully
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 * <0 - failed to initiate action
485 */
Martin Peschke9467a9b2008-03-27 14:22:03 +0100486static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port,
487 int clear_mask, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
489 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
491 ZFCP_LOG_DEBUG("forced reopen of port 0x%016Lx on adapter %s\n",
492 port->wwpn, zfcp_get_busid_by_port(port));
493
494 zfcp_erp_port_block(port, clear_mask);
495
496 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) {
497 ZFCP_LOG_DEBUG("skipped forced reopen of failed port 0x%016Lx "
498 "on adapter %s\n", port->wwpn,
499 zfcp_get_busid_by_port(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 retval = -EIO;
501 goto out;
502 }
503
504 retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
Martin Peschke9467a9b2008-03-27 14:22:03 +0100505 port->adapter, port, NULL, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 out:
508 return retval;
509}
510
511/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200512 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 *
514 * purpose: Wrappper for zfcp_erp_port_forced_reopen_internal
515 * used to ensure the correct locking
516 *
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200517 * returns: 0 - initiated action successfully
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 * <0 - failed to initiate action
519 */
Martin Peschke9467a9b2008-03-27 14:22:03 +0100520int zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask, u8 id,
521 u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522{
523 int retval;
524 unsigned long flags;
525 struct zfcp_adapter *adapter;
526
527 adapter = port->adapter;
528 read_lock_irqsave(&zfcp_data.config_lock, flags);
529 write_lock(&adapter->erp_lock);
Martin Peschke9467a9b2008-03-27 14:22:03 +0100530 retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask, id,
531 ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 write_unlock(&adapter->erp_lock);
533 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
534
535 return retval;
536}
537
538/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200539 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 *
541 * purpose: called if a port is to be opened
542 * initiates Reopen recovery which is done
543 * asynchronously
544 *
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200545 * returns: 0 - initiated action successfully
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 * <0 - failed to initiate action
547 */
Martin Peschke9467a9b2008-03-27 14:22:03 +0100548static int zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask,
549 u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
551 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
553 ZFCP_LOG_DEBUG("reopen of port 0x%016Lx on adapter %s\n",
554 port->wwpn, zfcp_get_busid_by_port(port));
555
556 zfcp_erp_port_block(port, clear_mask);
557
558 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) {
559 ZFCP_LOG_DEBUG("skipped reopen of failed port 0x%016Lx "
560 "on adapter %s\n", port->wwpn,
561 zfcp_get_busid_by_port(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 /* ensure propagation of failed status to new devices */
Martin Peschke698ec0162008-03-27 14:22:02 +0100563 zfcp_erp_port_failed(port, 14, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 retval = -EIO;
565 goto out;
566 }
567
568 retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
Martin Peschke9467a9b2008-03-27 14:22:03 +0100569 port->adapter, port, NULL, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570
571 out:
572 return retval;
573}
574
575/**
576 * zfcp_erp_port_reopen - initiate reopen of a remote port
577 * @port: port to be reopened
578 * @clear_mask: specifies flags in port status to be cleared
579 * Return: 0 on success, < 0 on error
580 *
581 * This is a wrappper function for zfcp_erp_port_reopen_internal. It ensures
582 * correct locking. An error recovery task is initiated to do the reopen.
583 * To wait for the completion of the reopen zfcp_erp_wait should be used.
584 */
Martin Peschke9467a9b2008-03-27 14:22:03 +0100585int zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
587 int retval;
588 unsigned long flags;
589 struct zfcp_adapter *adapter = port->adapter;
590
591 read_lock_irqsave(&zfcp_data.config_lock, flags);
592 write_lock(&adapter->erp_lock);
Martin Peschke9467a9b2008-03-27 14:22:03 +0100593 retval = zfcp_erp_port_reopen_internal(port, clear_mask, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 write_unlock(&adapter->erp_lock);
595 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
596
597 return retval;
598}
599
600/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200601 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 *
603 * purpose: called if a unit is to be opened
604 * initiates Reopen recovery which is done
605 * asynchronously
606 *
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200607 * returns: 0 - initiated action successfully
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 * <0 - failed to initiate action
609 */
Martin Peschke9467a9b2008-03-27 14:22:03 +0100610static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask,
611 u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
613 int retval;
614 struct zfcp_adapter *adapter = unit->port->adapter;
615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 ZFCP_LOG_DEBUG("reopen of unit 0x%016Lx on port 0x%016Lx "
617 "on adapter %s\n", unit->fcp_lun,
618 unit->port->wwpn, zfcp_get_busid_by_unit(unit));
619
620 zfcp_erp_unit_block(unit, clear_mask);
621
622 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) {
623 ZFCP_LOG_DEBUG("skipped reopen of failed unit 0x%016Lx "
624 "on port 0x%016Lx on adapter %s\n",
625 unit->fcp_lun, unit->port->wwpn,
626 zfcp_get_busid_by_unit(unit));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 retval = -EIO;
628 goto out;
629 }
630
631 retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
Martin Peschke9467a9b2008-03-27 14:22:03 +0100632 adapter, unit->port, unit, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 out:
634 return retval;
635}
636
637/**
638 * zfcp_erp_unit_reopen - initiate reopen of a unit
639 * @unit: unit to be reopened
640 * @clear_mask: specifies flags in unit status to be cleared
641 * Return: 0 on success, < 0 on error
642 *
643 * This is a wrappper for zfcp_erp_unit_reopen_internal. It ensures correct
644 * locking. An error recovery task is initiated to do the reopen.
645 * To wait for the completion of the reopen zfcp_erp_wait should be used.
646 */
Martin Peschke9467a9b2008-03-27 14:22:03 +0100647int zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
649 int retval;
650 unsigned long flags;
651 struct zfcp_adapter *adapter;
652 struct zfcp_port *port;
653
654 port = unit->port;
655 adapter = port->adapter;
656
657 read_lock_irqsave(&zfcp_data.config_lock, flags);
658 write_lock(&adapter->erp_lock);
Martin Peschke9467a9b2008-03-27 14:22:03 +0100659 retval = zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 write_unlock(&adapter->erp_lock);
661 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
662
663 return retval;
664}
665
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200666/**
667 * zfcp_erp_adapter_block - mark adapter as blocked, block scsi requests
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 */
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200669static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670{
Martin Peschke698ec0162008-03-27 14:22:02 +0100671 zfcp_erp_modify_adapter_status(adapter, 15, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 ZFCP_STATUS_COMMON_UNBLOCKED |
673 clear_mask, ZFCP_CLEAR);
674}
675
Martin Peschke698ec0162008-03-27 14:22:02 +0100676/* FIXME: isn't really atomic */
677/*
678 * returns the mask which has not been set so far, i.e.
679 * 0 if no bit has been changed, !0 if some bit has been changed
680 */
681static int atomic_test_and_set_mask(unsigned long mask, atomic_t *v)
682{
683 int changed_bits = (atomic_read(v) /*XOR*/^ mask) & mask;
684 atomic_set_mask(mask, v);
685 return changed_bits;
686}
687
688/* FIXME: isn't really atomic */
689/*
690 * returns the mask which has not been cleared so far, i.e.
691 * 0 if no bit has been changed, !0 if some bit has been changed
692 */
693static int atomic_test_and_clear_mask(unsigned long mask, atomic_t *v)
694{
695 int changed_bits = atomic_read(v) & mask;
696 atomic_clear_mask(mask, v);
697 return changed_bits;
698}
699
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200700/**
701 * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 */
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200703static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704{
Martin Peschke698ec0162008-03-27 14:22:02 +0100705 if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
706 &adapter->status))
707 zfcp_rec_dbf_event_adapter(16, 0, adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708}
709
710/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200711 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 *
713 * purpose: disable I/O,
714 * return any open requests and clean them up,
715 * aim: no pending and incoming I/O
716 *
717 * returns:
718 */
719static void
720zfcp_erp_port_block(struct zfcp_port *port, int clear_mask)
721{
Martin Peschke698ec0162008-03-27 14:22:02 +0100722 zfcp_erp_modify_port_status(port, 17, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
724 ZFCP_CLEAR);
725}
726
727/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200728 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 *
730 * purpose: enable I/O
731 *
732 * returns:
733 */
734static void
735zfcp_erp_port_unblock(struct zfcp_port *port)
736{
Martin Peschke698ec0162008-03-27 14:22:02 +0100737 if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
738 &port->status))
739 zfcp_rec_dbf_event_port(18, 0, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740}
741
742/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200743 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 *
745 * purpose: disable I/O,
746 * return any open requests and clean them up,
747 * aim: no pending and incoming I/O
748 *
749 * returns:
750 */
751static void
752zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
753{
Martin Peschke698ec0162008-03-27 14:22:02 +0100754 zfcp_erp_modify_unit_status(unit, 19, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
756 ZFCP_CLEAR);
757}
758
759/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200760 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 *
762 * purpose: enable I/O
763 *
764 * returns:
765 */
766static void
767zfcp_erp_unit_unblock(struct zfcp_unit *unit)
768{
Martin Peschke698ec0162008-03-27 14:22:02 +0100769 if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
770 &unit->status))
771 zfcp_rec_dbf_event_unit(20, 0, unit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772}
773
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774static void
775zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
776{
777 struct zfcp_adapter *adapter = erp_action->adapter;
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 zfcp_erp_action_to_ready(erp_action);
780 up(&adapter->erp_ready_sem);
Martin Peschke348447e2008-03-27 14:22:01 +0100781 zfcp_rec_dbf_event_thread(2, adapter, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782}
783
784/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200785 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 *
787 * purpose:
788 *
789 * returns: <0 erp_action not found in any list
790 * ZFCP_ERP_ACTION_READY erp_action is in ready list
791 * ZFCP_ERP_ACTION_RUNNING erp_action is in running list
792 *
793 * locks: erp_lock must be held
794 */
795static int
796zfcp_erp_action_exists(struct zfcp_erp_action *erp_action)
797{
798 int retval = -EINVAL;
799 struct list_head *entry;
800 struct zfcp_erp_action *entry_erp_action;
801 struct zfcp_adapter *adapter = erp_action->adapter;
802
803 /* search in running list */
804 list_for_each(entry, &adapter->erp_running_head) {
805 entry_erp_action =
806 list_entry(entry, struct zfcp_erp_action, list);
807 if (entry_erp_action == erp_action) {
808 retval = ZFCP_ERP_ACTION_RUNNING;
809 goto out;
810 }
811 }
812 /* search in ready list */
813 list_for_each(entry, &adapter->erp_ready_head) {
814 entry_erp_action =
815 list_entry(entry, struct zfcp_erp_action, list);
816 if (entry_erp_action == erp_action) {
817 retval = ZFCP_ERP_ACTION_READY;
818 goto out;
819 }
820 }
821
822 out:
823 return retval;
824}
825
826/*
827 * purpose: checks current status of action (timed out, dismissed, ...)
828 * and does appropriate preparations (dismiss fsf request, ...)
829 *
830 * locks: called under erp_lock (disabled interrupts)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 */
Swen Schilligca880cf2007-02-09 10:00:14 +0100832static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
834{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 struct zfcp_adapter *adapter = erp_action->adapter;
836
837 if (erp_action->fsf_req) {
Volker Sameskefea9d6c2006-08-02 11:05:16 +0200838 /* take lock to ensure that request is not deleted meanwhile */
839 spin_lock(&adapter->req_list_lock);
Heiko Carstensd1ad09d2007-12-20 12:30:22 +0100840 if (zfcp_reqlist_find_safe(adapter, erp_action->fsf_req) &&
841 erp_action->fsf_req->erp_action == erp_action) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 /* fsf_req still exists */
Volker Sameskefea9d6c2006-08-02 11:05:16 +0200843 /* dismiss fsf_req of timed out/dismissed erp_action */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
845 ZFCP_STATUS_ERP_TIMEDOUT)) {
Swen Schilligca880cf2007-02-09 10:00:14 +0100846 erp_action->fsf_req->status |=
847 ZFCP_STATUS_FSFREQ_DISMISSED;
Martin Peschke6f4f3652008-03-27 14:22:04 +0100848 zfcp_rec_dbf_event_action(142, erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 }
850 if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
Martin Peschke6f4f3652008-03-27 14:22:04 +0100851 zfcp_rec_dbf_event_action(143, erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 ZFCP_LOG_NORMAL("error: erp step timed out "
853 "(action=%d, fsf_req=%p)\n ",
854 erp_action->action,
855 erp_action->fsf_req);
856 }
857 /*
858 * If fsf_req is neither dismissed nor completed
859 * then keep it running asynchronously and don't mess
860 * with the association of erp_action and fsf_req.
861 */
Swen Schilligca880cf2007-02-09 10:00:14 +0100862 if (erp_action->fsf_req->status &
863 (ZFCP_STATUS_FSFREQ_COMPLETED |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 ZFCP_STATUS_FSFREQ_DISMISSED)) {
865 /* forget about association between fsf_req
866 and erp_action */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 erp_action->fsf_req = NULL;
868 }
869 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 /*
871 * even if this fsf_req has gone, forget about
872 * association between erp_action and fsf_req
873 */
874 erp_action->fsf_req = NULL;
875 }
Volker Sameskefea9d6c2006-08-02 11:05:16 +0200876 spin_unlock(&adapter->req_list_lock);
Martin Peschke507e4962008-03-27 14:22:05 +0100877 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878}
879
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200880/**
881 * zfcp_erp_async_handler_nolock - complete erp_action
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 *
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200883 * Used for normal completion, time-out, dismissal and failure after
884 * low memory condition.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 */
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200886static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
887 unsigned long set_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 erp_action->status |= set_mask;
891 zfcp_erp_action_ready(erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 } else {
893 /* action is ready or gone - nothing to do */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895}
896
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200897/**
898 * zfcp_erp_async_handler - wrapper for erp_async_handler_nolock w/ locking
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 */
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200900void zfcp_erp_async_handler(struct zfcp_erp_action *erp_action,
901 unsigned long set_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902{
903 struct zfcp_adapter *adapter = erp_action->adapter;
904 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 write_lock_irqsave(&adapter->erp_lock, flags);
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200907 zfcp_erp_async_handler_nolock(erp_action, set_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 write_unlock_irqrestore(&adapter->erp_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909}
910
911/*
912 * purpose: is called for erp_action which was slept waiting for
913 * memory becoming avaliable,
914 * will trigger that this action will be continued
915 */
916static void
917zfcp_erp_memwait_handler(unsigned long data)
918{
919 struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
921 zfcp_erp_async_handler(erp_action, 0);
922}
923
924/*
925 * purpose: is called if an asynchronous erp step timed out,
926 * action gets an appropriate flag and will be processed
927 * accordingly
928 */
Heiko Carstens364c8552007-10-12 16:11:35 +0200929static void zfcp_erp_timeout_handler(unsigned long data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930{
931 struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932
933 zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT);
934}
935
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200936/**
937 * zfcp_erp_action_dismiss - dismiss an erp_action
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 *
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200939 * adapter->erp_lock must be held
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200940 *
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200941 * Dismissal of an erp_action is usually required if an erp_action of
942 * higher priority is generated.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 */
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200944static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945{
Martin Peschked0076f72007-11-15 13:57:08 +0100946 erp_action->status |= ZFCP_STATUS_ERP_DISMISSED;
947 if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING)
948 zfcp_erp_action_ready(erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949}
950
951int
952zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
953{
954 int retval = 0;
955
956 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
957
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
959 if (retval < 0) {
960 ZFCP_LOG_NORMAL("error: creation of erp thread failed for "
961 "adapter %s\n",
962 zfcp_get_busid_by_adapter(adapter));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 } else {
964 wait_event(adapter->erp_thread_wqh,
965 atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
966 &adapter->status));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 }
968
969 return (retval < 0);
970}
971
972/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200973 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +0200975 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 *
977 * returns:
978 *
979 * context: process (i.e. proc-fs or rmmod/insmod)
980 *
981 * note: The caller of this routine ensures that the specified
982 * adapter has been shut down and that this operation
983 * has been completed. Thus, there are no pending erp_actions
984 * which would need to be handled here.
985 */
986int
987zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
988{
989 int retval = 0;
990
991 atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
992 up(&adapter->erp_ready_sem);
Martin Peschke348447e2008-03-27 14:22:01 +0100993 zfcp_rec_dbf_event_thread(2, adapter, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
995 wait_event(adapter->erp_thread_wqh,
996 !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
997 &adapter->status));
998
999 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
1000 &adapter->status);
1001
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 return retval;
1003}
1004
1005/*
1006 * purpose: is run as a kernel thread,
1007 * goes through list of error recovery actions of associated adapter
1008 * and delegates single action to execution
1009 *
1010 * returns: 0
1011 */
1012static int
1013zfcp_erp_thread(void *data)
1014{
1015 struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
1016 struct list_head *next;
1017 struct zfcp_erp_action *erp_action;
1018 unsigned long flags;
1019
1020 daemonize("zfcperp%s", zfcp_get_busid_by_adapter(adapter));
1021 /* Block all signals */
1022 siginitsetinv(&current->blocked, 0);
1023 atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 wake_up(&adapter->erp_thread_wqh);
1025
1026 while (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
1027 &adapter->status)) {
1028
1029 write_lock_irqsave(&adapter->erp_lock, flags);
Martin Peschke86e8dfc2007-11-15 13:57:17 +01001030 next = adapter->erp_ready_head.next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 write_unlock_irqrestore(&adapter->erp_lock, flags);
1032
1033 if (next != &adapter->erp_ready_head) {
1034 erp_action =
1035 list_entry(next, struct zfcp_erp_action, list);
1036 /*
1037 * process action (incl. [re]moving it
1038 * from 'ready' queue)
1039 */
1040 zfcp_erp_strategy(erp_action);
1041 }
1042
1043 /*
1044 * sleep as long as there is nothing to do, i.e.
1045 * no action in 'ready' queue to be processed and
1046 * thread is not to be killed
1047 */
Martin Peschke348447e2008-03-27 14:22:01 +01001048 zfcp_rec_dbf_event_thread(4, adapter, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 down_interruptible(&adapter->erp_ready_sem);
Martin Peschke348447e2008-03-27 14:22:01 +01001050 zfcp_rec_dbf_event_thread(5, adapter, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 }
1052
1053 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 wake_up(&adapter->erp_thread_wqh);
1055
1056 return 0;
1057}
1058
1059/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001060 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 *
1062 * purpose: drives single error recovery action and schedules higher and
1063 * subordinate actions, if necessary
1064 *
1065 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
1066 * ZFCP_ERP_SUCCEEDED - action finished successfully (deqd)
1067 * ZFCP_ERP_FAILED - action finished unsuccessfully (deqd)
1068 * ZFCP_ERP_EXIT - action finished (dequeued), offline
1069 * ZFCP_ERP_DISMISSED - action canceled (dequeued)
1070 */
1071static int
1072zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
1073{
1074 int retval = 0;
1075 struct zfcp_adapter *adapter = erp_action->adapter;
1076 struct zfcp_port *port = erp_action->port;
1077 struct zfcp_unit *unit = erp_action->unit;
1078 int action = erp_action->action;
1079 u32 status = erp_action->status;
1080 unsigned long flags;
1081
1082 /* serialise dismissing, timing out, moving, enqueueing */
1083 read_lock_irqsave(&zfcp_data.config_lock, flags);
1084 write_lock(&adapter->erp_lock);
1085
1086 /* dequeue dismissed action and leave, if required */
1087 retval = zfcp_erp_strategy_check_action(erp_action, retval);
1088 if (retval == ZFCP_ERP_DISMISSED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 goto unlock;
1090 }
1091
1092 /*
1093 * move action to 'running' queue before processing it
1094 * (to avoid a race condition regarding moving the
1095 * action to the 'running' queue and back)
1096 */
1097 zfcp_erp_action_to_running(erp_action);
1098
1099 /*
1100 * try to process action as far as possible,
1101 * no lock to allow for blocking operations (kmalloc, qdio, ...),
1102 * afterwards the lock is required again for the following reasons:
1103 * - dequeueing of finished action and enqueueing of
1104 * follow-up actions must be atomic so that any other
1105 * reopen-routine does not believe there is nothing to do
1106 * and that it is safe to enqueue something else,
1107 * - we want to force any control thread which is dismissing
1108 * actions to finish this before we decide about
1109 * necessary steps to be taken here further
1110 */
1111 write_unlock(&adapter->erp_lock);
1112 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1113 retval = zfcp_erp_strategy_do_action(erp_action);
1114 read_lock_irqsave(&zfcp_data.config_lock, flags);
1115 write_lock(&adapter->erp_lock);
1116
1117 /*
1118 * check for dismissed status again to avoid follow-up actions,
Martin Peschke86e8dfc2007-11-15 13:57:17 +01001119 * failing of targets and so on for dismissed actions,
1120 * we go through down() here because there has been an up()
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 */
Martin Peschke86e8dfc2007-11-15 13:57:17 +01001122 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
1123 retval = ZFCP_ERP_CONTINUES;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
1125 switch (retval) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 case ZFCP_ERP_NOMEM:
1127 /* no memory to continue immediately, let it sleep */
1128 if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) {
1129 ++adapter->erp_low_mem_count;
1130 erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;
1131 }
1132 /* This condition is true if there is no memory available
1133 for any erp_action on this adapter. This implies that there
1134 are no elements in the memory pool(s) left for erp_actions.
1135 This might happen if an erp_action that used a memory pool
1136 element was timed out.
1137 */
1138 if (adapter->erp_total_count == adapter->erp_low_mem_count) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 ZFCP_LOG_NORMAL("error: no mempool elements available, "
1140 "restarting I/O on adapter %s "
1141 "to free mempool\n",
1142 zfcp_get_busid_by_adapter(adapter));
Martin Peschke9467a9b2008-03-27 14:22:03 +01001143 zfcp_erp_adapter_reopen_internal(adapter, 0, 66, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 retval = zfcp_erp_strategy_memwait(erp_action);
1146 }
1147 goto unlock;
1148 case ZFCP_ERP_CONTINUES:
1149 /* leave since this action runs asynchronously */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
1151 --adapter->erp_low_mem_count;
1152 erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
1153 }
1154 goto unlock;
1155 }
1156 /* ok, finished action (whatever its result is) */
1157
1158 /* check for unrecoverable targets */
1159 retval = zfcp_erp_strategy_check_target(erp_action, retval);
1160
1161 /* action must be dequeued (here to allow for further ones) */
1162 zfcp_erp_action_dequeue(erp_action);
1163
1164 /*
1165 * put this target through the erp mill again if someone has
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001166 * requested to change the status of a target being online
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 * to offline or the other way around
1168 * (old retval is preserved if nothing has to be done here)
1169 */
1170 retval = zfcp_erp_strategy_statechange(action, status, adapter,
1171 port, unit, retval);
1172
1173 /*
1174 * leave if target is in permanent error state or if
1175 * action is repeated in order to process state change
1176 */
1177 if (retval == ZFCP_ERP_EXIT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 goto unlock;
1179 }
1180
1181 /* trigger follow up actions */
1182 zfcp_erp_strategy_followup_actions(action, adapter, port, unit, retval);
1183
1184 unlock:
1185 write_unlock(&adapter->erp_lock);
1186 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001187
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 if (retval != ZFCP_ERP_CONTINUES)
1189 zfcp_erp_action_cleanup(action, adapter, port, unit, retval);
1190
1191 /*
1192 * a few tasks remain when the erp queues are empty
1193 * (don't do that if the last action evaluated was dismissed
1194 * since this clearly indicates that there is more to come) :
1195 * - close the name server port if it is open yet
1196 * (enqueues another [probably] final action)
1197 * - otherwise, wake up whoever wants to be woken when we are
1198 * done with erp
1199 */
1200 if (retval != ZFCP_ERP_DISMISSED)
1201 zfcp_erp_strategy_check_queues(adapter);
1202
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 return retval;
1204}
1205
1206/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001207 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001209 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 *
1211 * returns: ZFCP_ERP_DISMISSED - if action has been dismissed
1212 * retval - otherwise
1213 */
1214static int
1215zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval)
1216{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 zfcp_erp_strategy_check_fsfreq(erp_action);
1218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 zfcp_erp_action_dequeue(erp_action);
1221 retval = ZFCP_ERP_DISMISSED;
Martin Peschke507e4962008-03-27 14:22:05 +01001222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
1224 return retval;
1225}
1226
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227static int
1228zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
1229{
1230 int retval = ZFCP_ERP_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 /*
1233 * try to execute/continue action as far as possible,
1234 * note: no lock in subsequent strategy routines
1235 * (this allows these routine to call schedule, e.g.
1236 * kmalloc with such flags or qdio_initialize & friends)
Joe Perches5d67d162008-01-26 14:11:20 +01001237 * Note: in case of timeout, the separate strategies will fail
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 * anyhow. No need for a special action. Even worse, a nameserver
1239 * failure would not wake up waiting ports without the call.
1240 */
1241 switch (erp_action->action) {
1242
1243 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1244 retval = zfcp_erp_adapter_strategy(erp_action);
1245 break;
1246
1247 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1248 retval = zfcp_erp_port_forced_strategy(erp_action);
1249 break;
1250
1251 case ZFCP_ERP_ACTION_REOPEN_PORT:
1252 retval = zfcp_erp_port_strategy(erp_action);
1253 break;
1254
1255 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1256 retval = zfcp_erp_unit_strategy(erp_action);
1257 break;
1258
1259 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 ZFCP_LOG_NORMAL("bug: unknown erp action requested on "
1261 "adapter %s (action=%d)\n",
1262 zfcp_get_busid_by_adapter(erp_action->adapter),
1263 erp_action->action);
1264 }
1265
1266 return retval;
1267}
1268
1269/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001270 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 *
1272 * purpose: triggers retry of this action after a certain amount of time
1273 * by means of timer provided by erp_action
1274 *
1275 * returns: ZFCP_ERP_CONTINUES - erp_action sleeps in erp running queue
1276 */
1277static int
1278zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
1279{
1280 int retval = ZFCP_ERP_CONTINUES;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 init_timer(&erp_action->timer);
1283 erp_action->timer.function = zfcp_erp_memwait_handler;
1284 erp_action->timer.data = (unsigned long) erp_action;
1285 erp_action->timer.expires = jiffies + ZFCP_ERP_MEMWAIT_TIMEOUT;
1286 add_timer(&erp_action->timer);
1287
1288 return retval;
1289}
1290
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001291/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 * function: zfcp_erp_adapter_failed
1293 *
1294 * purpose: sets the adapter and all underlying devices to ERP_FAILED
1295 *
1296 */
1297void
Martin Peschke698ec0162008-03-27 14:22:02 +01001298zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299{
Martin Peschke698ec0162008-03-27 14:22:02 +01001300 zfcp_erp_modify_adapter_status(adapter, id, ref,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
1302 ZFCP_LOG_NORMAL("adapter erp failed on adapter %s\n",
1303 zfcp_get_busid_by_adapter(adapter));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304}
1305
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001306/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 * function: zfcp_erp_port_failed
1308 *
1309 * purpose: sets the port and all underlying devices to ERP_FAILED
1310 *
1311 */
1312void
Martin Peschke698ec0162008-03-27 14:22:02 +01001313zfcp_erp_port_failed(struct zfcp_port *port, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314{
Martin Peschke698ec0162008-03-27 14:22:02 +01001315 zfcp_erp_modify_port_status(port, id, ref,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
1317
1318 if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
1319 ZFCP_LOG_NORMAL("port erp failed (adapter %s, "
Christof Schmitt1d589ed2007-05-08 11:14:41 +02001320 "port d_id=0x%06x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 zfcp_get_busid_by_port(port), port->d_id);
1322 else
1323 ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n",
1324 zfcp_get_busid_by_port(port), port->wwpn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325}
1326
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001327/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 * function: zfcp_erp_unit_failed
1329 *
1330 * purpose: sets the unit to ERP_FAILED
1331 *
1332 */
1333void
Martin Peschke698ec0162008-03-27 14:22:02 +01001334zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
Martin Peschke698ec0162008-03-27 14:22:02 +01001336 zfcp_erp_modify_unit_status(unit, id, ref,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
1338
1339 ZFCP_LOG_NORMAL("unit erp failed on unit 0x%016Lx on port 0x%016Lx "
1340 " on adapter %s\n", unit->fcp_lun,
1341 unit->port->wwpn, zfcp_get_busid_by_unit(unit));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342}
1343
1344/*
1345 * function: zfcp_erp_strategy_check_target
1346 *
1347 * purpose: increments the erp action count on the device currently in
1348 * recovery if the action failed or resets the count in case of
1349 * success. If a maximum count is exceeded the device is marked
1350 * as ERP_FAILED.
1351 * The 'blocked' state of a target which has been recovered
1352 * successfully is reset.
1353 *
1354 * returns: ZFCP_ERP_CONTINUES - action continues (not considered)
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001355 * ZFCP_ERP_SUCCEEDED - action finished successfully
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 * ZFCP_ERP_EXIT - action failed and will not continue
1357 */
1358static int
1359zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result)
1360{
1361 struct zfcp_adapter *adapter = erp_action->adapter;
1362 struct zfcp_port *port = erp_action->port;
1363 struct zfcp_unit *unit = erp_action->unit;
1364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 switch (erp_action->action) {
1366
1367 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1368 result = zfcp_erp_strategy_check_unit(unit, result);
1369 break;
1370
1371 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1372 case ZFCP_ERP_ACTION_REOPEN_PORT:
1373 result = zfcp_erp_strategy_check_port(port, result);
1374 break;
1375
1376 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1377 result = zfcp_erp_strategy_check_adapter(adapter, result);
1378 break;
1379 }
1380
1381 return result;
1382}
1383
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384static int
1385zfcp_erp_strategy_statechange(int action,
1386 u32 status,
1387 struct zfcp_adapter *adapter,
1388 struct zfcp_port *port,
1389 struct zfcp_unit *unit, int retval)
1390{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 switch (action) {
1392
1393 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1394 if (zfcp_erp_strategy_statechange_detected(&adapter->status,
1395 status)) {
Martin Peschke9467a9b2008-03-27 14:22:03 +01001396 zfcp_erp_adapter_reopen_internal(adapter,
1397 ZFCP_STATUS_COMMON_ERP_FAILED,
1398 67, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 retval = ZFCP_ERP_EXIT;
1400 }
1401 break;
1402
1403 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1404 case ZFCP_ERP_ACTION_REOPEN_PORT:
1405 if (zfcp_erp_strategy_statechange_detected(&port->status,
1406 status)) {
Martin Peschke9467a9b2008-03-27 14:22:03 +01001407 zfcp_erp_port_reopen_internal(port,
1408 ZFCP_STATUS_COMMON_ERP_FAILED,
1409 68, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 retval = ZFCP_ERP_EXIT;
1411 }
1412 break;
1413
1414 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1415 if (zfcp_erp_strategy_statechange_detected(&unit->status,
1416 status)) {
Martin Peschke9467a9b2008-03-27 14:22:03 +01001417 zfcp_erp_unit_reopen_internal(unit,
1418 ZFCP_STATUS_COMMON_ERP_FAILED,
1419 69, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 retval = ZFCP_ERP_EXIT;
1421 }
1422 break;
1423 }
1424
1425 return retval;
1426}
1427
Heiko Carstens364c8552007-10-12 16:11:35 +02001428static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status)
1430{
1431 return
1432 /* take it online */
1433 (atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) &&
1434 (ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)) ||
1435 /* take it offline */
1436 (!atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) &&
1437 !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status));
1438}
1439
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440static int
1441zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
1442{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 switch (result) {
1444 case ZFCP_ERP_SUCCEEDED :
1445 atomic_set(&unit->erp_counter, 0);
1446 zfcp_erp_unit_unblock(unit);
1447 break;
1448 case ZFCP_ERP_FAILED :
1449 atomic_inc(&unit->erp_counter);
1450 if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS)
Martin Peschke698ec0162008-03-27 14:22:02 +01001451 zfcp_erp_unit_failed(unit, 21, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 break;
1453 case ZFCP_ERP_EXIT :
1454 /* nothing */
1455 break;
1456 }
1457
1458 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) {
1459 zfcp_erp_unit_block(unit, 0); /* for ZFCP_ERP_SUCCEEDED */
1460 result = ZFCP_ERP_EXIT;
1461 }
1462
1463 return result;
1464}
1465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466static int
1467zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
1468{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 switch (result) {
1470 case ZFCP_ERP_SUCCEEDED :
1471 atomic_set(&port->erp_counter, 0);
1472 zfcp_erp_port_unblock(port);
1473 break;
1474 case ZFCP_ERP_FAILED :
1475 atomic_inc(&port->erp_counter);
1476 if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
Martin Peschke698ec0162008-03-27 14:22:02 +01001477 zfcp_erp_port_failed(port, 22, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 break;
1479 case ZFCP_ERP_EXIT :
1480 /* nothing */
1481 break;
1482 }
1483
1484 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) {
1485 zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */
1486 result = ZFCP_ERP_EXIT;
1487 }
1488
1489 return result;
1490}
1491
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492static int
1493zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
1494{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 switch (result) {
1496 case ZFCP_ERP_SUCCEEDED :
1497 atomic_set(&adapter->erp_counter, 0);
1498 zfcp_erp_adapter_unblock(adapter);
1499 break;
1500 case ZFCP_ERP_FAILED :
1501 atomic_inc(&adapter->erp_counter);
1502 if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS)
Martin Peschke698ec0162008-03-27 14:22:02 +01001503 zfcp_erp_adapter_failed(adapter, 23, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 break;
1505 case ZFCP_ERP_EXIT :
1506 /* nothing */
1507 break;
1508 }
1509
1510 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) {
1511 zfcp_erp_adapter_block(adapter, 0); /* for ZFCP_ERP_SUCCEEDED */
1512 result = ZFCP_ERP_EXIT;
1513 }
1514
1515 return result;
1516}
1517
Christof Schmitt5f852be2007-05-08 11:16:52 +02001518struct zfcp_erp_add_work {
1519 struct zfcp_unit *unit;
1520 struct work_struct work;
1521};
1522
1523/**
1524 * zfcp_erp_scsi_scan
1525 * @data: pointer to a struct zfcp_erp_add_work
1526 *
1527 * Registers a logical unit with the SCSI stack.
1528 */
1529static void zfcp_erp_scsi_scan(struct work_struct *work)
1530{
1531 struct zfcp_erp_add_work *p =
1532 container_of(work, struct zfcp_erp_add_work, work);
1533 struct zfcp_unit *unit = p->unit;
1534 struct fc_rport *rport = unit->port->rport;
1535 scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
1536 unit->scsi_lun, 0);
1537 atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
Christof Schmitt5f852be2007-05-08 11:16:52 +02001538 zfcp_unit_put(unit);
1539 kfree(p);
1540}
1541
1542/**
1543 * zfcp_erp_schedule_work
1544 * @unit: pointer to unit which should be registered with SCSI stack
1545 *
1546 * Schedules work which registers a unit with the SCSI stack
1547 */
1548static void
1549zfcp_erp_schedule_work(struct zfcp_unit *unit)
1550{
1551 struct zfcp_erp_add_work *p;
1552
Swen Schillig0d661322007-07-18 10:55:08 +02001553 p = kzalloc(sizeof(*p), GFP_KERNEL);
Christof Schmitt5f852be2007-05-08 11:16:52 +02001554 if (!p) {
1555 ZFCP_LOG_NORMAL("error: Out of resources. Could not register "
1556 "the FCP-LUN 0x%Lx connected to "
1557 "the port with WWPN 0x%Lx connected to "
1558 "the adapter %s with the SCSI stack.\n",
1559 unit->fcp_lun,
1560 unit->port->wwpn,
1561 zfcp_get_busid_by_unit(unit));
1562 return;
1563 }
1564
1565 zfcp_unit_get(unit);
Christof Schmitt5f852be2007-05-08 11:16:52 +02001566 atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
1567 INIT_WORK(&p->work, zfcp_erp_scsi_scan);
1568 p->unit = unit;
1569 schedule_work(&p->work);
1570}
1571
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001573 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 *
1575 * purpose: remaining things in good cases,
1576 * escalation in bad cases
1577 *
1578 * returns:
1579 */
1580static int
1581zfcp_erp_strategy_followup_actions(int action,
1582 struct zfcp_adapter *adapter,
1583 struct zfcp_port *port,
1584 struct zfcp_unit *unit, int status)
1585{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 /* initiate follow-up actions depending on success of finished action */
1587 switch (action) {
1588
1589 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1590 if (status == ZFCP_ERP_SUCCEEDED)
Martin Peschke9467a9b2008-03-27 14:22:03 +01001591 zfcp_erp_port_reopen_all_internal(adapter, 0, 70, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 else
Martin Peschke9467a9b2008-03-27 14:22:03 +01001593 zfcp_erp_adapter_reopen_internal(adapter, 0, 71, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 break;
1595
1596 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1597 if (status == ZFCP_ERP_SUCCEEDED)
Martin Peschke9467a9b2008-03-27 14:22:03 +01001598 zfcp_erp_port_reopen_internal(port, 0, 72, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 else
Martin Peschke9467a9b2008-03-27 14:22:03 +01001600 zfcp_erp_adapter_reopen_internal(adapter, 0, 73, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 break;
1602
1603 case ZFCP_ERP_ACTION_REOPEN_PORT:
1604 if (status == ZFCP_ERP_SUCCEEDED)
Martin Peschke9467a9b2008-03-27 14:22:03 +01001605 zfcp_erp_unit_reopen_all_internal(port, 0, 74, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 else
Martin Peschke9467a9b2008-03-27 14:22:03 +01001607 zfcp_erp_port_forced_reopen_internal(port, 0, 75, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 break;
1609
1610 case ZFCP_ERP_ACTION_REOPEN_UNIT:
Heiko Carstenscc16ceb2007-08-28 09:30:42 +02001611 /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */
1612 if (status != ZFCP_ERP_SUCCEEDED)
Martin Peschke9467a9b2008-03-27 14:22:03 +01001613 zfcp_erp_port_reopen_internal(unit->port, 0, 76, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 break;
1615 }
1616
1617 return 0;
1618}
1619
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620static int
1621zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter)
1622{
1623 unsigned long flags;
1624
1625 read_lock_irqsave(&zfcp_data.config_lock, flags);
1626 read_lock(&adapter->erp_lock);
1627 if (list_empty(&adapter->erp_ready_head) &&
1628 list_empty(&adapter->erp_running_head)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
1630 &adapter->status);
1631 wake_up(&adapter->erp_done_wqh);
Martin Peschke507e4962008-03-27 14:22:05 +01001632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 read_unlock(&adapter->erp_lock);
1634 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1635
1636 return 0;
1637}
1638
1639/**
1640 * zfcp_erp_wait - wait for completion of error recovery on an adapter
1641 * @adapter: adapter for which to wait for completion of its error recovery
1642 * Return: 0
1643 */
1644int
1645zfcp_erp_wait(struct zfcp_adapter *adapter)
1646{
1647 int retval = 0;
1648
1649 wait_event(adapter->erp_done_wqh,
1650 !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
1651 &adapter->status));
1652
1653 return retval;
1654}
1655
Martin Peschke698ec0162008-03-27 14:22:02 +01001656void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id,
1657 u64 ref, u32 mask, int set_or_clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658{
1659 struct zfcp_port *port;
Martin Peschke698ec0162008-03-27 14:22:02 +01001660 u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
1662 if (set_or_clear == ZFCP_SET) {
Martin Peschke698ec0162008-03-27 14:22:02 +01001663 changed = atomic_test_and_set_mask(mask, &adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 } else {
Martin Peschke698ec0162008-03-27 14:22:02 +01001665 changed = atomic_test_and_clear_mask(mask, &adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
1667 atomic_set(&adapter->erp_counter, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 }
Martin Peschke698ec0162008-03-27 14:22:02 +01001669 if (changed)
1670 zfcp_rec_dbf_event_adapter(id, ref, adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
1672 /* Deal with all underlying devices, only pass common_mask */
1673 if (common_mask)
1674 list_for_each_entry(port, &adapter->port_list_head, list)
Martin Peschke698ec0162008-03-27 14:22:02 +01001675 zfcp_erp_modify_port_status(port, id, ref, common_mask,
1676 set_or_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677}
1678
1679/*
1680 * function: zfcp_erp_modify_port_status
1681 *
1682 * purpose: sets the port and all underlying devices to ERP_FAILED
1683 *
1684 */
Martin Peschke698ec0162008-03-27 14:22:02 +01001685void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, u64 ref,
1686 u32 mask, int set_or_clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687{
1688 struct zfcp_unit *unit;
Martin Peschke698ec0162008-03-27 14:22:02 +01001689 u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690
1691 if (set_or_clear == ZFCP_SET) {
Martin Peschke698ec0162008-03-27 14:22:02 +01001692 changed = atomic_test_and_set_mask(mask, &port->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 } else {
Martin Peschke698ec0162008-03-27 14:22:02 +01001694 changed = atomic_test_and_clear_mask(mask, &port->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
1696 atomic_set(&port->erp_counter, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 }
Martin Peschke698ec0162008-03-27 14:22:02 +01001698 if (changed)
1699 zfcp_rec_dbf_event_port(id, ref, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
1701 /* Modify status of all underlying devices, only pass common mask */
1702 if (common_mask)
1703 list_for_each_entry(unit, &port->unit_list_head, list)
Martin Peschke698ec0162008-03-27 14:22:02 +01001704 zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
1705 set_or_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706}
1707
1708/*
1709 * function: zfcp_erp_modify_unit_status
1710 *
1711 * purpose: sets the unit to ERP_FAILED
1712 *
1713 */
Martin Peschke698ec0162008-03-27 14:22:02 +01001714void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, u64 ref,
1715 u32 mask, int set_or_clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716{
Martin Peschke698ec0162008-03-27 14:22:02 +01001717 u32 changed;
1718
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 if (set_or_clear == ZFCP_SET) {
Martin Peschke698ec0162008-03-27 14:22:02 +01001720 changed = atomic_test_and_set_mask(mask, &unit->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 } else {
Martin Peschke698ec0162008-03-27 14:22:02 +01001722 changed = atomic_test_and_clear_mask(mask, &unit->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
1724 atomic_set(&unit->erp_counter, 0);
1725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 }
Martin Peschke698ec0162008-03-27 14:22:02 +01001727 if (changed)
1728 zfcp_rec_dbf_event_unit(id, ref, unit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729}
1730
1731/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001732 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 *
1734 * purpose: Wrappper for zfcp_erp_port_reopen_all_internal
1735 * used to ensure the correct locking
1736 *
Andreas Mohrd6e05ed2006-06-26 18:35:02 +02001737 * returns: 0 - initiated action successfully
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 * <0 - failed to initiate action
1739 */
Martin Peschke9467a9b2008-03-27 14:22:03 +01001740int zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask,
1741 u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742{
1743 int retval;
1744 unsigned long flags;
1745
1746 read_lock_irqsave(&zfcp_data.config_lock, flags);
1747 write_lock(&adapter->erp_lock);
Martin Peschke9467a9b2008-03-27 14:22:03 +01001748 retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask, id,
1749 ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 write_unlock(&adapter->erp_lock);
1751 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1752
1753 return retval;
1754}
1755
Martin Peschke9467a9b2008-03-27 14:22:03 +01001756static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter,
1757 int clear_mask, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758{
1759 int retval = 0;
1760 struct zfcp_port *port;
1761
1762 list_for_each_entry(port, &adapter->port_list_head, list)
1763 if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
Martin Peschke9467a9b2008-03-27 14:22:03 +01001764 zfcp_erp_port_reopen_internal(port, clear_mask, id,
1765 ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
1767 return retval;
1768}
1769
1770/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001771 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001773 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 *
1775 * returns: FIXME
1776 */
Martin Peschke9467a9b2008-03-27 14:22:03 +01001777static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port,
1778 int clear_mask, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779{
1780 int retval = 0;
1781 struct zfcp_unit *unit;
1782
1783 list_for_each_entry(unit, &port->unit_list_head, list)
Martin Peschke9467a9b2008-03-27 14:22:03 +01001784 zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
1786 return retval;
1787}
1788
1789/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001790 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 *
1792 * purpose: this routine executes the 'Reopen Adapter' action
1793 * (the entire action is processed synchronously, since
1794 * there are no actions which might be run concurrently
1795 * per definition)
1796 *
1797 * returns: ZFCP_ERP_SUCCEEDED - action finished successfully
1798 * ZFCP_ERP_FAILED - action finished unsuccessfully
1799 */
1800static int
1801zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action)
1802{
1803 int retval;
1804 struct zfcp_adapter *adapter = erp_action->adapter;
1805
1806 retval = zfcp_erp_adapter_strategy_close(erp_action);
1807 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
1808 retval = ZFCP_ERP_EXIT;
1809 else
1810 retval = zfcp_erp_adapter_strategy_open(erp_action);
1811
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 if (retval == ZFCP_ERP_FAILED) {
1813 ZFCP_LOG_INFO("Waiting to allow the adapter %s "
1814 "to recover itself\n",
1815 zfcp_get_busid_by_adapter(adapter));
Christof Schmitt18edcdb2007-11-05 12:37:45 +01001816 ssleep(ZFCP_TYPE2_RECOVERY_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 }
1818
1819 return retval;
1820}
1821
1822/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001823 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001825 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 *
1827 * returns: ZFCP_ERP_SUCCEEDED - action finished successfully
1828 * ZFCP_ERP_FAILED - action finished unsuccessfully
1829 */
1830static int
1831zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *erp_action)
1832{
1833 int retval;
1834
1835 atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING,
1836 &erp_action->adapter->status);
1837 retval = zfcp_erp_adapter_strategy_generic(erp_action, 1);
1838 atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING,
1839 &erp_action->adapter->status);
1840
1841 return retval;
1842}
1843
1844/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001845 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001847 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 *
1849 * returns: ZFCP_ERP_SUCCEEDED - action finished successfully
1850 * ZFCP_ERP_FAILED - action finished unsuccessfully
1851 */
1852static int
1853zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *erp_action)
1854{
1855 int retval;
1856
1857 atomic_set_mask(ZFCP_STATUS_COMMON_OPENING,
1858 &erp_action->adapter->status);
1859 retval = zfcp_erp_adapter_strategy_generic(erp_action, 0);
1860 atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING,
1861 &erp_action->adapter->status);
1862
1863 return retval;
1864}
1865
1866/*
1867 * function: zfcp_register_adapter
1868 *
1869 * purpose: allocate the irq associated with this devno and register
1870 * the FSF adapter with the SCSI stack
1871 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001872 * returns:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 */
1874static int
1875zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close)
1876{
1877 int retval = ZFCP_ERP_SUCCEEDED;
1878
1879 if (close)
1880 goto close_only;
1881
1882 retval = zfcp_erp_adapter_strategy_open_qdio(erp_action);
1883 if (retval != ZFCP_ERP_SUCCEEDED)
1884 goto failed_qdio;
1885
1886 retval = zfcp_erp_adapter_strategy_open_fsf(erp_action);
1887 if (retval != ZFCP_ERP_SUCCEEDED)
1888 goto failed_openfcp;
1889
1890 atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &erp_action->adapter->status);
1891 goto out;
1892
1893 close_only:
1894 atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1895 &erp_action->adapter->status);
1896
1897 failed_openfcp:
Andreas Herrmann2abbe862006-09-18 22:29:56 +02001898 zfcp_close_fsf(erp_action->adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 failed_qdio:
Volker Sameskec7f6b3a2007-05-29 15:29:49 +02001900 atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
1901 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
1902 ZFCP_STATUS_ADAPTER_XPORT_OK,
1903 &erp_action->adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 out:
1905 return retval;
1906}
1907
1908/*
1909 * function: zfcp_qdio_init
1910 *
1911 * purpose: setup QDIO operation for specified adapter
1912 *
1913 * returns: 0 - successful setup
1914 * !0 - failed setup
1915 */
Heiko Carstens364c8552007-10-12 16:11:35 +02001916static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
1918{
1919 int retval;
1920 int i;
1921 volatile struct qdio_buffer_element *sbale;
1922 struct zfcp_adapter *adapter = erp_action->adapter;
1923
1924 if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) {
1925 ZFCP_LOG_NORMAL("bug: second attempt to set up QDIO on "
1926 "adapter %s\n",
1927 zfcp_get_busid_by_adapter(adapter));
1928 goto failed_sanity;
1929 }
1930
1931 if (qdio_establish(&adapter->qdio_init_data) != 0) {
1932 ZFCP_LOG_INFO("error: establishment of QDIO queues failed "
1933 "on adapter %s\n",
1934 zfcp_get_busid_by_adapter(adapter));
1935 goto failed_qdio_establish;
1936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937
1938 if (qdio_activate(adapter->ccw_device, 0) != 0) {
1939 ZFCP_LOG_INFO("error: activation of QDIO queues failed "
1940 "on adapter %s\n",
1941 zfcp_get_busid_by_adapter(adapter));
1942 goto failed_qdio_activate;
1943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
1945 /*
1946 * put buffers into response queue,
1947 */
1948 for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
1949 sbale = &(adapter->response_queue.buffer[i]->element[0]);
1950 sbale->length = 0;
1951 sbale->flags = SBAL_FLAGS_LAST_ENTRY;
Al Viro6aae8732006-10-10 22:44:27 +01001952 sbale->addr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 }
1954
1955 ZFCP_LOG_TRACE("calling do_QDIO on adapter %s (flags=0x%x, "
1956 "queue_no=%i, index_in_queue=%i, count=%i)\n",
1957 zfcp_get_busid_by_adapter(adapter),
1958 QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q);
1959
1960 retval = do_QDIO(adapter->ccw_device,
1961 QDIO_FLAG_SYNC_INPUT,
1962 0, 0, QDIO_MAX_BUFFERS_PER_Q, NULL);
1963
1964 if (retval) {
1965 ZFCP_LOG_NORMAL("bug: setup of QDIO failed (retval=%d)\n",
1966 retval);
1967 goto failed_do_qdio;
1968 } else {
1969 adapter->response_queue.free_index = 0;
1970 atomic_set(&adapter->response_queue.free_count, 0);
1971 ZFCP_LOG_DEBUG("%i buffers successfully enqueued to "
1972 "response queue\n", QDIO_MAX_BUFFERS_PER_Q);
1973 }
1974 /* set index of first avalable SBALS / number of available SBALS */
1975 adapter->request_queue.free_index = 0;
1976 atomic_set(&adapter->request_queue.free_count, QDIO_MAX_BUFFERS_PER_Q);
1977 adapter->request_queue.distance_from_int = 0;
1978
1979 /* initialize waitqueue used to wait for free SBALs in requests queue */
1980 init_waitqueue_head(&adapter->request_wq);
1981
1982 /* ok, we did it - skip all cleanups for different failures */
1983 atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
1984 retval = ZFCP_ERP_SUCCEEDED;
1985 goto out;
1986
1987 failed_do_qdio:
1988 /* NOP */
1989
1990 failed_qdio_activate:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 while (qdio_shutdown(adapter->ccw_device,
1992 QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
Christof Schmitt18edcdb2007-11-05 12:37:45 +01001993 ssleep(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
1995 failed_qdio_establish:
1996 failed_sanity:
1997 retval = ZFCP_ERP_FAILED;
1998
1999 out:
2000 return retval;
2001}
2002
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004static int
2005zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
2006{
Andreas Herrmann2448c452005-12-01 02:50:36 +01002007 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008
Andreas Herrmann2448c452005-12-01 02:50:36 +01002009 retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
2010 if (retval == ZFCP_ERP_FAILED)
2011 return ZFCP_ERP_FAILED;
2012
2013 retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
2014 if (retval == ZFCP_ERP_FAILED)
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02002015 return ZFCP_ERP_FAILED;
2016
2017 return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018}
2019
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020static int
2021zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
2022{
2023 int retval = ZFCP_ERP_SUCCEEDED;
2024 int retries;
Andreas Herrmann22753fa2005-06-13 13:15:15 +02002025 int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 struct zfcp_adapter *adapter = erp_action->adapter;
2027
2028 atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
Andreas Herrmann22753fa2005-06-13 13:15:15 +02002030 for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
2032 &adapter->status);
2033 ZFCP_LOG_DEBUG("Doing exchange config data\n");
Heiko Carstens9f09c542006-07-03 17:32:20 -07002034 write_lock_irq(&adapter->erp_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 zfcp_erp_action_to_running(erp_action);
Heiko Carstens9f09c542006-07-03 17:32:20 -07002036 write_unlock_irq(&adapter->erp_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 if (zfcp_fsf_exchange_config_data(erp_action)) {
2038 retval = ZFCP_ERP_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 ZFCP_LOG_INFO("error: initiation of exchange of "
2040 "configuration data failed for "
2041 "adapter %s\n",
2042 zfcp_get_busid_by_adapter(adapter));
2043 break;
2044 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 ZFCP_LOG_DEBUG("Xchange underway\n");
2046
2047 /*
2048 * Why this works:
2049 * Both the normal completion handler as well as the timeout
2050 * handler will do an 'up' when the 'exchange config data'
2051 * request completes or times out. Thus, the signal to go on
2052 * won't be lost utilizing this semaphore.
2053 * Furthermore, this 'adapter_reopen' action is
2054 * guaranteed to be the only action being there (highest action
2055 * which prevents other actions from being created).
2056 * Resulting from that, the wake signal recognized here
2057 * _must_ be the one belonging to the 'exchange config
2058 * data' request.
2059 */
Martin Peschke348447e2008-03-27 14:22:01 +01002060 zfcp_rec_dbf_event_thread(6, adapter, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 down(&adapter->erp_ready_sem);
Martin Peschke348447e2008-03-27 14:22:01 +01002062 zfcp_rec_dbf_event_thread(7, adapter, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
2064 ZFCP_LOG_INFO("error: exchange of configuration data "
2065 "for adapter %s timed out\n",
2066 zfcp_get_busid_by_adapter(adapter));
2067 break;
2068 }
Andreas Herrmann22753fa2005-06-13 13:15:15 +02002069
2070 if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
2071 &adapter->status))
2072 break;
2073
2074 ZFCP_LOG_DEBUG("host connection still initialising... "
2075 "waiting and retrying...\n");
2076 /* sleep a little bit before retry */
Christof Schmitt18edcdb2007-11-05 12:37:45 +01002077 ssleep(sleep);
Andreas Herrmann22753fa2005-06-13 13:15:15 +02002078 sleep *= 2;
2079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080
Volker Sameskec7f6b3a2007-05-29 15:29:49 +02002081 atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
2082 &adapter->status);
2083
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
2085 &adapter->status)) {
2086 ZFCP_LOG_INFO("error: exchange of configuration data for "
2087 "adapter %s failed\n",
2088 zfcp_get_busid_by_adapter(adapter));
2089 retval = ZFCP_ERP_FAILED;
2090 }
2091
2092 return retval;
2093}
2094
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02002095static int
2096zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
2097{
Andreas Herrmann2448c452005-12-01 02:50:36 +01002098 int ret;
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002099 struct zfcp_adapter *adapter;
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02002100
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002101 adapter = erp_action->adapter;
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02002102 atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
2103
Heiko Carstens9f09c542006-07-03 17:32:20 -07002104 write_lock_irq(&adapter->erp_lock);
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002105 zfcp_erp_action_to_running(erp_action);
Heiko Carstens9f09c542006-07-03 17:32:20 -07002106 write_unlock_irq(&adapter->erp_lock);
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02002107
Swen Schillig52ef11a2007-08-28 09:31:09 +02002108 ret = zfcp_fsf_exchange_port_data(erp_action);
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002109 if (ret == -EOPNOTSUPP) {
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002110 return ZFCP_ERP_SUCCEEDED;
2111 } else if (ret) {
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002112 return ZFCP_ERP_FAILED;
2113 }
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02002114
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002115 ret = ZFCP_ERP_SUCCEEDED;
Martin Peschke348447e2008-03-27 14:22:01 +01002116 zfcp_rec_dbf_event_thread(8, adapter, 1);
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002117 down(&adapter->erp_ready_sem);
Martin Peschke348447e2008-03-27 14:22:01 +01002118 zfcp_rec_dbf_event_thread(9, adapter, 1);
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002119 if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
2120 ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
2121 "%s)\n", zfcp_get_busid_by_adapter(adapter));
2122 ret = ZFCP_ERP_FAILED;
2123 }
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +02002124
2125 /* don't treat as error for the sake of compatibility */
2126 if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status))
2127 ZFCP_LOG_INFO("warning: exchange port data failed (adapter "
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002128 "%s\n", zfcp_get_busid_by_adapter(adapter));
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02002129
Andreas Herrmann2f8f3ed2006-02-11 01:41:50 +01002130 return ret;
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02002131}
2132
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133static int
2134zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action
2135 *erp_action)
2136{
2137 int retval = ZFCP_ERP_SUCCEEDED;
2138 int temp_ret;
2139 struct zfcp_adapter *adapter = erp_action->adapter;
2140 int i;
2141
2142 adapter->status_read_failed = 0;
2143 for (i = 0; i < ZFCP_STATUS_READS_RECOM; i++) {
2144 temp_ret = zfcp_fsf_status_read(adapter, ZFCP_WAIT_FOR_SBAL);
2145 if (temp_ret < 0) {
2146 ZFCP_LOG_INFO("error: set-up of unsolicited status "
2147 "notification failed on adapter %s\n",
2148 zfcp_get_busid_by_adapter(adapter));
2149 retval = ZFCP_ERP_FAILED;
2150 i--;
2151 break;
2152 }
2153 }
2154
2155 return retval;
2156}
2157
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002159 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 *
2161 * purpose: this routine executes the 'Reopen Physical Port' action
2162 *
2163 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2164 * ZFCP_ERP_SUCCEEDED - action finished successfully
2165 * ZFCP_ERP_FAILED - action finished unsuccessfully
2166 */
2167static int
2168zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
2169{
2170 int retval = ZFCP_ERP_FAILED;
2171 struct zfcp_port *port = erp_action->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172
2173 switch (erp_action->step) {
2174
2175 /*
2176 * FIXME:
2177 * the ULP spec. begs for waiting for oustanding commands
2178 */
2179 case ZFCP_ERP_STEP_UNINITIALIZED:
2180 zfcp_erp_port_strategy_clearstati(port);
2181 /*
2182 * it would be sufficient to test only the normal open flag
2183 * since the phys. open flag cannot be set if the normal
2184 * open flag is unset - however, this is for readabilty ...
2185 */
2186 if (atomic_test_mask((ZFCP_STATUS_PORT_PHYS_OPEN |
2187 ZFCP_STATUS_COMMON_OPEN),
2188 &port->status)) {
2189 ZFCP_LOG_DEBUG("port 0x%016Lx is open -> trying "
2190 "close physical\n", port->wwpn);
2191 retval =
2192 zfcp_erp_port_forced_strategy_close(erp_action);
2193 } else
2194 retval = ZFCP_ERP_FAILED;
2195 break;
2196
2197 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
2198 if (atomic_test_mask(ZFCP_STATUS_PORT_PHYS_OPEN,
2199 &port->status)) {
2200 ZFCP_LOG_DEBUG("close physical failed for port "
2201 "0x%016Lx\n", port->wwpn);
2202 retval = ZFCP_ERP_FAILED;
2203 } else
2204 retval = ZFCP_ERP_SUCCEEDED;
2205 break;
2206 }
2207
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 return retval;
2209}
2210
2211/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002212 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 *
2214 * purpose: this routine executes the 'Reopen Port' action
2215 *
2216 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2217 * ZFCP_ERP_SUCCEEDED - action finished successfully
2218 * ZFCP_ERP_FAILED - action finished unsuccessfully
2219 */
2220static int
2221zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
2222{
2223 int retval = ZFCP_ERP_FAILED;
2224 struct zfcp_port *port = erp_action->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
2226 switch (erp_action->step) {
2227
2228 /*
2229 * FIXME:
2230 * the ULP spec. begs for waiting for oustanding commands
2231 */
2232 case ZFCP_ERP_STEP_UNINITIALIZED:
2233 zfcp_erp_port_strategy_clearstati(port);
2234 if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) {
2235 ZFCP_LOG_DEBUG("port 0x%016Lx is open -> trying "
2236 "close\n", port->wwpn);
2237 retval = zfcp_erp_port_strategy_close(erp_action);
2238 goto out;
2239 } /* else it's already closed, open it */
2240 break;
2241
2242 case ZFCP_ERP_STEP_PORT_CLOSING:
2243 if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) {
2244 ZFCP_LOG_DEBUG("close failed for port 0x%016Lx\n",
2245 port->wwpn);
2246 retval = ZFCP_ERP_FAILED;
2247 goto out;
2248 } /* else it's closed now, open it */
2249 break;
2250 }
2251 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
2252 retval = ZFCP_ERP_EXIT;
2253 else
2254 retval = zfcp_erp_port_strategy_open(erp_action);
2255
2256 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 return retval;
2258}
2259
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260static int
2261zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action)
2262{
2263 int retval;
2264
2265 if (atomic_test_mask(ZFCP_STATUS_PORT_WKA,
2266 &erp_action->port->status))
2267 retval = zfcp_erp_port_strategy_open_nameserver(erp_action);
2268 else
2269 retval = zfcp_erp_port_strategy_open_common(erp_action);
2270
2271 return retval;
2272}
2273
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274static int
2275zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
2276{
2277 int retval = 0;
2278 struct zfcp_adapter *adapter = erp_action->adapter;
2279 struct zfcp_port *port = erp_action->port;
2280
2281 switch (erp_action->step) {
2282
2283 case ZFCP_ERP_STEP_UNINITIALIZED:
2284 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
2285 case ZFCP_ERP_STEP_PORT_CLOSING:
Andreas Herrmannad757cd2006-01-13 02:26:11 +01002286 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) {
6f71d9b2005-04-10 23:04:28 -05002287 if (port->wwpn != adapter->peer_wwpn) {
2288 ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "
2289 "on adapter %s.\nPeer WWPN "
2290 "0x%016Lx does not match\n",
2291 port->wwpn,
2292 zfcp_get_busid_by_adapter(adapter),
2293 adapter->peer_wwpn);
Martin Peschke698ec0162008-03-27 14:22:02 +01002294 zfcp_erp_port_failed(port, 25, 0);
6f71d9b2005-04-10 23:04:28 -05002295 retval = ZFCP_ERP_FAILED;
2296 break;
2297 }
2298 port->d_id = adapter->peer_d_id;
2299 atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
2300 retval = zfcp_erp_port_strategy_open_port(erp_action);
2301 break;
2302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 if (!(adapter->nameserver_port)) {
2304 retval = zfcp_nameserver_enqueue(adapter);
2305 if (retval != 0) {
2306 ZFCP_LOG_NORMAL("error: nameserver port "
2307 "unavailable for adapter %s\n",
2308 zfcp_get_busid_by_adapter(adapter));
2309 retval = ZFCP_ERP_FAILED;
2310 break;
2311 }
2312 }
2313 if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
2314 &adapter->nameserver_port->status)) {
2315 ZFCP_LOG_DEBUG("nameserver port is not open -> open "
2316 "nameserver port\n");
2317 /* nameserver port may live again */
2318 atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING,
2319 &adapter->nameserver_port->status);
Martin Peschke9467a9b2008-03-27 14:22:03 +01002320 if (zfcp_erp_port_reopen(adapter->nameserver_port, 0,
2321 77, (u64)erp_action) >= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 erp_action->step =
2323 ZFCP_ERP_STEP_NAMESERVER_OPEN;
2324 retval = ZFCP_ERP_CONTINUES;
2325 } else
2326 retval = ZFCP_ERP_FAILED;
2327 break;
2328 }
2329 /* else nameserver port is already open, fall through */
2330 case ZFCP_ERP_STEP_NAMESERVER_OPEN:
2331 if (!atomic_test_mask(ZFCP_STATUS_COMMON_OPEN,
2332 &adapter->nameserver_port->status)) {
2333 ZFCP_LOG_DEBUG("open failed for nameserver port\n");
2334 retval = ZFCP_ERP_FAILED;
2335 } else {
2336 ZFCP_LOG_DEBUG("nameserver port is open -> "
2337 "nameserver look-up for port 0x%016Lx\n",
2338 port->wwpn);
2339 retval = zfcp_erp_port_strategy_open_common_lookup
2340 (erp_action);
2341 }
2342 break;
2343
2344 case ZFCP_ERP_STEP_NAMESERVER_LOOKUP:
2345 if (!atomic_test_mask(ZFCP_STATUS_PORT_DID_DID, &port->status)) {
2346 if (atomic_test_mask
2347 (ZFCP_STATUS_PORT_INVALID_WWPN, &port->status)) {
2348 ZFCP_LOG_DEBUG("nameserver look-up failed "
2349 "for port 0x%016Lx "
2350 "(misconfigured WWPN?)\n",
2351 port->wwpn);
Martin Peschke698ec0162008-03-27 14:22:02 +01002352 zfcp_erp_port_failed(port, 26, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 retval = ZFCP_ERP_EXIT;
2354 } else {
2355 ZFCP_LOG_DEBUG("nameserver look-up failed for "
2356 "port 0x%016Lx\n", port->wwpn);
2357 retval = ZFCP_ERP_FAILED;
2358 }
2359 } else {
Christof Schmitt1d589ed2007-05-08 11:14:41 +02002360 ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 "trying open\n", port->wwpn, port->d_id);
2362 retval = zfcp_erp_port_strategy_open_port(erp_action);
2363 }
2364 break;
2365
2366 case ZFCP_ERP_STEP_PORT_OPENING:
2367 /* D_ID might have changed during open */
2368 if (atomic_test_mask((ZFCP_STATUS_COMMON_OPEN |
2369 ZFCP_STATUS_PORT_DID_DID),
2370 &port->status)) {
2371 ZFCP_LOG_DEBUG("port 0x%016Lx is open\n", port->wwpn);
2372 retval = ZFCP_ERP_SUCCEEDED;
2373 } else {
2374 ZFCP_LOG_DEBUG("open failed for port 0x%016Lx\n",
2375 port->wwpn);
2376 retval = ZFCP_ERP_FAILED;
2377 }
2378 break;
2379
2380 default:
2381 ZFCP_LOG_NORMAL("bug: unknown erp step 0x%08x\n",
2382 erp_action->step);
2383 retval = ZFCP_ERP_FAILED;
2384 }
2385
2386 return retval;
2387}
2388
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389static int
2390zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action)
2391{
2392 int retval;
2393 struct zfcp_port *port = erp_action->port;
2394
2395 switch (erp_action->step) {
2396
2397 case ZFCP_ERP_STEP_UNINITIALIZED:
2398 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
2399 case ZFCP_ERP_STEP_PORT_CLOSING:
Christof Schmitt1d589ed2007-05-08 11:14:41 +02002400 ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> trying open\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 port->wwpn, port->d_id);
2402 retval = zfcp_erp_port_strategy_open_port(erp_action);
2403 break;
2404
2405 case ZFCP_ERP_STEP_PORT_OPENING:
2406 if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) {
2407 ZFCP_LOG_DEBUG("WKA port is open\n");
2408 retval = ZFCP_ERP_SUCCEEDED;
2409 } else {
2410 ZFCP_LOG_DEBUG("open failed for WKA port\n");
2411 retval = ZFCP_ERP_FAILED;
2412 }
2413 /* this is needed anyway (dont care for retval of wakeup) */
2414 ZFCP_LOG_DEBUG("continue other open port operations\n");
2415 zfcp_erp_port_strategy_open_nameserver_wakeup(erp_action);
2416 break;
2417
2418 default:
2419 ZFCP_LOG_NORMAL("bug: unknown erp step 0x%08x\n",
2420 erp_action->step);
2421 retval = ZFCP_ERP_FAILED;
2422 }
2423
2424 return retval;
2425}
2426
2427/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002428 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 *
2430 * purpose: makes the erp thread continue with reopen (physical) port
2431 * actions which have been paused until the name server port
2432 * is opened (or failed)
2433 *
2434 * returns: 0 (a kind of void retval, its not used)
2435 */
2436static int
2437zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action
2438 *ns_erp_action)
2439{
2440 int retval = 0;
2441 unsigned long flags;
2442 struct zfcp_adapter *adapter = ns_erp_action->adapter;
2443 struct zfcp_erp_action *erp_action, *tmp;
2444
2445 read_lock_irqsave(&adapter->erp_lock, flags);
2446 list_for_each_entry_safe(erp_action, tmp, &adapter->erp_running_head,
2447 list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 if (erp_action->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 if (atomic_test_mask(
2450 ZFCP_STATUS_COMMON_ERP_FAILED,
2451 &adapter->nameserver_port->status))
Martin Peschke698ec0162008-03-27 14:22:02 +01002452 zfcp_erp_port_failed(erp_action->port, 27, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 zfcp_erp_action_ready(erp_action);
2454 }
2455 }
2456 read_unlock_irqrestore(&adapter->erp_lock, flags);
2457
2458 return retval;
2459}
2460
2461/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002462 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002464 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 *
2466 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2467 * ZFCP_ERP_FAILED - action finished unsuccessfully
2468 */
2469static int
2470zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action)
2471{
2472 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 retval = zfcp_fsf_close_physical_port(erp_action);
2475 if (retval == -ENOMEM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 retval = ZFCP_ERP_NOMEM;
2477 goto out;
2478 }
2479 erp_action->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING;
2480 if (retval != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 /* could not send 'open', fail */
2482 retval = ZFCP_ERP_FAILED;
2483 goto out;
2484 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 retval = ZFCP_ERP_CONTINUES;
2486 out:
2487 return retval;
2488}
2489
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490static int
2491zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
2492{
2493 int retval = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
2495 atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
2496 ZFCP_STATUS_COMMON_CLOSING |
2497 ZFCP_STATUS_COMMON_ACCESS_DENIED |
2498 ZFCP_STATUS_PORT_DID_DID |
2499 ZFCP_STATUS_PORT_PHYS_CLOSING |
2500 ZFCP_STATUS_PORT_INVALID_WWPN,
2501 &port->status);
2502 return retval;
2503}
2504
2505/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002506 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002508 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 *
2510 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2511 * ZFCP_ERP_FAILED - action finished unsuccessfully
2512 */
2513static int
2514zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
2515{
2516 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 retval = zfcp_fsf_close_port(erp_action);
2519 if (retval == -ENOMEM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 retval = ZFCP_ERP_NOMEM;
2521 goto out;
2522 }
2523 erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING;
2524 if (retval != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 /* could not send 'close', fail */
2526 retval = ZFCP_ERP_FAILED;
2527 goto out;
2528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 retval = ZFCP_ERP_CONTINUES;
2530 out:
2531 return retval;
2532}
2533
2534/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002535 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002537 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 *
2539 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2540 * ZFCP_ERP_FAILED - action finished unsuccessfully
2541 */
2542static int
2543zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
2544{
2545 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 retval = zfcp_fsf_open_port(erp_action);
2548 if (retval == -ENOMEM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 retval = ZFCP_ERP_NOMEM;
2550 goto out;
2551 }
2552 erp_action->step = ZFCP_ERP_STEP_PORT_OPENING;
2553 if (retval != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 /* could not send 'open', fail */
2555 retval = ZFCP_ERP_FAILED;
2556 goto out;
2557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 retval = ZFCP_ERP_CONTINUES;
2559 out:
2560 return retval;
2561}
2562
2563/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002564 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002566 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 *
2568 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2569 * ZFCP_ERP_FAILED - action finished unsuccessfully
2570 */
2571static int
2572zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action)
2573{
2574 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 retval = zfcp_ns_gid_pn_request(erp_action);
2577 if (retval == -ENOMEM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 retval = ZFCP_ERP_NOMEM;
2579 goto out;
2580 }
2581 erp_action->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
2582 if (retval != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 /* could not send nameserver request, fail */
2584 retval = ZFCP_ERP_FAILED;
2585 goto out;
2586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 retval = ZFCP_ERP_CONTINUES;
2588 out:
2589 return retval;
2590}
2591
2592/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002593 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 *
2595 * purpose: this routine executes the 'Reopen Unit' action
2596 * currently no retries
2597 *
2598 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2599 * ZFCP_ERP_SUCCEEDED - action finished successfully
2600 * ZFCP_ERP_FAILED - action finished unsuccessfully
2601 */
2602static int
2603zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
2604{
2605 int retval = ZFCP_ERP_FAILED;
2606 struct zfcp_unit *unit = erp_action->unit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
2608 switch (erp_action->step) {
2609
2610 /*
2611 * FIXME:
2612 * the ULP spec. begs for waiting for oustanding commands
2613 */
2614 case ZFCP_ERP_STEP_UNINITIALIZED:
2615 zfcp_erp_unit_strategy_clearstati(unit);
2616 if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) {
2617 ZFCP_LOG_DEBUG("unit 0x%016Lx is open -> "
2618 "trying close\n", unit->fcp_lun);
2619 retval = zfcp_erp_unit_strategy_close(erp_action);
2620 break;
2621 }
2622 /* else it's already closed, fall through */
2623 case ZFCP_ERP_STEP_UNIT_CLOSING:
2624 if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) {
2625 ZFCP_LOG_DEBUG("close failed for unit 0x%016Lx\n",
2626 unit->fcp_lun);
2627 retval = ZFCP_ERP_FAILED;
2628 } else {
2629 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
2630 retval = ZFCP_ERP_EXIT;
2631 else {
2632 ZFCP_LOG_DEBUG("unit 0x%016Lx is not open -> "
2633 "trying open\n", unit->fcp_lun);
2634 retval =
2635 zfcp_erp_unit_strategy_open(erp_action);
2636 }
2637 }
2638 break;
2639
2640 case ZFCP_ERP_STEP_UNIT_OPENING:
2641 if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) {
2642 ZFCP_LOG_DEBUG("unit 0x%016Lx is open\n",
2643 unit->fcp_lun);
2644 retval = ZFCP_ERP_SUCCEEDED;
2645 } else {
2646 ZFCP_LOG_DEBUG("open failed for unit 0x%016Lx\n",
2647 unit->fcp_lun);
2648 retval = ZFCP_ERP_FAILED;
2649 }
2650 break;
2651 }
2652
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 return retval;
2654}
2655
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656static int
2657zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
2658{
2659 int retval = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660
2661 atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
2662 ZFCP_STATUS_COMMON_CLOSING |
2663 ZFCP_STATUS_COMMON_ACCESS_DENIED |
2664 ZFCP_STATUS_UNIT_SHARED |
2665 ZFCP_STATUS_UNIT_READONLY,
2666 &unit->status);
2667
2668 return retval;
2669}
2670
2671/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002672 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002674 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 *
2676 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2677 * ZFCP_ERP_FAILED - action finished unsuccessfully
2678 */
2679static int
2680zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
2681{
2682 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 retval = zfcp_fsf_close_unit(erp_action);
2685 if (retval == -ENOMEM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 retval = ZFCP_ERP_NOMEM;
2687 goto out;
2688 }
2689 erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
2690 if (retval != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 /* could not send 'close', fail */
2692 retval = ZFCP_ERP_FAILED;
2693 goto out;
2694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 retval = ZFCP_ERP_CONTINUES;
2696
2697 out:
2698 return retval;
2699}
2700
2701/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002702 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 *
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002704 * purpose:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 *
2706 * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously)
2707 * ZFCP_ERP_FAILED - action finished unsuccessfully
2708 */
2709static int
2710zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
2711{
2712 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 retval = zfcp_fsf_open_unit(erp_action);
2715 if (retval == -ENOMEM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 retval = ZFCP_ERP_NOMEM;
2717 goto out;
2718 }
2719 erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
2720 if (retval != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 /* could not send 'open', fail */
2722 retval = ZFCP_ERP_FAILED;
2723 goto out;
2724 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 retval = ZFCP_ERP_CONTINUES;
2726 out:
2727 return retval;
2728}
2729
Andreas Herrmann2abbe862006-09-18 22:29:56 +02002730void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731{
Andreas Herrmann2abbe862006-09-18 22:29:56 +02002732 BUG_ON(!fsf_req->erp_action);
2733 fsf_req->timer.function = zfcp_erp_timeout_handler;
2734 fsf_req->timer.data = (unsigned long) fsf_req->erp_action;
2735 fsf_req->timer.expires = jiffies + ZFCP_ERP_FSFREQ_TIMEOUT;
2736 add_timer(&fsf_req->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737}
2738
2739/*
Swen Schillig41fa2ad2007-09-07 09:15:31 +02002740 * function:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 *
2742 * purpose: enqueue the specified error recovery action, if needed
2743 *
2744 * returns:
2745 */
Martin Peschke9467a9b2008-03-27 14:22:03 +01002746static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
2747 struct zfcp_port *port,
2748 struct zfcp_unit *unit, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749{
Martin Peschke9467a9b2008-03-27 14:22:03 +01002750 int retval = 1, need = want;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 struct zfcp_erp_action *erp_action = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 u32 status = 0;
2753
2754 /*
2755 * We need some rules here which check whether we really need
2756 * this action or whether we should just drop it.
2757 * E.g. if there is a unfinished 'Reopen Port' request then we drop a
2758 * 'Reopen Unit' request for an associated unit since we can't
2759 * satisfy this request now. A 'Reopen Port' action will trigger
2760 * 'Reopen Unit' actions when it completes.
2761 * Thus, there are only actions in the queue which can immediately be
2762 * executed. This makes the processing of the action queue more
2763 * efficient.
2764 */
2765
2766 if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
2767 &adapter->status))
2768 return -EIO;
2769
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 /* check whether we really need this */
Martin Peschke9467a9b2008-03-27 14:22:03 +01002771 switch (want) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 case ZFCP_ERP_ACTION_REOPEN_UNIT:
2773 if (atomic_test_mask
2774 (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 goto out;
2776 }
2777 if (!atomic_test_mask
2778 (ZFCP_STATUS_COMMON_RUNNING, &port->status) ||
2779 atomic_test_mask
2780 (ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) {
2781 goto out;
2782 }
2783 if (!atomic_test_mask
Martin Peschke9467a9b2008-03-27 14:22:03 +01002784 (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
2785 need = ZFCP_ERP_ACTION_REOPEN_PORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 /* fall through !!! */
2787
2788 case ZFCP_ERP_ACTION_REOPEN_PORT:
2789 if (atomic_test_mask
2790 (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 goto out;
2792 }
2793 /* fall through !!! */
2794
2795 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
Andreas Herrmann3734d242005-09-13 21:47:11 +02002796 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
2797 &port->status)) {
2798 if (port->erp_action.action !=
2799 ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) {
2800 ZFCP_LOG_INFO("dropped erp action %i (port "
2801 "0x%016Lx, action in use: %i)\n",
Martin Peschke9467a9b2008-03-27 14:22:03 +01002802 want, port->wwpn,
Andreas Herrmann3734d242005-09-13 21:47:11 +02002803 port->erp_action.action);
Martin Peschke507e4962008-03-27 14:22:05 +01002804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 goto out;
2806 }
2807 if (!atomic_test_mask
2808 (ZFCP_STATUS_COMMON_RUNNING, &adapter->status) ||
2809 atomic_test_mask
2810 (ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) {
2811 goto out;
2812 }
2813 if (!atomic_test_mask
Martin Peschke9467a9b2008-03-27 14:22:03 +01002814 (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
2815 need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 /* fall through !!! */
2817
2818 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
2819 if (atomic_test_mask
2820 (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 goto out;
2822 }
2823 break;
2824
2825 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 ZFCP_LOG_NORMAL("bug: unknown erp action requested "
2827 "on adapter %s (action=%d)\n",
Martin Peschke9467a9b2008-03-27 14:22:03 +01002828 zfcp_get_busid_by_adapter(adapter), want);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 goto out;
2830 }
2831
2832 /* check whether we need something stronger first */
Martin Peschke9467a9b2008-03-27 14:22:03 +01002833 if (need) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 ZFCP_LOG_DEBUG("stronger erp action %d needed before "
2835 "erp action %d on adapter %s\n",
Martin Peschke9467a9b2008-03-27 14:22:03 +01002836 need, want, zfcp_get_busid_by_adapter(adapter));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 }
2838
2839 /* mark adapter to have some error recovery pending */
2840 atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
2841
2842 /* setup error recovery action */
Martin Peschke9467a9b2008-03-27 14:22:03 +01002843 switch (need) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844
2845 case ZFCP_ERP_ACTION_REOPEN_UNIT:
2846 zfcp_unit_get(unit);
2847 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status);
2848 erp_action = &unit->erp_action;
2849 if (!atomic_test_mask
2850 (ZFCP_STATUS_COMMON_RUNNING, &unit->status))
2851 status = ZFCP_STATUS_ERP_CLOSE_ONLY;
2852 break;
2853
2854 case ZFCP_ERP_ACTION_REOPEN_PORT:
2855 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
2856 zfcp_port_get(port);
2857 zfcp_erp_action_dismiss_port(port);
2858 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
2859 erp_action = &port->erp_action;
2860 if (!atomic_test_mask
2861 (ZFCP_STATUS_COMMON_RUNNING, &port->status))
2862 status = ZFCP_STATUS_ERP_CLOSE_ONLY;
2863 break;
2864
2865 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
2866 zfcp_adapter_get(adapter);
2867 zfcp_erp_action_dismiss_adapter(adapter);
2868 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
2869 erp_action = &adapter->erp_action;
2870 if (!atomic_test_mask
2871 (ZFCP_STATUS_COMMON_RUNNING, &adapter->status))
2872 status = ZFCP_STATUS_ERP_CLOSE_ONLY;
2873 break;
2874 }
2875
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 memset(erp_action, 0, sizeof (struct zfcp_erp_action));
2877 erp_action->adapter = adapter;
2878 erp_action->port = port;
2879 erp_action->unit = unit;
Martin Peschke9467a9b2008-03-27 14:22:03 +01002880 erp_action->action = need;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 erp_action->status = status;
2882
2883 ++adapter->erp_total_count;
2884
2885 /* finally put it into 'ready' queue and kick erp thread */
Martin Peschke86e8dfc2007-11-15 13:57:17 +01002886 list_add_tail(&erp_action->list, &adapter->erp_ready_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 up(&adapter->erp_ready_sem);
Martin Peschke348447e2008-03-27 14:22:01 +01002888 zfcp_rec_dbf_event_thread(1, adapter, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 retval = 0;
2890 out:
Martin Peschke9467a9b2008-03-27 14:22:03 +01002891 zfcp_rec_dbf_event_trigger(id, ref, want, need, (u64)erp_action,
2892 adapter, port, unit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 return retval;
2894}
2895
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896static int
2897zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
2898{
2899 int retval = 0;
2900 struct zfcp_adapter *adapter = erp_action->adapter;
2901
2902 --adapter->erp_total_count;
2903 if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
2904 --adapter->erp_low_mem_count;
2905 erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
2906 }
2907
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 list_del(&erp_action->list);
Martin Peschke6f4f3652008-03-27 14:22:04 +01002909 zfcp_rec_dbf_event_action(144, erp_action);
2910
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 switch (erp_action->action) {
2912 case ZFCP_ERP_ACTION_REOPEN_UNIT:
2913 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
2914 &erp_action->unit->status);
2915 break;
2916 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
2917 case ZFCP_ERP_ACTION_REOPEN_PORT:
2918 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
2919 &erp_action->port->status);
2920 break;
2921 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
2922 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
2923 &erp_action->adapter->status);
2924 break;
2925 default:
2926 /* bug */
2927 break;
2928 }
2929 return retval;
2930}
2931
2932/**
2933 * zfcp_erp_action_cleanup
2934 *
Adrian Bunk575c9682006-01-15 02:00:17 +01002935 * Register unit with scsi stack if appropriate and fix reference counts.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 * Note: Temporary units are not registered with scsi stack.
2937 */
2938static void
2939zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
2940 struct zfcp_port *port, struct zfcp_unit *unit,
2941 int result)
2942{
2943 switch (action) {
2944 case ZFCP_ERP_ACTION_REOPEN_UNIT:
2945 if ((result == ZFCP_ERP_SUCCEEDED)
2946 && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
2947 &unit->status))
Andreas Herrmann3859f6a2005-08-27 11:07:54 -07002948 && !unit->device
Andreas Herrmannad58f7d2006-03-10 00:56:16 +01002949 && port->rport) {
2950 atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
2951 &unit->status);
Christof Schmitt5f852be2007-05-08 11:16:52 +02002952 if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
2953 &unit->status) == 0)
2954 zfcp_erp_schedule_work(unit);
Andreas Herrmannad58f7d2006-03-10 00:56:16 +01002955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956 zfcp_unit_put(unit);
2957 break;
2958 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
2959 case ZFCP_ERP_ACTION_REOPEN_PORT:
Andreas Herrmann338151e2006-05-22 18:25:56 +02002960 if (atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
2961 &port->status)) {
2962 zfcp_port_put(port);
2963 break;
2964 }
2965
Andreas Herrmann3859f6a2005-08-27 11:07:54 -07002966 if ((result == ZFCP_ERP_SUCCEEDED)
Andreas Herrmann3859f6a2005-08-27 11:07:54 -07002967 && !port->rport) {
2968 struct fc_rport_identifiers ids;
2969 ids.node_name = port->wwnn;
2970 ids.port_name = port->wwpn;
2971 ids.port_id = port->d_id;
2972 ids.roles = FC_RPORT_ROLE_FCP_TARGET;
2973 port->rport =
2974 fc_remote_port_add(adapter->scsi_host, 0, &ids);
2975 if (!port->rport)
2976 ZFCP_LOG_NORMAL("failed registration of rport"
2977 "(adapter %s, wwpn=0x%016Lx)\n",
2978 zfcp_get_busid_by_port(port),
2979 port->wwpn);
Ralph Wuerthner75bfc282006-05-22 18:24:33 +02002980 else {
Christof Schmitt5f852be2007-05-08 11:16:52 +02002981 scsi_target_unblock(&port->rport->dev);
Ralph Wuerthner75bfc282006-05-22 18:24:33 +02002982 port->rport->maxframe_size = port->maxframe_size;
2983 port->rport->supported_classes =
2984 port->supported_classes;
2985 }
Andreas Herrmann3859f6a2005-08-27 11:07:54 -07002986 }
Andreas Herrmann338151e2006-05-22 18:25:56 +02002987 if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) {
2988 fc_remote_port_delete(port->rport);
2989 port->rport = NULL;
2990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 zfcp_port_put(port);
2992 break;
2993 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Andreas Herrmann338151e2006-05-22 18:25:56 +02002994 if (result != ZFCP_ERP_SUCCEEDED) {
Andreas Herrmann338151e2006-05-22 18:25:56 +02002995 list_for_each_entry(port, &adapter->port_list_head, list)
2996 if (port->rport &&
2997 !atomic_test_mask(ZFCP_STATUS_PORT_WKA,
2998 &port->status)) {
2999 fc_remote_port_delete(port->rport);
3000 port->rport = NULL;
3001 }
3002 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 zfcp_adapter_put(adapter);
3004 break;
3005 default:
3006 break;
3007 }
3008}
3009
3010
Andreas Herrmann81654282006-09-18 22:30:36 +02003011static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 struct zfcp_port *port;
3014
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status))
3016 zfcp_erp_action_dismiss(&adapter->erp_action);
3017 else
3018 list_for_each_entry(port, &adapter->port_list_head, list)
3019 zfcp_erp_action_dismiss_port(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020}
3021
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +02003022static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 struct zfcp_unit *unit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status))
3027 zfcp_erp_action_dismiss(&port->erp_action);
3028 else
3029 list_for_each_entry(unit, &port->unit_list_head, list)
3030 zfcp_erp_action_dismiss_unit(unit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031}
3032
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +02003033static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status))
3036 zfcp_erp_action_dismiss(&unit->erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037}
3038
Heiko Carstens364c8552007-10-12 16:11:35 +02003039static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
Martin Peschke6f4f3652008-03-27 14:22:04 +01003042 zfcp_rec_dbf_event_action(145, erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043}
3044
Heiko Carstens364c8552007-10-12 16:11:35 +02003045static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 list_move(&erp_action->list, &erp_action->adapter->erp_ready_head);
Martin Peschke6f4f3652008-03-27 14:22:04 +01003048 zfcp_rec_dbf_event_action(146, erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049}
3050
Martin Peschke698ec0162008-03-27 14:22:02 +01003051void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, u64 ref)
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003052{
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003053 unsigned long flags;
3054
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003055 read_lock_irqsave(&zfcp_data.config_lock, flags);
Martin Peschke698ec0162008-03-27 14:22:02 +01003056 zfcp_erp_modify_port_status(port, id, ref,
3057 ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003058 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
Martin Peschke9467a9b2008-03-27 14:22:03 +01003059 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003060}
3061
Martin Peschke698ec0162008-03-27 14:22:02 +01003062void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, u64 ref)
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003063{
Martin Peschke698ec0162008-03-27 14:22:02 +01003064 zfcp_erp_modify_unit_status(unit, id, ref,
3065 ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
Martin Peschke9467a9b2008-03-27 14:22:03 +01003066 zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003067}
3068
Martin Peschke698ec0162008-03-27 14:22:02 +01003069void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 unsigned long flags;
3072
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 read_lock_irqsave(&zfcp_data.config_lock, flags);
Martin Peschke698ec0162008-03-27 14:22:02 +01003074 zfcp_erp_modify_port_status(port, id, ref,
3075 ZFCP_STATUS_COMMON_ERP_FAILED |
3076 ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
3078}
3079
Martin Peschke698ec0162008-03-27 14:22:02 +01003080void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081{
Martin Peschke698ec0162008-03-27 14:22:02 +01003082 zfcp_erp_modify_unit_status(unit, id, ref,
3083 ZFCP_STATUS_COMMON_ERP_FAILED |
3084 ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085}
3086
Martin Peschke9467a9b2008-03-27 14:22:03 +01003087void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id,
3088 u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089{
3090 struct zfcp_port *port;
3091 unsigned long flags;
3092
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02003093 if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
3094 return;
3095
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 read_lock_irqsave(&zfcp_data.config_lock, flags);
6f71d9b2005-04-10 23:04:28 -05003097 if (adapter->nameserver_port)
Martin Peschke9467a9b2008-03-27 14:22:03 +01003098 zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 list_for_each_entry(port, &adapter->port_list_head, list)
3100 if (port != adapter->nameserver_port)
Martin Peschke9467a9b2008-03-27 14:22:03 +01003101 zfcp_erp_port_access_changed(port, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
3103}
3104
Martin Peschke9467a9b2008-03-27 14:22:03 +01003105void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106{
3107 struct zfcp_adapter *adapter = port->adapter;
3108 struct zfcp_unit *unit;
3109
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003111 &port->status) &&
3112 !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 &port->status)) {
3114 if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
3115 list_for_each_entry(unit, &port->unit_list_head, list)
Martin Peschke9467a9b2008-03-27 14:22:03 +01003116 zfcp_erp_unit_access_changed(unit, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 return;
3118 }
3119
3120 ZFCP_LOG_NORMAL("reopen of port 0x%016Lx on adapter %s "
3121 "(due to ACT update)\n",
3122 port->wwpn, zfcp_get_busid_by_adapter(adapter));
Martin Peschke9467a9b2008-03-27 14:22:03 +01003123 if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 ZFCP_LOG_NORMAL("failed reopen of port"
3125 "(adapter %s, wwpn=0x%016Lx)\n",
3126 zfcp_get_busid_by_adapter(adapter), port->wwpn);
3127}
3128
Martin Peschke9467a9b2008-03-27 14:22:03 +01003129void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, u64 ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130{
3131 struct zfcp_adapter *adapter = unit->port->adapter;
3132
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02003133 if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
3134 &unit->status) &&
3135 !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
3136 &unit->status))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 return;
3138
3139 ZFCP_LOG_NORMAL("reopen of unit 0x%016Lx on port 0x%016Lx "
3140 " on adapter %s (due to ACT update)\n",
3141 unit->fcp_lun, unit->port->wwpn,
3142 zfcp_get_busid_by_adapter(adapter));
Martin Peschke9467a9b2008-03-27 14:22:03 +01003143 if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 ZFCP_LOG_NORMAL("failed reopen of unit (adapter %s, "
3145 "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
3146 zfcp_get_busid_by_adapter(adapter),
3147 unit->port->wwpn, unit->fcp_lun);
3148}
3149
3150#undef ZFCP_LOG_AREA