11da177e4SLinus Torvalds /* 24a9d2d8bSAndreas Herrmann * This file is part of the zfcp device driver for 34a9d2d8bSAndreas Herrmann * FCP adapters for IBM System z9 and zSeries. 41da177e4SLinus Torvalds * 54a9d2d8bSAndreas Herrmann * (C) Copyright IBM Corp. 2002, 2006 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 91da177e4SLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 101da177e4SLinus Torvalds * any later version. 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 131da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 141da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151da177e4SLinus Torvalds * GNU General Public License for more details. 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 181da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 191da177e4SLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 201da177e4SLinus Torvalds */ 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds #include "zfcp_ext.h" 251da177e4SLinus Torvalds 2664b29a13SAndreas Herrmann static int zfcp_erp_adisc(struct zfcp_port *); 271da177e4SLinus Torvalds static void zfcp_erp_adisc_handler(unsigned long); 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int); 301da177e4SLinus Torvalds static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int); 311da177e4SLinus Torvalds static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int); 321da177e4SLinus Torvalds static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int); 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int); 351da177e4SLinus Torvalds static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int); 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds static void zfcp_erp_adapter_block(struct zfcp_adapter *, int); 381da177e4SLinus Torvalds static void zfcp_erp_adapter_unblock(struct zfcp_adapter *); 391da177e4SLinus Torvalds static void zfcp_erp_port_block(struct zfcp_port *, int); 401da177e4SLinus Torvalds static void zfcp_erp_port_unblock(struct zfcp_port *); 411da177e4SLinus Torvalds static void zfcp_erp_unit_block(struct zfcp_unit *, int); 421da177e4SLinus Torvalds static void zfcp_erp_unit_unblock(struct zfcp_unit *); 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds static int zfcp_erp_thread(void *); 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds static int zfcp_erp_strategy(struct zfcp_erp_action *); 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *); 491da177e4SLinus Torvalds static int zfcp_erp_strategy_memwait(struct zfcp_erp_action *); 501da177e4SLinus Torvalds static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *, int); 511da177e4SLinus Torvalds static int zfcp_erp_strategy_check_unit(struct zfcp_unit *, int); 521da177e4SLinus Torvalds static int zfcp_erp_strategy_check_port(struct zfcp_port *, int); 531da177e4SLinus Torvalds static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *, int); 541da177e4SLinus Torvalds static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *, 551da177e4SLinus Torvalds struct zfcp_port *, 561da177e4SLinus Torvalds struct zfcp_unit *, int); 57364c8558SHeiko Carstens static int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); 581da177e4SLinus Torvalds static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *, 591da177e4SLinus Torvalds struct zfcp_port *, 601da177e4SLinus Torvalds struct zfcp_unit *, int); 611da177e4SLinus Torvalds static int zfcp_erp_strategy_check_queues(struct zfcp_adapter *); 621da177e4SLinus Torvalds static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int); 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *); 651da177e4SLinus Torvalds static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int); 661da177e4SLinus Torvalds static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *); 671da177e4SLinus Torvalds static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); 681da177e4SLinus Torvalds static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); 691da177e4SLinus Torvalds static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); 701da177e4SLinus Torvalds static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *); 71aef4a983SMaxim Shchetynin static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *); 721da177e4SLinus Torvalds static int zfcp_erp_adapter_strategy_open_fsf_statusread( 731da177e4SLinus Torvalds struct zfcp_erp_action *); 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *); 761da177e4SLinus Torvalds static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *); 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds static int zfcp_erp_port_strategy(struct zfcp_erp_action *); 791da177e4SLinus Torvalds static int zfcp_erp_port_strategy_clearstati(struct zfcp_port *); 801da177e4SLinus Torvalds static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *); 811da177e4SLinus Torvalds static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *); 821da177e4SLinus Torvalds static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *); 831da177e4SLinus Torvalds static int zfcp_erp_port_strategy_open_nameserver_wakeup( 841da177e4SLinus Torvalds struct zfcp_erp_action *); 851da177e4SLinus Torvalds static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *); 861da177e4SLinus Torvalds static int zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *); 871da177e4SLinus Torvalds static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *); 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds static int zfcp_erp_unit_strategy(struct zfcp_erp_action *); 901da177e4SLinus Torvalds static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *); 911da177e4SLinus Torvalds static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *); 921da177e4SLinus Torvalds static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *); 931da177e4SLinus Torvalds 9481654286SAndreas Herrmann static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); 95f6c0e7a7SAndreas Herrmann static void zfcp_erp_action_dismiss_port(struct zfcp_port *); 96f6c0e7a7SAndreas Herrmann static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *); 97f6c0e7a7SAndreas Herrmann static void zfcp_erp_action_dismiss(struct zfcp_erp_action *); 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *, 1001da177e4SLinus Torvalds struct zfcp_port *, struct zfcp_unit *); 1011da177e4SLinus Torvalds static int zfcp_erp_action_dequeue(struct zfcp_erp_action *); 1021da177e4SLinus Torvalds static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *, 1031da177e4SLinus Torvalds struct zfcp_port *, struct zfcp_unit *, 1041da177e4SLinus Torvalds int); 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds static void zfcp_erp_action_ready(struct zfcp_erp_action *); 1071da177e4SLinus Torvalds static int zfcp_erp_action_exists(struct zfcp_erp_action *); 1081da177e4SLinus Torvalds 109364c8558SHeiko Carstens static void zfcp_erp_action_to_ready(struct zfcp_erp_action *); 110364c8558SHeiko Carstens static void zfcp_erp_action_to_running(struct zfcp_erp_action *); 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds static void zfcp_erp_memwait_handler(unsigned long); 1132abbe866SAndreas Herrmann 1142abbe866SAndreas Herrmann /** 1152abbe866SAndreas Herrmann * zfcp_close_qdio - close qdio queues for an adapter 1162abbe866SAndreas Herrmann */ 1172abbe866SAndreas Herrmann static void zfcp_close_qdio(struct zfcp_adapter *adapter) 1182abbe866SAndreas Herrmann { 1192abbe866SAndreas Herrmann struct zfcp_qdio_queue *req_queue; 1202abbe866SAndreas Herrmann int first, count; 1212abbe866SAndreas Herrmann 1222abbe866SAndreas Herrmann if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) 1232abbe866SAndreas Herrmann return; 1242abbe866SAndreas Herrmann 1252abbe866SAndreas Herrmann /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ 1262abbe866SAndreas Herrmann req_queue = &adapter->request_queue; 1272abbe866SAndreas Herrmann write_lock_irq(&req_queue->queue_lock); 1282abbe866SAndreas Herrmann atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); 1292abbe866SAndreas Herrmann write_unlock_irq(&req_queue->queue_lock); 1302abbe866SAndreas Herrmann 1312abbe866SAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "qdio_down2a"); 1322abbe866SAndreas Herrmann while (qdio_shutdown(adapter->ccw_device, 1332abbe866SAndreas Herrmann QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) 13418edcdbdSChristof Schmitt ssleep(1); 1352abbe866SAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "qdio_down2b"); 1362abbe866SAndreas Herrmann 1372abbe866SAndreas Herrmann /* cleanup used outbound sbals */ 1382abbe866SAndreas Herrmann count = atomic_read(&req_queue->free_count); 1392abbe866SAndreas Herrmann if (count < QDIO_MAX_BUFFERS_PER_Q) { 1402abbe866SAndreas Herrmann first = (req_queue->free_index+count) % QDIO_MAX_BUFFERS_PER_Q; 1412abbe866SAndreas Herrmann count = QDIO_MAX_BUFFERS_PER_Q - count; 1422abbe866SAndreas Herrmann zfcp_qdio_zero_sbals(req_queue->buffer, first, count); 1432abbe866SAndreas Herrmann } 1442abbe866SAndreas Herrmann req_queue->free_index = 0; 1452abbe866SAndreas Herrmann atomic_set(&req_queue->free_count, 0); 1462abbe866SAndreas Herrmann req_queue->distance_from_int = 0; 1472abbe866SAndreas Herrmann adapter->response_queue.free_index = 0; 1482abbe866SAndreas Herrmann atomic_set(&adapter->response_queue.free_count, 0); 1492abbe866SAndreas Herrmann } 1502abbe866SAndreas Herrmann 1512abbe866SAndreas Herrmann /** 1522abbe866SAndreas Herrmann * zfcp_close_fsf - stop FSF operations for an adapter 1532abbe866SAndreas Herrmann * 1542abbe866SAndreas Herrmann * Dismiss and cleanup all pending fsf_reqs (this wakes up all initiators of 1552abbe866SAndreas Herrmann * requests waiting for completion; especially this returns SCSI commands 1562abbe866SAndreas Herrmann * with error state). 1572abbe866SAndreas Herrmann */ 1582abbe866SAndreas Herrmann static void zfcp_close_fsf(struct zfcp_adapter *adapter) 1592abbe866SAndreas Herrmann { 1602abbe866SAndreas Herrmann /* close queues to ensure that buffers are not accessed by adapter */ 1612abbe866SAndreas Herrmann zfcp_close_qdio(adapter); 1622abbe866SAndreas Herrmann zfcp_fsf_req_dismiss_all(adapter); 1632abbe866SAndreas Herrmann /* reset FSF request sequence number */ 1642abbe866SAndreas Herrmann adapter->fsf_req_seq_no = 0; 1652abbe866SAndreas Herrmann /* all ports and units are closed */ 166698ec016SMartin Peschke zfcp_erp_modify_adapter_status(adapter, 24, 0, 1672abbe866SAndreas Herrmann ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); 1682abbe866SAndreas Herrmann } 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds /** 1711da177e4SLinus Torvalds * zfcp_fsf_request_timeout_handler - called if a request timed out 1721da177e4SLinus Torvalds * @data: pointer to adapter for handler function 1731da177e4SLinus Torvalds * 1741da177e4SLinus Torvalds * This function needs to be called if requests (ELS, Generic Service, 1751da177e4SLinus Torvalds * or SCSI commands) exceed a certain time limit. The assumption is 1761da177e4SLinus Torvalds * that after the time limit the adapter get stuck. So we trigger a reopen of 1772abbe866SAndreas Herrmann * the adapter. 1781da177e4SLinus Torvalds */ 1792abbe866SAndreas Herrmann static void zfcp_fsf_request_timeout_handler(unsigned long data) 1801da177e4SLinus Torvalds { 1812abbe866SAndreas Herrmann struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; 1823b02191aSHeiko Carstens zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 1852abbe866SAndreas Herrmann void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout) 1861da177e4SLinus Torvalds { 1872abbe866SAndreas Herrmann fsf_req->timer.function = zfcp_fsf_request_timeout_handler; 1882abbe866SAndreas Herrmann fsf_req->timer.data = (unsigned long) fsf_req->adapter; 1899e3738f3SChristof Schmitt fsf_req->timer.expires = jiffies + timeout; 1902abbe866SAndreas Herrmann add_timer(&fsf_req->timer); 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /* 1941da177e4SLinus Torvalds * function: 1951da177e4SLinus Torvalds * 1961da177e4SLinus Torvalds * purpose: called if an adapter failed, 1971da177e4SLinus Torvalds * initiates adapter recovery which is done 1981da177e4SLinus Torvalds * asynchronously 1991da177e4SLinus Torvalds * 200d6e05edcSAndreas Mohr * returns: 0 - initiated action successfully 2011da177e4SLinus Torvalds * <0 - failed to initiate action 2021da177e4SLinus Torvalds */ 2032b67fc46SHeiko Carstens static int 2041da177e4SLinus Torvalds zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask) 2051da177e4SLinus Torvalds { 2061da177e4SLinus Torvalds int retval; 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_ro"); 2091da177e4SLinus Torvalds ZFCP_LOG_DEBUG("reopen adapter %s\n", 2101da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds zfcp_erp_adapter_block(adapter, clear_mask); 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { 2151da177e4SLinus Torvalds ZFCP_LOG_DEBUG("skipped reopen of failed adapter %s\n", 2161da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 2171da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_ro_f"); 2181da177e4SLinus Torvalds /* ensure propagation of failed status to new devices */ 219698ec016SMartin Peschke zfcp_erp_adapter_failed(adapter, 13, 0); 2201da177e4SLinus Torvalds retval = -EIO; 2211da177e4SLinus Torvalds goto out; 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, 2241da177e4SLinus Torvalds adapter, NULL, NULL); 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds out: 2271da177e4SLinus Torvalds return retval; 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds /* 2311da177e4SLinus Torvalds * function: 2321da177e4SLinus Torvalds * 2331da177e4SLinus Torvalds * purpose: Wrappper for zfcp_erp_adapter_reopen_internal 2341da177e4SLinus Torvalds * used to ensure the correct locking 2351da177e4SLinus Torvalds * 236d6e05edcSAndreas Mohr * returns: 0 - initiated action successfully 2371da177e4SLinus Torvalds * <0 - failed to initiate action 2381da177e4SLinus Torvalds */ 2391da177e4SLinus Torvalds int 2401da177e4SLinus Torvalds zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask) 2411da177e4SLinus Torvalds { 2421da177e4SLinus Torvalds int retval; 2431da177e4SLinus Torvalds unsigned long flags; 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 2461da177e4SLinus Torvalds write_lock(&adapter->erp_lock); 2471da177e4SLinus Torvalds retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask); 2481da177e4SLinus Torvalds write_unlock(&adapter->erp_lock); 2491da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds return retval; 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds int 2551da177e4SLinus Torvalds zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask) 2561da177e4SLinus Torvalds { 2571da177e4SLinus Torvalds int retval; 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds retval = zfcp_erp_adapter_reopen(adapter, 2601da177e4SLinus Torvalds ZFCP_STATUS_COMMON_RUNNING | 2611da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ERP_FAILED | 2621da177e4SLinus Torvalds clear_mask); 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds return retval; 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds int 2681da177e4SLinus Torvalds zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask) 2691da177e4SLinus Torvalds { 2701da177e4SLinus Torvalds int retval; 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds retval = zfcp_erp_port_reopen(port, 2731da177e4SLinus Torvalds ZFCP_STATUS_COMMON_RUNNING | 2741da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ERP_FAILED | 2751da177e4SLinus Torvalds clear_mask); 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds return retval; 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds int 2811da177e4SLinus Torvalds zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask) 2821da177e4SLinus Torvalds { 2831da177e4SLinus Torvalds int retval; 2841da177e4SLinus Torvalds 2851da177e4SLinus Torvalds retval = zfcp_erp_unit_reopen(unit, 2861da177e4SLinus Torvalds ZFCP_STATUS_COMMON_RUNNING | 2871da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ERP_FAILED | 2881da177e4SLinus Torvalds clear_mask); 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds return retval; 2911da177e4SLinus Torvalds } 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds /** 2951da177e4SLinus Torvalds * zfcp_erp_adisc - send ADISC ELS command 29664b29a13SAndreas Herrmann * @port: port structure 2971da177e4SLinus Torvalds */ 2982b67fc46SHeiko Carstens static int 29964b29a13SAndreas Herrmann zfcp_erp_adisc(struct zfcp_port *port) 3001da177e4SLinus Torvalds { 30164b29a13SAndreas Herrmann struct zfcp_adapter *adapter = port->adapter; 3021da177e4SLinus Torvalds struct zfcp_send_els *send_els; 3031da177e4SLinus Torvalds struct zfcp_ls_adisc *adisc; 3041da177e4SLinus Torvalds void *address = NULL; 3051da177e4SLinus Torvalds int retval = 0; 3061da177e4SLinus Torvalds 307ec4081c6SAndreas Herrmann send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC); 3081da177e4SLinus Torvalds if (send_els == NULL) 3091da177e4SLinus Torvalds goto nomem; 3101da177e4SLinus Torvalds 31173fc4f0dSJens Axboe send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); 3121da177e4SLinus Torvalds if (send_els->req == NULL) 3131da177e4SLinus Torvalds goto nomem; 31473fc4f0dSJens Axboe sg_init_table(send_els->req, 1); 3151da177e4SLinus Torvalds 31673fc4f0dSJens Axboe send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); 3171da177e4SLinus Torvalds if (send_els->resp == NULL) 3181da177e4SLinus Torvalds goto nomem; 31973fc4f0dSJens Axboe sg_init_table(send_els->resp, 1); 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds address = (void *) get_zeroed_page(GFP_ATOMIC); 3221da177e4SLinus Torvalds if (address == NULL) 3231da177e4SLinus Torvalds goto nomem; 3241da177e4SLinus Torvalds 325642f1490SJens Axboe zfcp_address_to_sg(address, send_els->req, sizeof(struct zfcp_ls_adisc)); 3261da177e4SLinus Torvalds address += PAGE_SIZE >> 1; 327642f1490SJens Axboe zfcp_address_to_sg(address, send_els->resp, sizeof(struct zfcp_ls_adisc_acc)); 3281da177e4SLinus Torvalds send_els->req_count = send_els->resp_count = 1; 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds send_els->adapter = adapter; 33164b29a13SAndreas Herrmann send_els->port = port; 33264b29a13SAndreas Herrmann send_els->d_id = port->d_id; 3331da177e4SLinus Torvalds send_els->handler = zfcp_erp_adisc_handler; 3341da177e4SLinus Torvalds send_els->handler_data = (unsigned long) send_els; 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds adisc = zfcp_sg_to_address(send_els->req); 3371da177e4SLinus Torvalds send_els->ls_code = adisc->code = ZFCP_LS_ADISC; 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports 3401da177e4SLinus Torvalds without FC-AL-2 capability, so we don't set it */ 34113e1e1f0SAndreas Herrmann adisc->wwpn = fc_host_port_name(adapter->scsi_host); 34213e1e1f0SAndreas Herrmann adisc->wwnn = fc_host_node_name(adapter->scsi_host); 34313e1e1f0SAndreas Herrmann adisc->nport_id = fc_host_port_id(adapter->scsi_host); 3441d589edfSChristof Schmitt ZFCP_LOG_INFO("ADISC request from s_id 0x%06x to d_id 0x%06x " 3451da177e4SLinus Torvalds "(wwpn=0x%016Lx, wwnn=0x%016Lx, " 3461d589edfSChristof Schmitt "hard_nport_id=0x%06x, nport_id=0x%06x)\n", 34713e1e1f0SAndreas Herrmann adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn, 3481da177e4SLinus Torvalds (wwn_t) adisc->wwnn, adisc->hard_nport_id, 3491da177e4SLinus Torvalds adisc->nport_id); 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds retval = zfcp_fsf_send_els(send_els); 3521da177e4SLinus Torvalds if (retval != 0) { 3531da177e4SLinus Torvalds ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port " 3541d589edfSChristof Schmitt "0x%06x on adapter %s\n", send_els->d_id, 3551da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 3561da177e4SLinus Torvalds goto freemem; 3571da177e4SLinus Torvalds } 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds goto out; 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds nomem: 3621da177e4SLinus Torvalds retval = -ENOMEM; 3631da177e4SLinus Torvalds freemem: 3641da177e4SLinus Torvalds if (address != NULL) 36573fc4f0dSJens Axboe __free_pages(sg_page(send_els->req), 0); 3661da177e4SLinus Torvalds if (send_els != NULL) { 3671da177e4SLinus Torvalds kfree(send_els->req); 3681da177e4SLinus Torvalds kfree(send_els->resp); 3691da177e4SLinus Torvalds kfree(send_els); 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds out: 3721da177e4SLinus Torvalds return retval; 3731da177e4SLinus Torvalds } 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds /** 3771da177e4SLinus Torvalds * zfcp_erp_adisc_handler - handler for ADISC ELS command 3781da177e4SLinus Torvalds * @data: pointer to struct zfcp_send_els 3791da177e4SLinus Torvalds * 3801da177e4SLinus Torvalds * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered. 3811da177e4SLinus Torvalds */ 3822b67fc46SHeiko Carstens static void 3831da177e4SLinus Torvalds zfcp_erp_adisc_handler(unsigned long data) 3841da177e4SLinus Torvalds { 3851da177e4SLinus Torvalds struct zfcp_send_els *send_els; 3861da177e4SLinus Torvalds struct zfcp_port *port; 3871da177e4SLinus Torvalds struct zfcp_adapter *adapter; 38813e1e1f0SAndreas Herrmann u32 d_id; 3891da177e4SLinus Torvalds struct zfcp_ls_adisc_acc *adisc; 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds send_els = (struct zfcp_send_els *) data; 3921da177e4SLinus Torvalds adapter = send_els->adapter; 39364b29a13SAndreas Herrmann port = send_els->port; 3941da177e4SLinus Torvalds d_id = send_els->d_id; 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds /* request rejected or timed out */ 3971da177e4SLinus Torvalds if (send_els->status != 0) { 3981da177e4SLinus Torvalds ZFCP_LOG_NORMAL("ELS request rejected/timed out, " 3991da177e4SLinus Torvalds "force physical port reopen " 4001d589edfSChristof Schmitt "(adapter %s, port d_id=0x%06x)\n", 4011da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 4021da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "forcreop"); 4031da177e4SLinus Torvalds if (zfcp_erp_port_forced_reopen(port, 0)) 4041da177e4SLinus Torvalds ZFCP_LOG_NORMAL("failed reopen of port " 4051da177e4SLinus Torvalds "(adapter %s, wwpn=0x%016Lx)\n", 4061da177e4SLinus Torvalds zfcp_get_busid_by_port(port), 4071da177e4SLinus Torvalds port->wwpn); 4081da177e4SLinus Torvalds goto out; 4091da177e4SLinus Torvalds } 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds adisc = zfcp_sg_to_address(send_els->resp); 4121da177e4SLinus Torvalds 4131d589edfSChristof Schmitt ZFCP_LOG_INFO("ADISC response from d_id 0x%06x to s_id " 4141d589edfSChristof Schmitt "0x%06x (wwpn=0x%016Lx, wwnn=0x%016Lx, " 4151d589edfSChristof Schmitt "hard_nport_id=0x%06x, nport_id=0x%06x)\n", 41613e1e1f0SAndreas Herrmann d_id, fc_host_port_id(adapter->scsi_host), 41713e1e1f0SAndreas Herrmann (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn, 41813e1e1f0SAndreas Herrmann adisc->hard_nport_id, adisc->nport_id); 4191da177e4SLinus Torvalds 4201da177e4SLinus Torvalds /* set wwnn for port */ 4211da177e4SLinus Torvalds if (port->wwnn == 0) 4221da177e4SLinus Torvalds port->wwnn = adisc->wwnn; 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds if (port->wwpn != adisc->wwpn) { 4251da177e4SLinus Torvalds ZFCP_LOG_NORMAL("d_id assignment changed, reopening " 4261da177e4SLinus Torvalds "port (adapter %s, wwpn=0x%016Lx, " 4271da177e4SLinus Torvalds "adisc_resp_wwpn=0x%016Lx)\n", 4281da177e4SLinus Torvalds zfcp_get_busid_by_port(port), 4291da177e4SLinus Torvalds port->wwpn, (wwn_t) adisc->wwpn); 4301da177e4SLinus Torvalds if (zfcp_erp_port_reopen(port, 0)) 4311da177e4SLinus Torvalds ZFCP_LOG_NORMAL("failed reopen of port " 4321da177e4SLinus Torvalds "(adapter %s, wwpn=0x%016Lx)\n", 4331da177e4SLinus Torvalds zfcp_get_busid_by_port(port), 4341da177e4SLinus Torvalds port->wwpn); 4351da177e4SLinus Torvalds } 4361da177e4SLinus Torvalds 4371da177e4SLinus Torvalds out: 4381da177e4SLinus Torvalds zfcp_port_put(port); 43973fc4f0dSJens Axboe __free_pages(sg_page(send_els->req), 0); 4401da177e4SLinus Torvalds kfree(send_els->req); 4411da177e4SLinus Torvalds kfree(send_els->resp); 4421da177e4SLinus Torvalds kfree(send_els); 4431da177e4SLinus Torvalds } 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds /** 4471da177e4SLinus Torvalds * zfcp_test_link - lightweight link test procedure 4481da177e4SLinus Torvalds * @port: port to be tested 4491da177e4SLinus Torvalds * 4501da177e4SLinus Torvalds * Test status of a link to a remote port using the ELS command ADISC. 4511da177e4SLinus Torvalds */ 4521da177e4SLinus Torvalds int 4531da177e4SLinus Torvalds zfcp_test_link(struct zfcp_port *port) 4541da177e4SLinus Torvalds { 4551da177e4SLinus Torvalds int retval; 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds zfcp_port_get(port); 45864b29a13SAndreas Herrmann retval = zfcp_erp_adisc(port); 4593f0ca62aSChristof Schmitt if (retval != 0 && retval != -EBUSY) { 4601da177e4SLinus Torvalds zfcp_port_put(port); 4611da177e4SLinus Torvalds ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " 4621da177e4SLinus Torvalds "on adapter %s\n ", port->wwpn, 4631da177e4SLinus Torvalds zfcp_get_busid_by_port(port)); 4641da177e4SLinus Torvalds retval = zfcp_erp_port_forced_reopen(port, 0); 4651da177e4SLinus Torvalds if (retval != 0) { 4661da177e4SLinus Torvalds ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx " 4671da177e4SLinus Torvalds "on adapter %s failed\n", port->wwpn, 4681da177e4SLinus Torvalds zfcp_get_busid_by_port(port)); 4691da177e4SLinus Torvalds retval = -EPERM; 4701da177e4SLinus Torvalds } 4711da177e4SLinus Torvalds } 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds return retval; 4741da177e4SLinus Torvalds } 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds /* 4781da177e4SLinus Torvalds * function: 4791da177e4SLinus Torvalds * 4801da177e4SLinus Torvalds * purpose: called if a port failed to be opened normally 4811da177e4SLinus Torvalds * initiates Forced Reopen recovery which is done 4821da177e4SLinus Torvalds * asynchronously 4831da177e4SLinus Torvalds * 484d6e05edcSAndreas Mohr * returns: 0 - initiated action successfully 4851da177e4SLinus Torvalds * <0 - failed to initiate action 4861da177e4SLinus Torvalds */ 4871da177e4SLinus Torvalds static int 4881da177e4SLinus Torvalds zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask) 4891da177e4SLinus Torvalds { 4901da177e4SLinus Torvalds int retval; 4911da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 4921da177e4SLinus Torvalds 4931da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "pf_ro"); 4941da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds ZFCP_LOG_DEBUG("forced reopen of port 0x%016Lx on adapter %s\n", 4971da177e4SLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 4981da177e4SLinus Torvalds 4991da177e4SLinus Torvalds zfcp_erp_port_block(port, clear_mask); 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { 5021da177e4SLinus Torvalds ZFCP_LOG_DEBUG("skipped forced reopen of failed port 0x%016Lx " 5031da177e4SLinus Torvalds "on adapter %s\n", port->wwpn, 5041da177e4SLinus Torvalds zfcp_get_busid_by_port(port)); 5051da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "pf_ro_f"); 5061da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 5071da177e4SLinus Torvalds retval = -EIO; 5081da177e4SLinus Torvalds goto out; 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, 5121da177e4SLinus Torvalds port->adapter, port, NULL); 5131da177e4SLinus Torvalds 5141da177e4SLinus Torvalds out: 5151da177e4SLinus Torvalds return retval; 5161da177e4SLinus Torvalds } 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds /* 5191da177e4SLinus Torvalds * function: 5201da177e4SLinus Torvalds * 5211da177e4SLinus Torvalds * purpose: Wrappper for zfcp_erp_port_forced_reopen_internal 5221da177e4SLinus Torvalds * used to ensure the correct locking 5231da177e4SLinus Torvalds * 524d6e05edcSAndreas Mohr * returns: 0 - initiated action successfully 5251da177e4SLinus Torvalds * <0 - failed to initiate action 5261da177e4SLinus Torvalds */ 5271da177e4SLinus Torvalds int 5281da177e4SLinus Torvalds zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask) 5291da177e4SLinus Torvalds { 5301da177e4SLinus Torvalds int retval; 5311da177e4SLinus Torvalds unsigned long flags; 5321da177e4SLinus Torvalds struct zfcp_adapter *adapter; 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds adapter = port->adapter; 5351da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 5361da177e4SLinus Torvalds write_lock(&adapter->erp_lock); 5371da177e4SLinus Torvalds retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask); 5381da177e4SLinus Torvalds write_unlock(&adapter->erp_lock); 5391da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds return retval; 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds /* 5451da177e4SLinus Torvalds * function: 5461da177e4SLinus Torvalds * 5471da177e4SLinus Torvalds * purpose: called if a port is to be opened 5481da177e4SLinus Torvalds * initiates Reopen recovery which is done 5491da177e4SLinus Torvalds * asynchronously 5501da177e4SLinus Torvalds * 551d6e05edcSAndreas Mohr * returns: 0 - initiated action successfully 5521da177e4SLinus Torvalds * <0 - failed to initiate action 5531da177e4SLinus Torvalds */ 5541da177e4SLinus Torvalds static int 5551da177e4SLinus Torvalds zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask) 5561da177e4SLinus Torvalds { 5571da177e4SLinus Torvalds int retval; 5581da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_ro"); 5611da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds ZFCP_LOG_DEBUG("reopen of port 0x%016Lx on adapter %s\n", 5641da177e4SLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 5651da177e4SLinus Torvalds 5661da177e4SLinus Torvalds zfcp_erp_port_block(port, clear_mask); 5671da177e4SLinus Torvalds 5681da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { 5691da177e4SLinus Torvalds ZFCP_LOG_DEBUG("skipped reopen of failed port 0x%016Lx " 5701da177e4SLinus Torvalds "on adapter %s\n", port->wwpn, 5711da177e4SLinus Torvalds zfcp_get_busid_by_port(port)); 5721da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_ro_f"); 5731da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 5741da177e4SLinus Torvalds /* ensure propagation of failed status to new devices */ 575698ec016SMartin Peschke zfcp_erp_port_failed(port, 14, 0); 5761da177e4SLinus Torvalds retval = -EIO; 5771da177e4SLinus Torvalds goto out; 5781da177e4SLinus Torvalds } 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, 5811da177e4SLinus Torvalds port->adapter, port, NULL); 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds out: 5841da177e4SLinus Torvalds return retval; 5851da177e4SLinus Torvalds } 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds /** 5881da177e4SLinus Torvalds * zfcp_erp_port_reopen - initiate reopen of a remote port 5891da177e4SLinus Torvalds * @port: port to be reopened 5901da177e4SLinus Torvalds * @clear_mask: specifies flags in port status to be cleared 5911da177e4SLinus Torvalds * Return: 0 on success, < 0 on error 5921da177e4SLinus Torvalds * 5931da177e4SLinus Torvalds * This is a wrappper function for zfcp_erp_port_reopen_internal. It ensures 5941da177e4SLinus Torvalds * correct locking. An error recovery task is initiated to do the reopen. 5951da177e4SLinus Torvalds * To wait for the completion of the reopen zfcp_erp_wait should be used. 5961da177e4SLinus Torvalds */ 5971da177e4SLinus Torvalds int 5981da177e4SLinus Torvalds zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask) 5991da177e4SLinus Torvalds { 6001da177e4SLinus Torvalds int retval; 6011da177e4SLinus Torvalds unsigned long flags; 6021da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 6031da177e4SLinus Torvalds 6041da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 6051da177e4SLinus Torvalds write_lock(&adapter->erp_lock); 6061da177e4SLinus Torvalds retval = zfcp_erp_port_reopen_internal(port, clear_mask); 6071da177e4SLinus Torvalds write_unlock(&adapter->erp_lock); 6081da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 6091da177e4SLinus Torvalds 6101da177e4SLinus Torvalds return retval; 6111da177e4SLinus Torvalds } 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds /* 6141da177e4SLinus Torvalds * function: 6151da177e4SLinus Torvalds * 6161da177e4SLinus Torvalds * purpose: called if a unit is to be opened 6171da177e4SLinus Torvalds * initiates Reopen recovery which is done 6181da177e4SLinus Torvalds * asynchronously 6191da177e4SLinus Torvalds * 620d6e05edcSAndreas Mohr * returns: 0 - initiated action successfully 6211da177e4SLinus Torvalds * <0 - failed to initiate action 6221da177e4SLinus Torvalds */ 6231da177e4SLinus Torvalds static int 6241da177e4SLinus Torvalds zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask) 6251da177e4SLinus Torvalds { 6261da177e4SLinus Torvalds int retval; 6271da177e4SLinus Torvalds struct zfcp_adapter *adapter = unit->port->adapter; 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "u_ro"); 6301da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); 6311da177e4SLinus Torvalds ZFCP_LOG_DEBUG("reopen of unit 0x%016Lx on port 0x%016Lx " 6321da177e4SLinus Torvalds "on adapter %s\n", unit->fcp_lun, 6331da177e4SLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds zfcp_erp_unit_block(unit, clear_mask); 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { 6381da177e4SLinus Torvalds ZFCP_LOG_DEBUG("skipped reopen of failed unit 0x%016Lx " 6391da177e4SLinus Torvalds "on port 0x%016Lx on adapter %s\n", 6401da177e4SLinus Torvalds unit->fcp_lun, unit->port->wwpn, 6411da177e4SLinus Torvalds zfcp_get_busid_by_unit(unit)); 6421da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "u_ro_f"); 6431da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, 6441da177e4SLinus Torvalds sizeof (fcp_lun_t)); 6451da177e4SLinus Torvalds retval = -EIO; 6461da177e4SLinus Torvalds goto out; 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, 6501da177e4SLinus Torvalds unit->port->adapter, unit->port, unit); 6511da177e4SLinus Torvalds out: 6521da177e4SLinus Torvalds return retval; 6531da177e4SLinus Torvalds } 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds /** 6561da177e4SLinus Torvalds * zfcp_erp_unit_reopen - initiate reopen of a unit 6571da177e4SLinus Torvalds * @unit: unit to be reopened 6581da177e4SLinus Torvalds * @clear_mask: specifies flags in unit status to be cleared 6591da177e4SLinus Torvalds * Return: 0 on success, < 0 on error 6601da177e4SLinus Torvalds * 6611da177e4SLinus Torvalds * This is a wrappper for zfcp_erp_unit_reopen_internal. It ensures correct 6621da177e4SLinus Torvalds * locking. An error recovery task is initiated to do the reopen. 6631da177e4SLinus Torvalds * To wait for the completion of the reopen zfcp_erp_wait should be used. 6641da177e4SLinus Torvalds */ 6651da177e4SLinus Torvalds int 6661da177e4SLinus Torvalds zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask) 6671da177e4SLinus Torvalds { 6681da177e4SLinus Torvalds int retval; 6691da177e4SLinus Torvalds unsigned long flags; 6701da177e4SLinus Torvalds struct zfcp_adapter *adapter; 6711da177e4SLinus Torvalds struct zfcp_port *port; 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds port = unit->port; 6741da177e4SLinus Torvalds adapter = port->adapter; 6751da177e4SLinus Torvalds 6761da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 6771da177e4SLinus Torvalds write_lock(&adapter->erp_lock); 6781da177e4SLinus Torvalds retval = zfcp_erp_unit_reopen_internal(unit, clear_mask); 6791da177e4SLinus Torvalds write_unlock(&adapter->erp_lock); 6801da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds return retval; 6831da177e4SLinus Torvalds } 6841da177e4SLinus Torvalds 685f6c0e7a7SAndreas Herrmann /** 686f6c0e7a7SAndreas Herrmann * zfcp_erp_adapter_block - mark adapter as blocked, block scsi requests 6871da177e4SLinus Torvalds */ 688f6c0e7a7SAndreas Herrmann static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) 6891da177e4SLinus Torvalds { 6901da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "a_bl"); 691698ec016SMartin Peschke zfcp_erp_modify_adapter_status(adapter, 15, 0, 6921da177e4SLinus Torvalds ZFCP_STATUS_COMMON_UNBLOCKED | 6931da177e4SLinus Torvalds clear_mask, ZFCP_CLEAR); 6941da177e4SLinus Torvalds } 6951da177e4SLinus Torvalds 696698ec016SMartin Peschke /* FIXME: isn't really atomic */ 697698ec016SMartin Peschke /* 698698ec016SMartin Peschke * returns the mask which has not been set so far, i.e. 699698ec016SMartin Peschke * 0 if no bit has been changed, !0 if some bit has been changed 700698ec016SMartin Peschke */ 701698ec016SMartin Peschke static int atomic_test_and_set_mask(unsigned long mask, atomic_t *v) 702698ec016SMartin Peschke { 703698ec016SMartin Peschke int changed_bits = (atomic_read(v) /*XOR*/^ mask) & mask; 704698ec016SMartin Peschke atomic_set_mask(mask, v); 705698ec016SMartin Peschke return changed_bits; 706698ec016SMartin Peschke } 707698ec016SMartin Peschke 708698ec016SMartin Peschke /* FIXME: isn't really atomic */ 709698ec016SMartin Peschke /* 710698ec016SMartin Peschke * returns the mask which has not been cleared so far, i.e. 711698ec016SMartin Peschke * 0 if no bit has been changed, !0 if some bit has been changed 712698ec016SMartin Peschke */ 713698ec016SMartin Peschke static int atomic_test_and_clear_mask(unsigned long mask, atomic_t *v) 714698ec016SMartin Peschke { 715698ec016SMartin Peschke int changed_bits = atomic_read(v) & mask; 716698ec016SMartin Peschke atomic_clear_mask(mask, v); 717698ec016SMartin Peschke return changed_bits; 718698ec016SMartin Peschke } 719698ec016SMartin Peschke 720f6c0e7a7SAndreas Herrmann /** 721f6c0e7a7SAndreas Herrmann * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests 7221da177e4SLinus Torvalds */ 723f6c0e7a7SAndreas Herrmann static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) 7241da177e4SLinus Torvalds { 7251da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "a_ubl"); 726698ec016SMartin Peschke if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, 727698ec016SMartin Peschke &adapter->status)) 728698ec016SMartin Peschke zfcp_rec_dbf_event_adapter(16, 0, adapter); 7291da177e4SLinus Torvalds } 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds /* 7321da177e4SLinus Torvalds * function: 7331da177e4SLinus Torvalds * 7341da177e4SLinus Torvalds * purpose: disable I/O, 7351da177e4SLinus Torvalds * return any open requests and clean them up, 7361da177e4SLinus Torvalds * aim: no pending and incoming I/O 7371da177e4SLinus Torvalds * 7381da177e4SLinus Torvalds * returns: 7391da177e4SLinus Torvalds */ 7401da177e4SLinus Torvalds static void 7411da177e4SLinus Torvalds zfcp_erp_port_block(struct zfcp_port *port, int clear_mask) 7421da177e4SLinus Torvalds { 7431da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 7441da177e4SLinus Torvalds 7451da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "p_bl"); 7461da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t)); 747698ec016SMartin Peschke zfcp_erp_modify_port_status(port, 17, 0, 7481da177e4SLinus Torvalds ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, 7491da177e4SLinus Torvalds ZFCP_CLEAR); 7501da177e4SLinus Torvalds } 7511da177e4SLinus Torvalds 7521da177e4SLinus Torvalds /* 7531da177e4SLinus Torvalds * function: 7541da177e4SLinus Torvalds * 7551da177e4SLinus Torvalds * purpose: enable I/O 7561da177e4SLinus Torvalds * 7571da177e4SLinus Torvalds * returns: 7581da177e4SLinus Torvalds */ 7591da177e4SLinus Torvalds static void 7601da177e4SLinus Torvalds zfcp_erp_port_unblock(struct zfcp_port *port) 7611da177e4SLinus Torvalds { 7621da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "p_ubl"); 7651da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t)); 766698ec016SMartin Peschke if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, 767698ec016SMartin Peschke &port->status)) 768698ec016SMartin Peschke zfcp_rec_dbf_event_port(18, 0, port); 7691da177e4SLinus Torvalds } 7701da177e4SLinus Torvalds 7711da177e4SLinus Torvalds /* 7721da177e4SLinus Torvalds * function: 7731da177e4SLinus Torvalds * 7741da177e4SLinus Torvalds * purpose: disable I/O, 7751da177e4SLinus Torvalds * return any open requests and clean them up, 7761da177e4SLinus Torvalds * aim: no pending and incoming I/O 7771da177e4SLinus Torvalds * 7781da177e4SLinus Torvalds * returns: 7791da177e4SLinus Torvalds */ 7801da177e4SLinus Torvalds static void 7811da177e4SLinus Torvalds zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) 7821da177e4SLinus Torvalds { 7831da177e4SLinus Torvalds struct zfcp_adapter *adapter = unit->port->adapter; 7841da177e4SLinus Torvalds 7851da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "u_bl"); 7861da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t)); 787698ec016SMartin Peschke zfcp_erp_modify_unit_status(unit, 19, 0, 7881da177e4SLinus Torvalds ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, 7891da177e4SLinus Torvalds ZFCP_CLEAR); 7901da177e4SLinus Torvalds } 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds /* 7931da177e4SLinus Torvalds * function: 7941da177e4SLinus Torvalds * 7951da177e4SLinus Torvalds * purpose: enable I/O 7961da177e4SLinus Torvalds * 7971da177e4SLinus Torvalds * returns: 7981da177e4SLinus Torvalds */ 7991da177e4SLinus Torvalds static void 8001da177e4SLinus Torvalds zfcp_erp_unit_unblock(struct zfcp_unit *unit) 8011da177e4SLinus Torvalds { 8021da177e4SLinus Torvalds struct zfcp_adapter *adapter = unit->port->adapter; 8031da177e4SLinus Torvalds 8041da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "u_ubl"); 8051da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t)); 806698ec016SMartin Peschke if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, 807698ec016SMartin Peschke &unit->status)) 808698ec016SMartin Peschke zfcp_rec_dbf_event_unit(20, 0, unit); 8091da177e4SLinus Torvalds } 8101da177e4SLinus Torvalds 8111da177e4SLinus Torvalds static void 8121da177e4SLinus Torvalds zfcp_erp_action_ready(struct zfcp_erp_action *erp_action) 8131da177e4SLinus Torvalds { 8141da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 8151da177e4SLinus Torvalds 8161da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "a_ar"); 8171da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int)); 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds zfcp_erp_action_to_ready(erp_action); 8201da177e4SLinus Torvalds up(&adapter->erp_ready_sem); 821348447e8SMartin Peschke zfcp_rec_dbf_event_thread(2, adapter, 0); 8221da177e4SLinus Torvalds } 8231da177e4SLinus Torvalds 8241da177e4SLinus Torvalds /* 8251da177e4SLinus Torvalds * function: 8261da177e4SLinus Torvalds * 8271da177e4SLinus Torvalds * purpose: 8281da177e4SLinus Torvalds * 8291da177e4SLinus Torvalds * returns: <0 erp_action not found in any list 8301da177e4SLinus Torvalds * ZFCP_ERP_ACTION_READY erp_action is in ready list 8311da177e4SLinus Torvalds * ZFCP_ERP_ACTION_RUNNING erp_action is in running list 8321da177e4SLinus Torvalds * 8331da177e4SLinus Torvalds * locks: erp_lock must be held 8341da177e4SLinus Torvalds */ 8351da177e4SLinus Torvalds static int 8361da177e4SLinus Torvalds zfcp_erp_action_exists(struct zfcp_erp_action *erp_action) 8371da177e4SLinus Torvalds { 8381da177e4SLinus Torvalds int retval = -EINVAL; 8391da177e4SLinus Torvalds struct list_head *entry; 8401da177e4SLinus Torvalds struct zfcp_erp_action *entry_erp_action; 8411da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 8421da177e4SLinus Torvalds 8431da177e4SLinus Torvalds /* search in running list */ 8441da177e4SLinus Torvalds list_for_each(entry, &adapter->erp_running_head) { 8451da177e4SLinus Torvalds entry_erp_action = 8461da177e4SLinus Torvalds list_entry(entry, struct zfcp_erp_action, list); 8471da177e4SLinus Torvalds if (entry_erp_action == erp_action) { 8481da177e4SLinus Torvalds retval = ZFCP_ERP_ACTION_RUNNING; 8491da177e4SLinus Torvalds goto out; 8501da177e4SLinus Torvalds } 8511da177e4SLinus Torvalds } 8521da177e4SLinus Torvalds /* search in ready list */ 8531da177e4SLinus Torvalds list_for_each(entry, &adapter->erp_ready_head) { 8541da177e4SLinus Torvalds entry_erp_action = 8551da177e4SLinus Torvalds list_entry(entry, struct zfcp_erp_action, list); 8561da177e4SLinus Torvalds if (entry_erp_action == erp_action) { 8571da177e4SLinus Torvalds retval = ZFCP_ERP_ACTION_READY; 8581da177e4SLinus Torvalds goto out; 8591da177e4SLinus Torvalds } 8601da177e4SLinus Torvalds } 8611da177e4SLinus Torvalds 8621da177e4SLinus Torvalds out: 8631da177e4SLinus Torvalds return retval; 8641da177e4SLinus Torvalds } 8651da177e4SLinus Torvalds 8661da177e4SLinus Torvalds /* 8671da177e4SLinus Torvalds * purpose: checks current status of action (timed out, dismissed, ...) 8681da177e4SLinus Torvalds * and does appropriate preparations (dismiss fsf request, ...) 8691da177e4SLinus Torvalds * 8701da177e4SLinus Torvalds * locks: called under erp_lock (disabled interrupts) 8711da177e4SLinus Torvalds */ 872ca880cf9SSwen Schillig static void 8731da177e4SLinus Torvalds zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) 8741da177e4SLinus Torvalds { 8751da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 8761da177e4SLinus Torvalds 8771da177e4SLinus Torvalds if (erp_action->fsf_req) { 878fea9d6c7SVolker Sameske /* take lock to ensure that request is not deleted meanwhile */ 879fea9d6c7SVolker Sameske spin_lock(&adapter->req_list_lock); 880d1ad09dbSHeiko Carstens if (zfcp_reqlist_find_safe(adapter, erp_action->fsf_req) && 881d1ad09dbSHeiko Carstens erp_action->fsf_req->erp_action == erp_action) { 8821da177e4SLinus Torvalds /* fsf_req still exists */ 8831da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); 884ca880cf9SSwen Schillig debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req, 8851da177e4SLinus Torvalds sizeof (unsigned long)); 886fea9d6c7SVolker Sameske /* dismiss fsf_req of timed out/dismissed erp_action */ 8871da177e4SLinus Torvalds if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | 8881da177e4SLinus Torvalds ZFCP_STATUS_ERP_TIMEDOUT)) { 8891da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, 8901da177e4SLinus Torvalds "a_ca_disreq"); 891ca880cf9SSwen Schillig erp_action->fsf_req->status |= 892ca880cf9SSwen Schillig ZFCP_STATUS_FSFREQ_DISMISSED; 8931da177e4SLinus Torvalds } 8941da177e4SLinus Torvalds if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { 8951da177e4SLinus Torvalds ZFCP_LOG_NORMAL("error: erp step timed out " 8961da177e4SLinus Torvalds "(action=%d, fsf_req=%p)\n ", 8971da177e4SLinus Torvalds erp_action->action, 8981da177e4SLinus Torvalds erp_action->fsf_req); 8991da177e4SLinus Torvalds } 9001da177e4SLinus Torvalds /* 9011da177e4SLinus Torvalds * If fsf_req is neither dismissed nor completed 9021da177e4SLinus Torvalds * then keep it running asynchronously and don't mess 9031da177e4SLinus Torvalds * with the association of erp_action and fsf_req. 9041da177e4SLinus Torvalds */ 905ca880cf9SSwen Schillig if (erp_action->fsf_req->status & 906ca880cf9SSwen Schillig (ZFCP_STATUS_FSFREQ_COMPLETED | 9071da177e4SLinus Torvalds ZFCP_STATUS_FSFREQ_DISMISSED)) { 9081da177e4SLinus Torvalds /* forget about association between fsf_req 9091da177e4SLinus Torvalds and erp_action */ 9101da177e4SLinus Torvalds erp_action->fsf_req = NULL; 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds } else { 9131da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_ca_gonereq"); 9141da177e4SLinus Torvalds /* 9151da177e4SLinus Torvalds * even if this fsf_req has gone, forget about 9161da177e4SLinus Torvalds * association between erp_action and fsf_req 9171da177e4SLinus Torvalds */ 9181da177e4SLinus Torvalds erp_action->fsf_req = NULL; 9191da177e4SLinus Torvalds } 920fea9d6c7SVolker Sameske spin_unlock(&adapter->req_list_lock); 9211da177e4SLinus Torvalds } else 9221da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); 9231da177e4SLinus Torvalds } 9241da177e4SLinus Torvalds 925f6c0e7a7SAndreas Herrmann /** 926f6c0e7a7SAndreas Herrmann * zfcp_erp_async_handler_nolock - complete erp_action 9271da177e4SLinus Torvalds * 928f6c0e7a7SAndreas Herrmann * Used for normal completion, time-out, dismissal and failure after 929f6c0e7a7SAndreas Herrmann * low memory condition. 9301da177e4SLinus Torvalds */ 931f6c0e7a7SAndreas Herrmann static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, 9321da177e4SLinus Torvalds unsigned long set_mask) 9331da177e4SLinus Torvalds { 9341da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 9351da177e4SLinus Torvalds 9361da177e4SLinus Torvalds if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { 9371da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "a_asyh_ex"); 9381da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 2, &erp_action->action, 9391da177e4SLinus Torvalds sizeof (int)); 9401da177e4SLinus Torvalds erp_action->status |= set_mask; 9411da177e4SLinus Torvalds zfcp_erp_action_ready(erp_action); 9421da177e4SLinus Torvalds } else { 9431da177e4SLinus Torvalds /* action is ready or gone - nothing to do */ 9441da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone"); 9451da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &erp_action->action, 9461da177e4SLinus Torvalds sizeof (int)); 947f6c0e7a7SAndreas Herrmann } 9481da177e4SLinus Torvalds } 9491da177e4SLinus Torvalds 950f6c0e7a7SAndreas Herrmann /** 951f6c0e7a7SAndreas Herrmann * zfcp_erp_async_handler - wrapper for erp_async_handler_nolock w/ locking 9521da177e4SLinus Torvalds */ 953f6c0e7a7SAndreas Herrmann void zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, 9541da177e4SLinus Torvalds unsigned long set_mask) 9551da177e4SLinus Torvalds { 9561da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 9571da177e4SLinus Torvalds unsigned long flags; 9581da177e4SLinus Torvalds 9591da177e4SLinus Torvalds write_lock_irqsave(&adapter->erp_lock, flags); 960f6c0e7a7SAndreas Herrmann zfcp_erp_async_handler_nolock(erp_action, set_mask); 9611da177e4SLinus Torvalds write_unlock_irqrestore(&adapter->erp_lock, flags); 9621da177e4SLinus Torvalds } 9631da177e4SLinus Torvalds 9641da177e4SLinus Torvalds /* 9651da177e4SLinus Torvalds * purpose: is called for erp_action which was slept waiting for 9661da177e4SLinus Torvalds * memory becoming avaliable, 9671da177e4SLinus Torvalds * will trigger that this action will be continued 9681da177e4SLinus Torvalds */ 9691da177e4SLinus Torvalds static void 9701da177e4SLinus Torvalds zfcp_erp_memwait_handler(unsigned long data) 9711da177e4SLinus Torvalds { 9721da177e4SLinus Torvalds struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; 9731da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 9741da177e4SLinus Torvalds 9751da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "a_mwh"); 9761da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); 9771da177e4SLinus Torvalds 9781da177e4SLinus Torvalds zfcp_erp_async_handler(erp_action, 0); 9791da177e4SLinus Torvalds } 9801da177e4SLinus Torvalds 9811da177e4SLinus Torvalds /* 9821da177e4SLinus Torvalds * purpose: is called if an asynchronous erp step timed out, 9831da177e4SLinus Torvalds * action gets an appropriate flag and will be processed 9841da177e4SLinus Torvalds * accordingly 9851da177e4SLinus Torvalds */ 986364c8558SHeiko Carstens static void zfcp_erp_timeout_handler(unsigned long data) 9871da177e4SLinus Torvalds { 9881da177e4SLinus Torvalds struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; 9891da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "a_th"); 9921da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); 9931da177e4SLinus Torvalds 9941da177e4SLinus Torvalds zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT); 9951da177e4SLinus Torvalds } 9961da177e4SLinus Torvalds 997f6c0e7a7SAndreas Herrmann /** 998f6c0e7a7SAndreas Herrmann * zfcp_erp_action_dismiss - dismiss an erp_action 9991da177e4SLinus Torvalds * 1000f6c0e7a7SAndreas Herrmann * adapter->erp_lock must be held 1001f6c0e7a7SAndreas Herrmann * 1002f6c0e7a7SAndreas Herrmann * Dismissal of an erp_action is usually required if an erp_action of 1003f6c0e7a7SAndreas Herrmann * higher priority is generated. 10041da177e4SLinus Torvalds */ 1005f6c0e7a7SAndreas Herrmann static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) 10061da177e4SLinus Torvalds { 10071da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 10081da177e4SLinus Torvalds 10091da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "a_adis"); 10101da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); 10111da177e4SLinus Torvalds 1012d0076f77SMartin Peschke erp_action->status |= ZFCP_STATUS_ERP_DISMISSED; 1013d0076f77SMartin Peschke if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) 1014d0076f77SMartin Peschke zfcp_erp_action_ready(erp_action); 10151da177e4SLinus Torvalds } 10161da177e4SLinus Torvalds 10171da177e4SLinus Torvalds int 10181da177e4SLinus Torvalds zfcp_erp_thread_setup(struct zfcp_adapter *adapter) 10191da177e4SLinus Torvalds { 10201da177e4SLinus Torvalds int retval = 0; 10211da177e4SLinus Torvalds 10221da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); 10231da177e4SLinus Torvalds 10241da177e4SLinus Torvalds retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); 10251da177e4SLinus Torvalds if (retval < 0) { 10261da177e4SLinus Torvalds ZFCP_LOG_NORMAL("error: creation of erp thread failed for " 10271da177e4SLinus Torvalds "adapter %s\n", 10281da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 10291da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_thset_fail"); 10301da177e4SLinus Torvalds } else { 10311da177e4SLinus Torvalds wait_event(adapter->erp_thread_wqh, 10321da177e4SLinus Torvalds atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, 10331da177e4SLinus Torvalds &adapter->status)); 10341da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_thset_ok"); 10351da177e4SLinus Torvalds } 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds return (retval < 0); 10381da177e4SLinus Torvalds } 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds /* 10411da177e4SLinus Torvalds * function: 10421da177e4SLinus Torvalds * 10431da177e4SLinus Torvalds * purpose: 10441da177e4SLinus Torvalds * 10451da177e4SLinus Torvalds * returns: 10461da177e4SLinus Torvalds * 10471da177e4SLinus Torvalds * context: process (i.e. proc-fs or rmmod/insmod) 10481da177e4SLinus Torvalds * 10491da177e4SLinus Torvalds * note: The caller of this routine ensures that the specified 10501da177e4SLinus Torvalds * adapter has been shut down and that this operation 10511da177e4SLinus Torvalds * has been completed. Thus, there are no pending erp_actions 10521da177e4SLinus Torvalds * which would need to be handled here. 10531da177e4SLinus Torvalds */ 10541da177e4SLinus Torvalds int 10551da177e4SLinus Torvalds zfcp_erp_thread_kill(struct zfcp_adapter *adapter) 10561da177e4SLinus Torvalds { 10571da177e4SLinus Torvalds int retval = 0; 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); 10601da177e4SLinus Torvalds up(&adapter->erp_ready_sem); 1061348447e8SMartin Peschke zfcp_rec_dbf_event_thread(2, adapter, 1); 10621da177e4SLinus Torvalds 10631da177e4SLinus Torvalds wait_event(adapter->erp_thread_wqh, 10641da177e4SLinus Torvalds !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, 10651da177e4SLinus Torvalds &adapter->status)); 10661da177e4SLinus Torvalds 10671da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, 10681da177e4SLinus Torvalds &adapter->status); 10691da177e4SLinus Torvalds 10701da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_thki_ok"); 10711da177e4SLinus Torvalds 10721da177e4SLinus Torvalds return retval; 10731da177e4SLinus Torvalds } 10741da177e4SLinus Torvalds 10751da177e4SLinus Torvalds /* 10761da177e4SLinus Torvalds * purpose: is run as a kernel thread, 10771da177e4SLinus Torvalds * goes through list of error recovery actions of associated adapter 10781da177e4SLinus Torvalds * and delegates single action to execution 10791da177e4SLinus Torvalds * 10801da177e4SLinus Torvalds * returns: 0 10811da177e4SLinus Torvalds */ 10821da177e4SLinus Torvalds static int 10831da177e4SLinus Torvalds zfcp_erp_thread(void *data) 10841da177e4SLinus Torvalds { 10851da177e4SLinus Torvalds struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; 10861da177e4SLinus Torvalds struct list_head *next; 10871da177e4SLinus Torvalds struct zfcp_erp_action *erp_action; 10881da177e4SLinus Torvalds unsigned long flags; 10891da177e4SLinus Torvalds 10901da177e4SLinus Torvalds daemonize("zfcperp%s", zfcp_get_busid_by_adapter(adapter)); 10911da177e4SLinus Torvalds /* Block all signals */ 10921da177e4SLinus Torvalds siginitsetinv(¤t->blocked, 0); 10931da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); 10941da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_th_run"); 10951da177e4SLinus Torvalds wake_up(&adapter->erp_thread_wqh); 10961da177e4SLinus Torvalds 10971da177e4SLinus Torvalds while (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, 10981da177e4SLinus Torvalds &adapter->status)) { 10991da177e4SLinus Torvalds 11001da177e4SLinus Torvalds write_lock_irqsave(&adapter->erp_lock, flags); 110186e8dfc5SMartin Peschke next = adapter->erp_ready_head.next; 11021da177e4SLinus Torvalds write_unlock_irqrestore(&adapter->erp_lock, flags); 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds if (next != &adapter->erp_ready_head) { 11051da177e4SLinus Torvalds erp_action = 11061da177e4SLinus Torvalds list_entry(next, struct zfcp_erp_action, list); 11071da177e4SLinus Torvalds /* 11081da177e4SLinus Torvalds * process action (incl. [re]moving it 11091da177e4SLinus Torvalds * from 'ready' queue) 11101da177e4SLinus Torvalds */ 11111da177e4SLinus Torvalds zfcp_erp_strategy(erp_action); 11121da177e4SLinus Torvalds } 11131da177e4SLinus Torvalds 11141da177e4SLinus Torvalds /* 11151da177e4SLinus Torvalds * sleep as long as there is nothing to do, i.e. 11161da177e4SLinus Torvalds * no action in 'ready' queue to be processed and 11171da177e4SLinus Torvalds * thread is not to be killed 11181da177e4SLinus Torvalds */ 1119348447e8SMartin Peschke zfcp_rec_dbf_event_thread(4, adapter, 1); 11201da177e4SLinus Torvalds down_interruptible(&adapter->erp_ready_sem); 1121348447e8SMartin Peschke zfcp_rec_dbf_event_thread(5, adapter, 1); 11221da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_th_woken"); 11231da177e4SLinus Torvalds } 11241da177e4SLinus Torvalds 11251da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); 11261da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_th_stop"); 11271da177e4SLinus Torvalds wake_up(&adapter->erp_thread_wqh); 11281da177e4SLinus Torvalds 11291da177e4SLinus Torvalds return 0; 11301da177e4SLinus Torvalds } 11311da177e4SLinus Torvalds 11321da177e4SLinus Torvalds /* 11331da177e4SLinus Torvalds * function: 11341da177e4SLinus Torvalds * 11351da177e4SLinus Torvalds * purpose: drives single error recovery action and schedules higher and 11361da177e4SLinus Torvalds * subordinate actions, if necessary 11371da177e4SLinus Torvalds * 11381da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 11391da177e4SLinus Torvalds * ZFCP_ERP_SUCCEEDED - action finished successfully (deqd) 11401da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully (deqd) 11411da177e4SLinus Torvalds * ZFCP_ERP_EXIT - action finished (dequeued), offline 11421da177e4SLinus Torvalds * ZFCP_ERP_DISMISSED - action canceled (dequeued) 11431da177e4SLinus Torvalds */ 11441da177e4SLinus Torvalds static int 11451da177e4SLinus Torvalds zfcp_erp_strategy(struct zfcp_erp_action *erp_action) 11461da177e4SLinus Torvalds { 11471da177e4SLinus Torvalds int retval = 0; 11481da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 11491da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 11501da177e4SLinus Torvalds struct zfcp_unit *unit = erp_action->unit; 11511da177e4SLinus Torvalds int action = erp_action->action; 11521da177e4SLinus Torvalds u32 status = erp_action->status; 11531da177e4SLinus Torvalds unsigned long flags; 11541da177e4SLinus Torvalds 11551da177e4SLinus Torvalds /* serialise dismissing, timing out, moving, enqueueing */ 11561da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 11571da177e4SLinus Torvalds write_lock(&adapter->erp_lock); 11581da177e4SLinus Torvalds 11591da177e4SLinus Torvalds /* dequeue dismissed action and leave, if required */ 11601da177e4SLinus Torvalds retval = zfcp_erp_strategy_check_action(erp_action, retval); 11611da177e4SLinus Torvalds if (retval == ZFCP_ERP_DISMISSED) { 11621da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "a_st_dis1"); 11631da177e4SLinus Torvalds goto unlock; 11641da177e4SLinus Torvalds } 11651da177e4SLinus Torvalds 11661da177e4SLinus Torvalds /* 11671da177e4SLinus Torvalds * move action to 'running' queue before processing it 11681da177e4SLinus Torvalds * (to avoid a race condition regarding moving the 11691da177e4SLinus Torvalds * action to the 'running' queue and back) 11701da177e4SLinus Torvalds */ 11711da177e4SLinus Torvalds zfcp_erp_action_to_running(erp_action); 11721da177e4SLinus Torvalds 11731da177e4SLinus Torvalds /* 11741da177e4SLinus Torvalds * try to process action as far as possible, 11751da177e4SLinus Torvalds * no lock to allow for blocking operations (kmalloc, qdio, ...), 11761da177e4SLinus Torvalds * afterwards the lock is required again for the following reasons: 11771da177e4SLinus Torvalds * - dequeueing of finished action and enqueueing of 11781da177e4SLinus Torvalds * follow-up actions must be atomic so that any other 11791da177e4SLinus Torvalds * reopen-routine does not believe there is nothing to do 11801da177e4SLinus Torvalds * and that it is safe to enqueue something else, 11811da177e4SLinus Torvalds * - we want to force any control thread which is dismissing 11821da177e4SLinus Torvalds * actions to finish this before we decide about 11831da177e4SLinus Torvalds * necessary steps to be taken here further 11841da177e4SLinus Torvalds */ 11851da177e4SLinus Torvalds write_unlock(&adapter->erp_lock); 11861da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 11871da177e4SLinus Torvalds retval = zfcp_erp_strategy_do_action(erp_action); 11881da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 11891da177e4SLinus Torvalds write_lock(&adapter->erp_lock); 11901da177e4SLinus Torvalds 11911da177e4SLinus Torvalds /* 11921da177e4SLinus Torvalds * check for dismissed status again to avoid follow-up actions, 119386e8dfc5SMartin Peschke * failing of targets and so on for dismissed actions, 119486e8dfc5SMartin Peschke * we go through down() here because there has been an up() 11951da177e4SLinus Torvalds */ 119686e8dfc5SMartin Peschke if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) 119786e8dfc5SMartin Peschke retval = ZFCP_ERP_CONTINUES; 11981da177e4SLinus Torvalds 11991da177e4SLinus Torvalds switch (retval) { 12001da177e4SLinus Torvalds case ZFCP_ERP_NOMEM: 12011da177e4SLinus Torvalds /* no memory to continue immediately, let it sleep */ 12021da177e4SLinus Torvalds if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) { 12031da177e4SLinus Torvalds ++adapter->erp_low_mem_count; 12041da177e4SLinus Torvalds erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; 12051da177e4SLinus Torvalds } 12061da177e4SLinus Torvalds /* This condition is true if there is no memory available 12071da177e4SLinus Torvalds for any erp_action on this adapter. This implies that there 12081da177e4SLinus Torvalds are no elements in the memory pool(s) left for erp_actions. 12091da177e4SLinus Torvalds This might happen if an erp_action that used a memory pool 12101da177e4SLinus Torvalds element was timed out. 12111da177e4SLinus Torvalds */ 12121da177e4SLinus Torvalds if (adapter->erp_total_count == adapter->erp_low_mem_count) { 12131da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_st_lowmem"); 12141da177e4SLinus Torvalds ZFCP_LOG_NORMAL("error: no mempool elements available, " 12151da177e4SLinus Torvalds "restarting I/O on adapter %s " 12161da177e4SLinus Torvalds "to free mempool\n", 12171da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 12181da177e4SLinus Torvalds zfcp_erp_adapter_reopen_internal(adapter, 0); 12191da177e4SLinus Torvalds } else { 12201da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "a_st_memw"); 12211da177e4SLinus Torvalds retval = zfcp_erp_strategy_memwait(erp_action); 12221da177e4SLinus Torvalds } 12231da177e4SLinus Torvalds goto unlock; 12241da177e4SLinus Torvalds case ZFCP_ERP_CONTINUES: 12251da177e4SLinus Torvalds /* leave since this action runs asynchronously */ 12261da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "a_st_cont"); 12271da177e4SLinus Torvalds if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { 12281da177e4SLinus Torvalds --adapter->erp_low_mem_count; 12291da177e4SLinus Torvalds erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; 12301da177e4SLinus Torvalds } 12311da177e4SLinus Torvalds goto unlock; 12321da177e4SLinus Torvalds } 12331da177e4SLinus Torvalds /* ok, finished action (whatever its result is) */ 12341da177e4SLinus Torvalds 12351da177e4SLinus Torvalds /* check for unrecoverable targets */ 12361da177e4SLinus Torvalds retval = zfcp_erp_strategy_check_target(erp_action, retval); 12371da177e4SLinus Torvalds 12381da177e4SLinus Torvalds /* action must be dequeued (here to allow for further ones) */ 12391da177e4SLinus Torvalds zfcp_erp_action_dequeue(erp_action); 12401da177e4SLinus Torvalds 12411da177e4SLinus Torvalds /* 12421da177e4SLinus Torvalds * put this target through the erp mill again if someone has 12431da177e4SLinus Torvalds * requested to change the status of a target being online 12441da177e4SLinus Torvalds * to offline or the other way around 12451da177e4SLinus Torvalds * (old retval is preserved if nothing has to be done here) 12461da177e4SLinus Torvalds */ 12471da177e4SLinus Torvalds retval = zfcp_erp_strategy_statechange(action, status, adapter, 12481da177e4SLinus Torvalds port, unit, retval); 12491da177e4SLinus Torvalds 12501da177e4SLinus Torvalds /* 12511da177e4SLinus Torvalds * leave if target is in permanent error state or if 12521da177e4SLinus Torvalds * action is repeated in order to process state change 12531da177e4SLinus Torvalds */ 12541da177e4SLinus Torvalds if (retval == ZFCP_ERP_EXIT) { 12551da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "a_st_exit"); 12561da177e4SLinus Torvalds goto unlock; 12571da177e4SLinus Torvalds } 12581da177e4SLinus Torvalds 12591da177e4SLinus Torvalds /* trigger follow up actions */ 12601da177e4SLinus Torvalds zfcp_erp_strategy_followup_actions(action, adapter, port, unit, retval); 12611da177e4SLinus Torvalds 12621da177e4SLinus Torvalds unlock: 12631da177e4SLinus Torvalds write_unlock(&adapter->erp_lock); 12641da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 12651da177e4SLinus Torvalds 12661da177e4SLinus Torvalds if (retval != ZFCP_ERP_CONTINUES) 12671da177e4SLinus Torvalds zfcp_erp_action_cleanup(action, adapter, port, unit, retval); 12681da177e4SLinus Torvalds 12691da177e4SLinus Torvalds /* 12701da177e4SLinus Torvalds * a few tasks remain when the erp queues are empty 12711da177e4SLinus Torvalds * (don't do that if the last action evaluated was dismissed 12721da177e4SLinus Torvalds * since this clearly indicates that there is more to come) : 12731da177e4SLinus Torvalds * - close the name server port if it is open yet 12741da177e4SLinus Torvalds * (enqueues another [probably] final action) 12751da177e4SLinus Torvalds * - otherwise, wake up whoever wants to be woken when we are 12761da177e4SLinus Torvalds * done with erp 12771da177e4SLinus Torvalds */ 12781da177e4SLinus Torvalds if (retval != ZFCP_ERP_DISMISSED) 12791da177e4SLinus Torvalds zfcp_erp_strategy_check_queues(adapter); 12801da177e4SLinus Torvalds 12811da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "a_st_done"); 12821da177e4SLinus Torvalds 12831da177e4SLinus Torvalds return retval; 12841da177e4SLinus Torvalds } 12851da177e4SLinus Torvalds 12861da177e4SLinus Torvalds /* 12871da177e4SLinus Torvalds * function: 12881da177e4SLinus Torvalds * 12891da177e4SLinus Torvalds * purpose: 12901da177e4SLinus Torvalds * 12911da177e4SLinus Torvalds * returns: ZFCP_ERP_DISMISSED - if action has been dismissed 12921da177e4SLinus Torvalds * retval - otherwise 12931da177e4SLinus Torvalds */ 12941da177e4SLinus Torvalds static int 12951da177e4SLinus Torvalds zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval) 12961da177e4SLinus Torvalds { 12971da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 12981da177e4SLinus Torvalds 12991da177e4SLinus Torvalds zfcp_erp_strategy_check_fsfreq(erp_action); 13001da177e4SLinus Torvalds 13011da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int)); 13021da177e4SLinus Torvalds if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) { 13031da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_stcd_dis"); 13041da177e4SLinus Torvalds zfcp_erp_action_dequeue(erp_action); 13051da177e4SLinus Torvalds retval = ZFCP_ERP_DISMISSED; 13061da177e4SLinus Torvalds } else 13071da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_stcd_nodis"); 13081da177e4SLinus Torvalds 13091da177e4SLinus Torvalds return retval; 13101da177e4SLinus Torvalds } 13111da177e4SLinus Torvalds 13121da177e4SLinus Torvalds static int 13131da177e4SLinus Torvalds zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) 13141da177e4SLinus Torvalds { 13151da177e4SLinus Torvalds int retval = ZFCP_ERP_FAILED; 13161da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 13171da177e4SLinus Torvalds 13181da177e4SLinus Torvalds /* 13191da177e4SLinus Torvalds * try to execute/continue action as far as possible, 13201da177e4SLinus Torvalds * note: no lock in subsequent strategy routines 13211da177e4SLinus Torvalds * (this allows these routine to call schedule, e.g. 13221da177e4SLinus Torvalds * kmalloc with such flags or qdio_initialize & friends) 13235d67d164SJoe Perches * Note: in case of timeout, the separate strategies will fail 13241da177e4SLinus Torvalds * anyhow. No need for a special action. Even worse, a nameserver 13251da177e4SLinus Torvalds * failure would not wake up waiting ports without the call. 13261da177e4SLinus Torvalds */ 13271da177e4SLinus Torvalds switch (erp_action->action) { 13281da177e4SLinus Torvalds 13291da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 13301da177e4SLinus Torvalds retval = zfcp_erp_adapter_strategy(erp_action); 13311da177e4SLinus Torvalds break; 13321da177e4SLinus Torvalds 13331da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: 13341da177e4SLinus Torvalds retval = zfcp_erp_port_forced_strategy(erp_action); 13351da177e4SLinus Torvalds break; 13361da177e4SLinus Torvalds 13371da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT: 13381da177e4SLinus Torvalds retval = zfcp_erp_port_strategy(erp_action); 13391da177e4SLinus Torvalds break; 13401da177e4SLinus Torvalds 13411da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_UNIT: 13421da177e4SLinus Torvalds retval = zfcp_erp_unit_strategy(erp_action); 13431da177e4SLinus Torvalds break; 13441da177e4SLinus Torvalds 13451da177e4SLinus Torvalds default: 13461da177e4SLinus Torvalds debug_text_exception(adapter->erp_dbf, 1, "a_stda_bug"); 13471da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 1, &erp_action->action, 13481da177e4SLinus Torvalds sizeof (int)); 13491da177e4SLinus Torvalds ZFCP_LOG_NORMAL("bug: unknown erp action requested on " 13501da177e4SLinus Torvalds "adapter %s (action=%d)\n", 13511da177e4SLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 13521da177e4SLinus Torvalds erp_action->action); 13531da177e4SLinus Torvalds } 13541da177e4SLinus Torvalds 13551da177e4SLinus Torvalds return retval; 13561da177e4SLinus Torvalds } 13571da177e4SLinus Torvalds 13581da177e4SLinus Torvalds /* 13591da177e4SLinus Torvalds * function: 13601da177e4SLinus Torvalds * 13611da177e4SLinus Torvalds * purpose: triggers retry of this action after a certain amount of time 13621da177e4SLinus Torvalds * by means of timer provided by erp_action 13631da177e4SLinus Torvalds * 13641da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - erp_action sleeps in erp running queue 13651da177e4SLinus Torvalds */ 13661da177e4SLinus Torvalds static int 13671da177e4SLinus Torvalds zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) 13681da177e4SLinus Torvalds { 13691da177e4SLinus Torvalds int retval = ZFCP_ERP_CONTINUES; 13701da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 13711da177e4SLinus Torvalds 13721da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "a_mwinit"); 13731da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int)); 13741da177e4SLinus Torvalds init_timer(&erp_action->timer); 13751da177e4SLinus Torvalds erp_action->timer.function = zfcp_erp_memwait_handler; 13761da177e4SLinus Torvalds erp_action->timer.data = (unsigned long) erp_action; 13771da177e4SLinus Torvalds erp_action->timer.expires = jiffies + ZFCP_ERP_MEMWAIT_TIMEOUT; 13781da177e4SLinus Torvalds add_timer(&erp_action->timer); 13791da177e4SLinus Torvalds 13801da177e4SLinus Torvalds return retval; 13811da177e4SLinus Torvalds } 13821da177e4SLinus Torvalds 13831da177e4SLinus Torvalds /* 13841da177e4SLinus Torvalds * function: zfcp_erp_adapter_failed 13851da177e4SLinus Torvalds * 13861da177e4SLinus Torvalds * purpose: sets the adapter and all underlying devices to ERP_FAILED 13871da177e4SLinus Torvalds * 13881da177e4SLinus Torvalds */ 13891da177e4SLinus Torvalds void 1390698ec016SMartin Peschke zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, u64 ref) 13911da177e4SLinus Torvalds { 1392698ec016SMartin Peschke zfcp_erp_modify_adapter_status(adapter, id, ref, 13931da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); 13941da177e4SLinus Torvalds ZFCP_LOG_NORMAL("adapter erp failed on adapter %s\n", 13951da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 13961da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "a_afail"); 13971da177e4SLinus Torvalds } 13981da177e4SLinus Torvalds 13991da177e4SLinus Torvalds /* 14001da177e4SLinus Torvalds * function: zfcp_erp_port_failed 14011da177e4SLinus Torvalds * 14021da177e4SLinus Torvalds * purpose: sets the port and all underlying devices to ERP_FAILED 14031da177e4SLinus Torvalds * 14041da177e4SLinus Torvalds */ 14051da177e4SLinus Torvalds void 1406698ec016SMartin Peschke zfcp_erp_port_failed(struct zfcp_port *port, u8 id, u64 ref) 14071da177e4SLinus Torvalds { 1408698ec016SMartin Peschke zfcp_erp_modify_port_status(port, id, ref, 14091da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); 14101da177e4SLinus Torvalds 14111da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) 14121da177e4SLinus Torvalds ZFCP_LOG_NORMAL("port erp failed (adapter %s, " 14131d589edfSChristof Schmitt "port d_id=0x%06x)\n", 14141da177e4SLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 14151da177e4SLinus Torvalds else 14161da177e4SLinus Torvalds ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n", 14171da177e4SLinus Torvalds zfcp_get_busid_by_port(port), port->wwpn); 14181da177e4SLinus Torvalds 14191da177e4SLinus Torvalds debug_text_event(port->adapter->erp_dbf, 2, "p_pfail"); 14201da177e4SLinus Torvalds debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t)); 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds /* 14241da177e4SLinus Torvalds * function: zfcp_erp_unit_failed 14251da177e4SLinus Torvalds * 14261da177e4SLinus Torvalds * purpose: sets the unit to ERP_FAILED 14271da177e4SLinus Torvalds * 14281da177e4SLinus Torvalds */ 14291da177e4SLinus Torvalds void 1430698ec016SMartin Peschke zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, u64 ref) 14311da177e4SLinus Torvalds { 1432698ec016SMartin Peschke zfcp_erp_modify_unit_status(unit, id, ref, 14331da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); 14341da177e4SLinus Torvalds 14351da177e4SLinus Torvalds ZFCP_LOG_NORMAL("unit erp failed on unit 0x%016Lx on port 0x%016Lx " 14361da177e4SLinus Torvalds " on adapter %s\n", unit->fcp_lun, 14371da177e4SLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 14381da177e4SLinus Torvalds debug_text_event(unit->port->adapter->erp_dbf, 2, "u_ufail"); 14391da177e4SLinus Torvalds debug_event(unit->port->adapter->erp_dbf, 2, 14401da177e4SLinus Torvalds &unit->fcp_lun, sizeof (fcp_lun_t)); 14411da177e4SLinus Torvalds } 14421da177e4SLinus Torvalds 14431da177e4SLinus Torvalds /* 14441da177e4SLinus Torvalds * function: zfcp_erp_strategy_check_target 14451da177e4SLinus Torvalds * 14461da177e4SLinus Torvalds * purpose: increments the erp action count on the device currently in 14471da177e4SLinus Torvalds * recovery if the action failed or resets the count in case of 14481da177e4SLinus Torvalds * success. If a maximum count is exceeded the device is marked 14491da177e4SLinus Torvalds * as ERP_FAILED. 14501da177e4SLinus Torvalds * The 'blocked' state of a target which has been recovered 14511da177e4SLinus Torvalds * successfully is reset. 14521da177e4SLinus Torvalds * 14531da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (not considered) 14541da177e4SLinus Torvalds * ZFCP_ERP_SUCCEEDED - action finished successfully 14551da177e4SLinus Torvalds * ZFCP_ERP_EXIT - action failed and will not continue 14561da177e4SLinus Torvalds */ 14571da177e4SLinus Torvalds static int 14581da177e4SLinus Torvalds zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result) 14591da177e4SLinus Torvalds { 14601da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 14611da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 14621da177e4SLinus Torvalds struct zfcp_unit *unit = erp_action->unit; 14631da177e4SLinus Torvalds 14641da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_stct_norm"); 14651da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int)); 14661da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &result, sizeof (int)); 14671da177e4SLinus Torvalds 14681da177e4SLinus Torvalds switch (erp_action->action) { 14691da177e4SLinus Torvalds 14701da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_UNIT: 14711da177e4SLinus Torvalds result = zfcp_erp_strategy_check_unit(unit, result); 14721da177e4SLinus Torvalds break; 14731da177e4SLinus Torvalds 14741da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: 14751da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT: 14761da177e4SLinus Torvalds result = zfcp_erp_strategy_check_port(port, result); 14771da177e4SLinus Torvalds break; 14781da177e4SLinus Torvalds 14791da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 14801da177e4SLinus Torvalds result = zfcp_erp_strategy_check_adapter(adapter, result); 14811da177e4SLinus Torvalds break; 14821da177e4SLinus Torvalds } 14831da177e4SLinus Torvalds 14841da177e4SLinus Torvalds return result; 14851da177e4SLinus Torvalds } 14861da177e4SLinus Torvalds 14871da177e4SLinus Torvalds static int 14881da177e4SLinus Torvalds zfcp_erp_strategy_statechange(int action, 14891da177e4SLinus Torvalds u32 status, 14901da177e4SLinus Torvalds struct zfcp_adapter *adapter, 14911da177e4SLinus Torvalds struct zfcp_port *port, 14921da177e4SLinus Torvalds struct zfcp_unit *unit, int retval) 14931da177e4SLinus Torvalds { 14941da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_stsc"); 14951da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &action, sizeof (int)); 14961da177e4SLinus Torvalds 14971da177e4SLinus Torvalds switch (action) { 14981da177e4SLinus Torvalds 14991da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 15001da177e4SLinus Torvalds if (zfcp_erp_strategy_statechange_detected(&adapter->status, 15011da177e4SLinus Torvalds status)) { 15021da177e4SLinus Torvalds zfcp_erp_adapter_reopen_internal(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); 15031da177e4SLinus Torvalds retval = ZFCP_ERP_EXIT; 15041da177e4SLinus Torvalds } 15051da177e4SLinus Torvalds break; 15061da177e4SLinus Torvalds 15071da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: 15081da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT: 15091da177e4SLinus Torvalds if (zfcp_erp_strategy_statechange_detected(&port->status, 15101da177e4SLinus Torvalds status)) { 15111da177e4SLinus Torvalds zfcp_erp_port_reopen_internal(port, ZFCP_STATUS_COMMON_ERP_FAILED); 15121da177e4SLinus Torvalds retval = ZFCP_ERP_EXIT; 15131da177e4SLinus Torvalds } 15141da177e4SLinus Torvalds break; 15151da177e4SLinus Torvalds 15161da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_UNIT: 15171da177e4SLinus Torvalds if (zfcp_erp_strategy_statechange_detected(&unit->status, 15181da177e4SLinus Torvalds status)) { 15191da177e4SLinus Torvalds zfcp_erp_unit_reopen_internal(unit, ZFCP_STATUS_COMMON_ERP_FAILED); 15201da177e4SLinus Torvalds retval = ZFCP_ERP_EXIT; 15211da177e4SLinus Torvalds } 15221da177e4SLinus Torvalds break; 15231da177e4SLinus Torvalds } 15241da177e4SLinus Torvalds 15251da177e4SLinus Torvalds return retval; 15261da177e4SLinus Torvalds } 15271da177e4SLinus Torvalds 1528364c8558SHeiko Carstens static int 15291da177e4SLinus Torvalds zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) 15301da177e4SLinus Torvalds { 15311da177e4SLinus Torvalds return 15321da177e4SLinus Torvalds /* take it online */ 15331da177e4SLinus Torvalds (atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) && 15341da177e4SLinus Torvalds (ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)) || 15351da177e4SLinus Torvalds /* take it offline */ 15361da177e4SLinus Torvalds (!atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) && 15371da177e4SLinus Torvalds !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)); 15381da177e4SLinus Torvalds } 15391da177e4SLinus Torvalds 15401da177e4SLinus Torvalds static int 15411da177e4SLinus Torvalds zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) 15421da177e4SLinus Torvalds { 15431da177e4SLinus Torvalds debug_text_event(unit->port->adapter->erp_dbf, 5, "u_stct"); 15441da177e4SLinus Torvalds debug_event(unit->port->adapter->erp_dbf, 5, &unit->fcp_lun, 15451da177e4SLinus Torvalds sizeof (fcp_lun_t)); 15461da177e4SLinus Torvalds 15471da177e4SLinus Torvalds switch (result) { 15481da177e4SLinus Torvalds case ZFCP_ERP_SUCCEEDED : 15491da177e4SLinus Torvalds atomic_set(&unit->erp_counter, 0); 15501da177e4SLinus Torvalds zfcp_erp_unit_unblock(unit); 15511da177e4SLinus Torvalds break; 15521da177e4SLinus Torvalds case ZFCP_ERP_FAILED : 15531da177e4SLinus Torvalds atomic_inc(&unit->erp_counter); 15541da177e4SLinus Torvalds if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) 1555698ec016SMartin Peschke zfcp_erp_unit_failed(unit, 21, 0); 15561da177e4SLinus Torvalds break; 15571da177e4SLinus Torvalds case ZFCP_ERP_EXIT : 15581da177e4SLinus Torvalds /* nothing */ 15591da177e4SLinus Torvalds break; 15601da177e4SLinus Torvalds } 15611da177e4SLinus Torvalds 15621da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { 15631da177e4SLinus Torvalds zfcp_erp_unit_block(unit, 0); /* for ZFCP_ERP_SUCCEEDED */ 15641da177e4SLinus Torvalds result = ZFCP_ERP_EXIT; 15651da177e4SLinus Torvalds } 15661da177e4SLinus Torvalds 15671da177e4SLinus Torvalds return result; 15681da177e4SLinus Torvalds } 15691da177e4SLinus Torvalds 15701da177e4SLinus Torvalds static int 15711da177e4SLinus Torvalds zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) 15721da177e4SLinus Torvalds { 15731da177e4SLinus Torvalds debug_text_event(port->adapter->erp_dbf, 5, "p_stct"); 15741da177e4SLinus Torvalds debug_event(port->adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 15751da177e4SLinus Torvalds 15761da177e4SLinus Torvalds switch (result) { 15771da177e4SLinus Torvalds case ZFCP_ERP_SUCCEEDED : 15781da177e4SLinus Torvalds atomic_set(&port->erp_counter, 0); 15791da177e4SLinus Torvalds zfcp_erp_port_unblock(port); 15801da177e4SLinus Torvalds break; 15811da177e4SLinus Torvalds case ZFCP_ERP_FAILED : 15821da177e4SLinus Torvalds atomic_inc(&port->erp_counter); 15831da177e4SLinus Torvalds if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) 1584698ec016SMartin Peschke zfcp_erp_port_failed(port, 22, 0); 15851da177e4SLinus Torvalds break; 15861da177e4SLinus Torvalds case ZFCP_ERP_EXIT : 15871da177e4SLinus Torvalds /* nothing */ 15881da177e4SLinus Torvalds break; 15891da177e4SLinus Torvalds } 15901da177e4SLinus Torvalds 15911da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { 15921da177e4SLinus Torvalds zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */ 15931da177e4SLinus Torvalds result = ZFCP_ERP_EXIT; 15941da177e4SLinus Torvalds } 15951da177e4SLinus Torvalds 15961da177e4SLinus Torvalds return result; 15971da177e4SLinus Torvalds } 15981da177e4SLinus Torvalds 15991da177e4SLinus Torvalds static int 16001da177e4SLinus Torvalds zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result) 16011da177e4SLinus Torvalds { 16021da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_stct"); 16031da177e4SLinus Torvalds 16041da177e4SLinus Torvalds switch (result) { 16051da177e4SLinus Torvalds case ZFCP_ERP_SUCCEEDED : 16061da177e4SLinus Torvalds atomic_set(&adapter->erp_counter, 0); 16071da177e4SLinus Torvalds zfcp_erp_adapter_unblock(adapter); 16081da177e4SLinus Torvalds break; 16091da177e4SLinus Torvalds case ZFCP_ERP_FAILED : 16101da177e4SLinus Torvalds atomic_inc(&adapter->erp_counter); 16111da177e4SLinus Torvalds if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) 1612698ec016SMartin Peschke zfcp_erp_adapter_failed(adapter, 23, 0); 16131da177e4SLinus Torvalds break; 16141da177e4SLinus Torvalds case ZFCP_ERP_EXIT : 16151da177e4SLinus Torvalds /* nothing */ 16161da177e4SLinus Torvalds break; 16171da177e4SLinus Torvalds } 16181da177e4SLinus Torvalds 16191da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { 16201da177e4SLinus Torvalds zfcp_erp_adapter_block(adapter, 0); /* for ZFCP_ERP_SUCCEEDED */ 16211da177e4SLinus Torvalds result = ZFCP_ERP_EXIT; 16221da177e4SLinus Torvalds } 16231da177e4SLinus Torvalds 16241da177e4SLinus Torvalds return result; 16251da177e4SLinus Torvalds } 16261da177e4SLinus Torvalds 16275f852be9SChristof Schmitt struct zfcp_erp_add_work { 16285f852be9SChristof Schmitt struct zfcp_unit *unit; 16295f852be9SChristof Schmitt struct work_struct work; 16305f852be9SChristof Schmitt }; 16315f852be9SChristof Schmitt 16325f852be9SChristof Schmitt /** 16335f852be9SChristof Schmitt * zfcp_erp_scsi_scan 16345f852be9SChristof Schmitt * @data: pointer to a struct zfcp_erp_add_work 16355f852be9SChristof Schmitt * 16365f852be9SChristof Schmitt * Registers a logical unit with the SCSI stack. 16375f852be9SChristof Schmitt */ 16385f852be9SChristof Schmitt static void zfcp_erp_scsi_scan(struct work_struct *work) 16395f852be9SChristof Schmitt { 16405f852be9SChristof Schmitt struct zfcp_erp_add_work *p = 16415f852be9SChristof Schmitt container_of(work, struct zfcp_erp_add_work, work); 16425f852be9SChristof Schmitt struct zfcp_unit *unit = p->unit; 16435f852be9SChristof Schmitt struct fc_rport *rport = unit->port->rport; 16445f852be9SChristof Schmitt scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, 16455f852be9SChristof Schmitt unit->scsi_lun, 0); 16465f852be9SChristof Schmitt atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); 16475f852be9SChristof Schmitt zfcp_unit_put(unit); 16485f852be9SChristof Schmitt kfree(p); 16495f852be9SChristof Schmitt } 16505f852be9SChristof Schmitt 16515f852be9SChristof Schmitt /** 16525f852be9SChristof Schmitt * zfcp_erp_schedule_work 16535f852be9SChristof Schmitt * @unit: pointer to unit which should be registered with SCSI stack 16545f852be9SChristof Schmitt * 16555f852be9SChristof Schmitt * Schedules work which registers a unit with the SCSI stack 16565f852be9SChristof Schmitt */ 16575f852be9SChristof Schmitt static void 16585f852be9SChristof Schmitt zfcp_erp_schedule_work(struct zfcp_unit *unit) 16595f852be9SChristof Schmitt { 16605f852be9SChristof Schmitt struct zfcp_erp_add_work *p; 16615f852be9SChristof Schmitt 16620d661327SSwen Schillig p = kzalloc(sizeof(*p), GFP_KERNEL); 16635f852be9SChristof Schmitt if (!p) { 16645f852be9SChristof Schmitt ZFCP_LOG_NORMAL("error: Out of resources. Could not register " 16655f852be9SChristof Schmitt "the FCP-LUN 0x%Lx connected to " 16665f852be9SChristof Schmitt "the port with WWPN 0x%Lx connected to " 16675f852be9SChristof Schmitt "the adapter %s with the SCSI stack.\n", 16685f852be9SChristof Schmitt unit->fcp_lun, 16695f852be9SChristof Schmitt unit->port->wwpn, 16705f852be9SChristof Schmitt zfcp_get_busid_by_unit(unit)); 16715f852be9SChristof Schmitt return; 16725f852be9SChristof Schmitt } 16735f852be9SChristof Schmitt 16745f852be9SChristof Schmitt zfcp_unit_get(unit); 16755f852be9SChristof Schmitt atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); 16765f852be9SChristof Schmitt INIT_WORK(&p->work, zfcp_erp_scsi_scan); 16775f852be9SChristof Schmitt p->unit = unit; 16785f852be9SChristof Schmitt schedule_work(&p->work); 16795f852be9SChristof Schmitt } 16805f852be9SChristof Schmitt 16811da177e4SLinus Torvalds /* 16821da177e4SLinus Torvalds * function: 16831da177e4SLinus Torvalds * 16841da177e4SLinus Torvalds * purpose: remaining things in good cases, 16851da177e4SLinus Torvalds * escalation in bad cases 16861da177e4SLinus Torvalds * 16871da177e4SLinus Torvalds * returns: 16881da177e4SLinus Torvalds */ 16891da177e4SLinus Torvalds static int 16901da177e4SLinus Torvalds zfcp_erp_strategy_followup_actions(int action, 16911da177e4SLinus Torvalds struct zfcp_adapter *adapter, 16921da177e4SLinus Torvalds struct zfcp_port *port, 16931da177e4SLinus Torvalds struct zfcp_unit *unit, int status) 16941da177e4SLinus Torvalds { 16951da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_stfol"); 16961da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &action, sizeof (int)); 16971da177e4SLinus Torvalds 16981da177e4SLinus Torvalds /* initiate follow-up actions depending on success of finished action */ 16991da177e4SLinus Torvalds switch (action) { 17001da177e4SLinus Torvalds 17011da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 17021da177e4SLinus Torvalds if (status == ZFCP_ERP_SUCCEEDED) 17031da177e4SLinus Torvalds zfcp_erp_port_reopen_all_internal(adapter, 0); 17041da177e4SLinus Torvalds else 17051da177e4SLinus Torvalds zfcp_erp_adapter_reopen_internal(adapter, 0); 17061da177e4SLinus Torvalds break; 17071da177e4SLinus Torvalds 17081da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: 17091da177e4SLinus Torvalds if (status == ZFCP_ERP_SUCCEEDED) 17101da177e4SLinus Torvalds zfcp_erp_port_reopen_internal(port, 0); 17111da177e4SLinus Torvalds else 17121da177e4SLinus Torvalds zfcp_erp_adapter_reopen_internal(adapter, 0); 17131da177e4SLinus Torvalds break; 17141da177e4SLinus Torvalds 17151da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT: 17161da177e4SLinus Torvalds if (status == ZFCP_ERP_SUCCEEDED) 17171da177e4SLinus Torvalds zfcp_erp_unit_reopen_all_internal(port, 0); 17181da177e4SLinus Torvalds else 17191da177e4SLinus Torvalds zfcp_erp_port_forced_reopen_internal(port, 0); 17201da177e4SLinus Torvalds break; 17211da177e4SLinus Torvalds 17221da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_UNIT: 1723cc16cebaSHeiko Carstens /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */ 1724cc16cebaSHeiko Carstens if (status != ZFCP_ERP_SUCCEEDED) 17251da177e4SLinus Torvalds zfcp_erp_port_reopen_internal(unit->port, 0); 17261da177e4SLinus Torvalds break; 17271da177e4SLinus Torvalds } 17281da177e4SLinus Torvalds 17291da177e4SLinus Torvalds return 0; 17301da177e4SLinus Torvalds } 17311da177e4SLinus Torvalds 17321da177e4SLinus Torvalds static int 17331da177e4SLinus Torvalds zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter) 17341da177e4SLinus Torvalds { 17351da177e4SLinus Torvalds unsigned long flags; 17361da177e4SLinus Torvalds 17371da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 17381da177e4SLinus Torvalds read_lock(&adapter->erp_lock); 17391da177e4SLinus Torvalds if (list_empty(&adapter->erp_ready_head) && 17401da177e4SLinus Torvalds list_empty(&adapter->erp_running_head)) { 17411da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "a_cq_wake"); 17421da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, 17431da177e4SLinus Torvalds &adapter->status); 17441da177e4SLinus Torvalds wake_up(&adapter->erp_done_wqh); 17451da177e4SLinus Torvalds } else 17461da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_cq_notempty"); 17471da177e4SLinus Torvalds read_unlock(&adapter->erp_lock); 17481da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 17491da177e4SLinus Torvalds 17501da177e4SLinus Torvalds return 0; 17511da177e4SLinus Torvalds } 17521da177e4SLinus Torvalds 17531da177e4SLinus Torvalds /** 17541da177e4SLinus Torvalds * zfcp_erp_wait - wait for completion of error recovery on an adapter 17551da177e4SLinus Torvalds * @adapter: adapter for which to wait for completion of its error recovery 17561da177e4SLinus Torvalds * Return: 0 17571da177e4SLinus Torvalds */ 17581da177e4SLinus Torvalds int 17591da177e4SLinus Torvalds zfcp_erp_wait(struct zfcp_adapter *adapter) 17601da177e4SLinus Torvalds { 17611da177e4SLinus Torvalds int retval = 0; 17621da177e4SLinus Torvalds 17631da177e4SLinus Torvalds wait_event(adapter->erp_done_wqh, 17641da177e4SLinus Torvalds !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, 17651da177e4SLinus Torvalds &adapter->status)); 17661da177e4SLinus Torvalds 17671da177e4SLinus Torvalds return retval; 17681da177e4SLinus Torvalds } 17691da177e4SLinus Torvalds 1770698ec016SMartin Peschke void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id, 1771698ec016SMartin Peschke u64 ref, u32 mask, int set_or_clear) 17721da177e4SLinus Torvalds { 17731da177e4SLinus Torvalds struct zfcp_port *port; 1774698ec016SMartin Peschke u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS; 17751da177e4SLinus Torvalds 17761da177e4SLinus Torvalds if (set_or_clear == ZFCP_SET) { 1777698ec016SMartin Peschke changed = atomic_test_and_set_mask(mask, &adapter->status); 17781da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_mod_as_s"); 17791da177e4SLinus Torvalds } else { 1780698ec016SMartin Peschke changed = atomic_test_and_clear_mask(mask, &adapter->status); 17811da177e4SLinus Torvalds if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) 17821da177e4SLinus Torvalds atomic_set(&adapter->erp_counter, 0); 17831da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_mod_as_c"); 17841da177e4SLinus Torvalds } 1785698ec016SMartin Peschke if (changed) 1786698ec016SMartin Peschke zfcp_rec_dbf_event_adapter(id, ref, adapter); 17871da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &mask, sizeof (u32)); 17881da177e4SLinus Torvalds 17891da177e4SLinus Torvalds /* Deal with all underlying devices, only pass common_mask */ 17901da177e4SLinus Torvalds if (common_mask) 17911da177e4SLinus Torvalds list_for_each_entry(port, &adapter->port_list_head, list) 1792698ec016SMartin Peschke zfcp_erp_modify_port_status(port, id, ref, common_mask, 17931da177e4SLinus Torvalds set_or_clear); 17941da177e4SLinus Torvalds } 17951da177e4SLinus Torvalds 17961da177e4SLinus Torvalds /* 17971da177e4SLinus Torvalds * function: zfcp_erp_modify_port_status 17981da177e4SLinus Torvalds * 17991da177e4SLinus Torvalds * purpose: sets the port and all underlying devices to ERP_FAILED 18001da177e4SLinus Torvalds * 18011da177e4SLinus Torvalds */ 1802698ec016SMartin Peschke void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, u64 ref, 1803698ec016SMartin Peschke u32 mask, int set_or_clear) 18041da177e4SLinus Torvalds { 18051da177e4SLinus Torvalds struct zfcp_unit *unit; 1806698ec016SMartin Peschke u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS; 18071da177e4SLinus Torvalds 18081da177e4SLinus Torvalds if (set_or_clear == ZFCP_SET) { 1809698ec016SMartin Peschke changed = atomic_test_and_set_mask(mask, &port->status); 18101da177e4SLinus Torvalds debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_s"); 18111da177e4SLinus Torvalds } else { 1812698ec016SMartin Peschke changed = atomic_test_and_clear_mask(mask, &port->status); 18131da177e4SLinus Torvalds if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) 18141da177e4SLinus Torvalds atomic_set(&port->erp_counter, 0); 18151da177e4SLinus Torvalds debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_c"); 18161da177e4SLinus Torvalds } 1817698ec016SMartin Peschke if (changed) 1818698ec016SMartin Peschke zfcp_rec_dbf_event_port(id, ref, port); 18191da177e4SLinus Torvalds debug_event(port->adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t)); 18201da177e4SLinus Torvalds debug_event(port->adapter->erp_dbf, 3, &mask, sizeof (u32)); 18211da177e4SLinus Torvalds 18221da177e4SLinus Torvalds /* Modify status of all underlying devices, only pass common mask */ 18231da177e4SLinus Torvalds if (common_mask) 18241da177e4SLinus Torvalds list_for_each_entry(unit, &port->unit_list_head, list) 1825698ec016SMartin Peschke zfcp_erp_modify_unit_status(unit, id, ref, common_mask, 18261da177e4SLinus Torvalds set_or_clear); 18271da177e4SLinus Torvalds } 18281da177e4SLinus Torvalds 18291da177e4SLinus Torvalds /* 18301da177e4SLinus Torvalds * function: zfcp_erp_modify_unit_status 18311da177e4SLinus Torvalds * 18321da177e4SLinus Torvalds * purpose: sets the unit to ERP_FAILED 18331da177e4SLinus Torvalds * 18341da177e4SLinus Torvalds */ 1835698ec016SMartin Peschke void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, u64 ref, 1836698ec016SMartin Peschke u32 mask, int set_or_clear) 18371da177e4SLinus Torvalds { 1838698ec016SMartin Peschke u32 changed; 1839698ec016SMartin Peschke 18401da177e4SLinus Torvalds if (set_or_clear == ZFCP_SET) { 1841698ec016SMartin Peschke changed = atomic_test_and_set_mask(mask, &unit->status); 18421da177e4SLinus Torvalds debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_s"); 18431da177e4SLinus Torvalds } else { 1844698ec016SMartin Peschke changed = atomic_test_and_clear_mask(mask, &unit->status); 18451da177e4SLinus Torvalds if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) { 18461da177e4SLinus Torvalds atomic_set(&unit->erp_counter, 0); 18471da177e4SLinus Torvalds } 18481da177e4SLinus Torvalds debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_c"); 18491da177e4SLinus Torvalds } 1850698ec016SMartin Peschke if (changed) 1851698ec016SMartin Peschke zfcp_rec_dbf_event_unit(id, ref, unit); 18521da177e4SLinus Torvalds debug_event(unit->port->adapter->erp_dbf, 3, &unit->fcp_lun, 18531da177e4SLinus Torvalds sizeof (fcp_lun_t)); 18541da177e4SLinus Torvalds debug_event(unit->port->adapter->erp_dbf, 3, &mask, sizeof (u32)); 18551da177e4SLinus Torvalds } 18561da177e4SLinus Torvalds 18571da177e4SLinus Torvalds /* 18581da177e4SLinus Torvalds * function: 18591da177e4SLinus Torvalds * 18601da177e4SLinus Torvalds * purpose: Wrappper for zfcp_erp_port_reopen_all_internal 18611da177e4SLinus Torvalds * used to ensure the correct locking 18621da177e4SLinus Torvalds * 1863d6e05edcSAndreas Mohr * returns: 0 - initiated action successfully 18641da177e4SLinus Torvalds * <0 - failed to initiate action 18651da177e4SLinus Torvalds */ 18661da177e4SLinus Torvalds int 18671da177e4SLinus Torvalds zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask) 18681da177e4SLinus Torvalds { 18691da177e4SLinus Torvalds int retval; 18701da177e4SLinus Torvalds unsigned long flags; 18711da177e4SLinus Torvalds 18721da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 18731da177e4SLinus Torvalds write_lock(&adapter->erp_lock); 18741da177e4SLinus Torvalds retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask); 18751da177e4SLinus Torvalds write_unlock(&adapter->erp_lock); 18761da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 18771da177e4SLinus Torvalds 18781da177e4SLinus Torvalds return retval; 18791da177e4SLinus Torvalds } 18801da177e4SLinus Torvalds 18811da177e4SLinus Torvalds static int 18821da177e4SLinus Torvalds zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask) 18831da177e4SLinus Torvalds { 18841da177e4SLinus Torvalds int retval = 0; 18851da177e4SLinus Torvalds struct zfcp_port *port; 18861da177e4SLinus Torvalds 18871da177e4SLinus Torvalds list_for_each_entry(port, &adapter->port_list_head, list) 18881da177e4SLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) 18891da177e4SLinus Torvalds zfcp_erp_port_reopen_internal(port, clear_mask); 18901da177e4SLinus Torvalds 18911da177e4SLinus Torvalds return retval; 18921da177e4SLinus Torvalds } 18931da177e4SLinus Torvalds 18941da177e4SLinus Torvalds /* 18951da177e4SLinus Torvalds * function: 18961da177e4SLinus Torvalds * 18971da177e4SLinus Torvalds * purpose: 18981da177e4SLinus Torvalds * 18991da177e4SLinus Torvalds * returns: FIXME 19001da177e4SLinus Torvalds */ 19011da177e4SLinus Torvalds static int 19021da177e4SLinus Torvalds zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, int clear_mask) 19031da177e4SLinus Torvalds { 19041da177e4SLinus Torvalds int retval = 0; 19051da177e4SLinus Torvalds struct zfcp_unit *unit; 19061da177e4SLinus Torvalds 19071da177e4SLinus Torvalds list_for_each_entry(unit, &port->unit_list_head, list) 19081da177e4SLinus Torvalds zfcp_erp_unit_reopen_internal(unit, clear_mask); 19091da177e4SLinus Torvalds 19101da177e4SLinus Torvalds return retval; 19111da177e4SLinus Torvalds } 19121da177e4SLinus Torvalds 19131da177e4SLinus Torvalds /* 19141da177e4SLinus Torvalds * function: 19151da177e4SLinus Torvalds * 19161da177e4SLinus Torvalds * purpose: this routine executes the 'Reopen Adapter' action 19171da177e4SLinus Torvalds * (the entire action is processed synchronously, since 19181da177e4SLinus Torvalds * there are no actions which might be run concurrently 19191da177e4SLinus Torvalds * per definition) 19201da177e4SLinus Torvalds * 19211da177e4SLinus Torvalds * returns: ZFCP_ERP_SUCCEEDED - action finished successfully 19221da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 19231da177e4SLinus Torvalds */ 19241da177e4SLinus Torvalds static int 19251da177e4SLinus Torvalds zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action) 19261da177e4SLinus Torvalds { 19271da177e4SLinus Torvalds int retval; 19281da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 19291da177e4SLinus Torvalds 19301da177e4SLinus Torvalds retval = zfcp_erp_adapter_strategy_close(erp_action); 19311da177e4SLinus Torvalds if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) 19321da177e4SLinus Torvalds retval = ZFCP_ERP_EXIT; 19331da177e4SLinus Torvalds else 19341da177e4SLinus Torvalds retval = zfcp_erp_adapter_strategy_open(erp_action); 19351da177e4SLinus Torvalds 19361da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "a_ast/ret"); 19371da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int)); 19381da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &retval, sizeof (int)); 19391da177e4SLinus Torvalds 19401da177e4SLinus Torvalds if (retval == ZFCP_ERP_FAILED) { 19411da177e4SLinus Torvalds ZFCP_LOG_INFO("Waiting to allow the adapter %s " 19421da177e4SLinus Torvalds "to recover itself\n", 19431da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 194418edcdbdSChristof Schmitt ssleep(ZFCP_TYPE2_RECOVERY_TIME); 19451da177e4SLinus Torvalds } 19461da177e4SLinus Torvalds 19471da177e4SLinus Torvalds return retval; 19481da177e4SLinus Torvalds } 19491da177e4SLinus Torvalds 19501da177e4SLinus Torvalds /* 19511da177e4SLinus Torvalds * function: 19521da177e4SLinus Torvalds * 19531da177e4SLinus Torvalds * purpose: 19541da177e4SLinus Torvalds * 19551da177e4SLinus Torvalds * returns: ZFCP_ERP_SUCCEEDED - action finished successfully 19561da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 19571da177e4SLinus Torvalds */ 19581da177e4SLinus Torvalds static int 19591da177e4SLinus Torvalds zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *erp_action) 19601da177e4SLinus Torvalds { 19611da177e4SLinus Torvalds int retval; 19621da177e4SLinus Torvalds 19631da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, 19641da177e4SLinus Torvalds &erp_action->adapter->status); 19651da177e4SLinus Torvalds retval = zfcp_erp_adapter_strategy_generic(erp_action, 1); 19661da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, 19671da177e4SLinus Torvalds &erp_action->adapter->status); 19681da177e4SLinus Torvalds 19691da177e4SLinus Torvalds return retval; 19701da177e4SLinus Torvalds } 19711da177e4SLinus Torvalds 19721da177e4SLinus Torvalds /* 19731da177e4SLinus Torvalds * function: 19741da177e4SLinus Torvalds * 19751da177e4SLinus Torvalds * purpose: 19761da177e4SLinus Torvalds * 19771da177e4SLinus Torvalds * returns: ZFCP_ERP_SUCCEEDED - action finished successfully 19781da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 19791da177e4SLinus Torvalds */ 19801da177e4SLinus Torvalds static int 19811da177e4SLinus Torvalds zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *erp_action) 19821da177e4SLinus Torvalds { 19831da177e4SLinus Torvalds int retval; 19841da177e4SLinus Torvalds 19851da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, 19861da177e4SLinus Torvalds &erp_action->adapter->status); 19871da177e4SLinus Torvalds retval = zfcp_erp_adapter_strategy_generic(erp_action, 0); 19881da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, 19891da177e4SLinus Torvalds &erp_action->adapter->status); 19901da177e4SLinus Torvalds 19911da177e4SLinus Torvalds return retval; 19921da177e4SLinus Torvalds } 19931da177e4SLinus Torvalds 19941da177e4SLinus Torvalds /* 19951da177e4SLinus Torvalds * function: zfcp_register_adapter 19961da177e4SLinus Torvalds * 19971da177e4SLinus Torvalds * purpose: allocate the irq associated with this devno and register 19981da177e4SLinus Torvalds * the FSF adapter with the SCSI stack 19991da177e4SLinus Torvalds * 20001da177e4SLinus Torvalds * returns: 20011da177e4SLinus Torvalds */ 20021da177e4SLinus Torvalds static int 20031da177e4SLinus Torvalds zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close) 20041da177e4SLinus Torvalds { 20051da177e4SLinus Torvalds int retval = ZFCP_ERP_SUCCEEDED; 20061da177e4SLinus Torvalds 20071da177e4SLinus Torvalds if (close) 20081da177e4SLinus Torvalds goto close_only; 20091da177e4SLinus Torvalds 20101da177e4SLinus Torvalds retval = zfcp_erp_adapter_strategy_open_qdio(erp_action); 20111da177e4SLinus Torvalds if (retval != ZFCP_ERP_SUCCEEDED) 20121da177e4SLinus Torvalds goto failed_qdio; 20131da177e4SLinus Torvalds 20141da177e4SLinus Torvalds retval = zfcp_erp_adapter_strategy_open_fsf(erp_action); 20151da177e4SLinus Torvalds if (retval != ZFCP_ERP_SUCCEEDED) 20161da177e4SLinus Torvalds goto failed_openfcp; 20171da177e4SLinus Torvalds 20181da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &erp_action->adapter->status); 20191da177e4SLinus Torvalds goto out; 20201da177e4SLinus Torvalds 20211da177e4SLinus Torvalds close_only: 20221da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, 20231da177e4SLinus Torvalds &erp_action->adapter->status); 20241da177e4SLinus Torvalds 20251da177e4SLinus Torvalds failed_openfcp: 20262abbe866SAndreas Herrmann zfcp_close_fsf(erp_action->adapter); 20271da177e4SLinus Torvalds failed_qdio: 2028c7f6b3a3SVolker Sameske atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | 2029c7f6b3a3SVolker Sameske ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | 2030c7f6b3a3SVolker Sameske ZFCP_STATUS_ADAPTER_XPORT_OK, 2031c7f6b3a3SVolker Sameske &erp_action->adapter->status); 20321da177e4SLinus Torvalds out: 20331da177e4SLinus Torvalds return retval; 20341da177e4SLinus Torvalds } 20351da177e4SLinus Torvalds 20361da177e4SLinus Torvalds /* 20371da177e4SLinus Torvalds * function: zfcp_qdio_init 20381da177e4SLinus Torvalds * 20391da177e4SLinus Torvalds * purpose: setup QDIO operation for specified adapter 20401da177e4SLinus Torvalds * 20411da177e4SLinus Torvalds * returns: 0 - successful setup 20421da177e4SLinus Torvalds * !0 - failed setup 20431da177e4SLinus Torvalds */ 2044364c8558SHeiko Carstens static int 20451da177e4SLinus Torvalds zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) 20461da177e4SLinus Torvalds { 20471da177e4SLinus Torvalds int retval; 20481da177e4SLinus Torvalds int i; 20491da177e4SLinus Torvalds volatile struct qdio_buffer_element *sbale; 20501da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 20511da177e4SLinus Torvalds 20521da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) { 20531da177e4SLinus Torvalds ZFCP_LOG_NORMAL("bug: second attempt to set up QDIO on " 20541da177e4SLinus Torvalds "adapter %s\n", 20551da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20561da177e4SLinus Torvalds goto failed_sanity; 20571da177e4SLinus Torvalds } 20581da177e4SLinus Torvalds 20591da177e4SLinus Torvalds if (qdio_establish(&adapter->qdio_init_data) != 0) { 20601da177e4SLinus Torvalds ZFCP_LOG_INFO("error: establishment of QDIO queues failed " 20611da177e4SLinus Torvalds "on adapter %s\n", 20621da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20631da177e4SLinus Torvalds goto failed_qdio_establish; 20641da177e4SLinus Torvalds } 20651da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "qdio_est"); 20661da177e4SLinus Torvalds 20671da177e4SLinus Torvalds if (qdio_activate(adapter->ccw_device, 0) != 0) { 20681da177e4SLinus Torvalds ZFCP_LOG_INFO("error: activation of QDIO queues failed " 20691da177e4SLinus Torvalds "on adapter %s\n", 20701da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20711da177e4SLinus Torvalds goto failed_qdio_activate; 20721da177e4SLinus Torvalds } 20731da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "qdio_act"); 20741da177e4SLinus Torvalds 20751da177e4SLinus Torvalds /* 20761da177e4SLinus Torvalds * put buffers into response queue, 20771da177e4SLinus Torvalds */ 20781da177e4SLinus Torvalds for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { 20791da177e4SLinus Torvalds sbale = &(adapter->response_queue.buffer[i]->element[0]); 20801da177e4SLinus Torvalds sbale->length = 0; 20811da177e4SLinus Torvalds sbale->flags = SBAL_FLAGS_LAST_ENTRY; 20826aae8738SAl Viro sbale->addr = NULL; 20831da177e4SLinus Torvalds } 20841da177e4SLinus Torvalds 20851da177e4SLinus Torvalds ZFCP_LOG_TRACE("calling do_QDIO on adapter %s (flags=0x%x, " 20861da177e4SLinus Torvalds "queue_no=%i, index_in_queue=%i, count=%i)\n", 20871da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter), 20881da177e4SLinus Torvalds QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q); 20891da177e4SLinus Torvalds 20901da177e4SLinus Torvalds retval = do_QDIO(adapter->ccw_device, 20911da177e4SLinus Torvalds QDIO_FLAG_SYNC_INPUT, 20921da177e4SLinus Torvalds 0, 0, QDIO_MAX_BUFFERS_PER_Q, NULL); 20931da177e4SLinus Torvalds 20941da177e4SLinus Torvalds if (retval) { 20951da177e4SLinus Torvalds ZFCP_LOG_NORMAL("bug: setup of QDIO failed (retval=%d)\n", 20961da177e4SLinus Torvalds retval); 20971da177e4SLinus Torvalds goto failed_do_qdio; 20981da177e4SLinus Torvalds } else { 20991da177e4SLinus Torvalds adapter->response_queue.free_index = 0; 21001da177e4SLinus Torvalds atomic_set(&adapter->response_queue.free_count, 0); 21011da177e4SLinus Torvalds ZFCP_LOG_DEBUG("%i buffers successfully enqueued to " 21021da177e4SLinus Torvalds "response queue\n", QDIO_MAX_BUFFERS_PER_Q); 21031da177e4SLinus Torvalds } 21041da177e4SLinus Torvalds /* set index of first avalable SBALS / number of available SBALS */ 21051da177e4SLinus Torvalds adapter->request_queue.free_index = 0; 21061da177e4SLinus Torvalds atomic_set(&adapter->request_queue.free_count, QDIO_MAX_BUFFERS_PER_Q); 21071da177e4SLinus Torvalds adapter->request_queue.distance_from_int = 0; 21081da177e4SLinus Torvalds 21091da177e4SLinus Torvalds /* initialize waitqueue used to wait for free SBALs in requests queue */ 21101da177e4SLinus Torvalds init_waitqueue_head(&adapter->request_wq); 21111da177e4SLinus Torvalds 21121da177e4SLinus Torvalds /* ok, we did it - skip all cleanups for different failures */ 21131da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); 21141da177e4SLinus Torvalds retval = ZFCP_ERP_SUCCEEDED; 21151da177e4SLinus Torvalds goto out; 21161da177e4SLinus Torvalds 21171da177e4SLinus Torvalds failed_do_qdio: 21181da177e4SLinus Torvalds /* NOP */ 21191da177e4SLinus Torvalds 21201da177e4SLinus Torvalds failed_qdio_activate: 21211da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "qdio_down1a"); 21221da177e4SLinus Torvalds while (qdio_shutdown(adapter->ccw_device, 21231da177e4SLinus Torvalds QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) 212418edcdbdSChristof Schmitt ssleep(1); 21251da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "qdio_down1b"); 21261da177e4SLinus Torvalds 21271da177e4SLinus Torvalds failed_qdio_establish: 21281da177e4SLinus Torvalds failed_sanity: 21291da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 21301da177e4SLinus Torvalds 21311da177e4SLinus Torvalds out: 21321da177e4SLinus Torvalds return retval; 21331da177e4SLinus Torvalds } 21341da177e4SLinus Torvalds 21351da177e4SLinus Torvalds 21361da177e4SLinus Torvalds static int 21371da177e4SLinus Torvalds zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) 21381da177e4SLinus Torvalds { 21392448c459SAndreas Herrmann int retval; 21401da177e4SLinus Torvalds 21412448c459SAndreas Herrmann retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); 21422448c459SAndreas Herrmann if (retval == ZFCP_ERP_FAILED) 21432448c459SAndreas Herrmann return ZFCP_ERP_FAILED; 21442448c459SAndreas Herrmann 21452448c459SAndreas Herrmann retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); 21462448c459SAndreas Herrmann if (retval == ZFCP_ERP_FAILED) 2147aef4a983SMaxim Shchetynin return ZFCP_ERP_FAILED; 2148aef4a983SMaxim Shchetynin 2149aef4a983SMaxim Shchetynin return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); 21501da177e4SLinus Torvalds } 21511da177e4SLinus Torvalds 21521da177e4SLinus Torvalds static int 21531da177e4SLinus Torvalds zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) 21541da177e4SLinus Torvalds { 21551da177e4SLinus Torvalds int retval = ZFCP_ERP_SUCCEEDED; 21561da177e4SLinus Torvalds int retries; 215722753fa5SAndreas Herrmann int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP; 21581da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 21591da177e4SLinus Torvalds 21601da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); 21611da177e4SLinus Torvalds 216222753fa5SAndreas Herrmann for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) { 21631da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, 21641da177e4SLinus Torvalds &adapter->status); 21651da177e4SLinus Torvalds ZFCP_LOG_DEBUG("Doing exchange config data\n"); 21669f09c548SHeiko Carstens write_lock_irq(&adapter->erp_lock); 21671da177e4SLinus Torvalds zfcp_erp_action_to_running(erp_action); 21689f09c548SHeiko Carstens write_unlock_irq(&adapter->erp_lock); 21691da177e4SLinus Torvalds if (zfcp_fsf_exchange_config_data(erp_action)) { 21701da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 21711da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); 21721da177e4SLinus Torvalds ZFCP_LOG_INFO("error: initiation of exchange of " 21731da177e4SLinus Torvalds "configuration data failed for " 21741da177e4SLinus Torvalds "adapter %s\n", 21751da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21761da177e4SLinus Torvalds break; 21771da177e4SLinus Torvalds } 21781da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); 21791da177e4SLinus Torvalds ZFCP_LOG_DEBUG("Xchange underway\n"); 21801da177e4SLinus Torvalds 21811da177e4SLinus Torvalds /* 21821da177e4SLinus Torvalds * Why this works: 21831da177e4SLinus Torvalds * Both the normal completion handler as well as the timeout 21841da177e4SLinus Torvalds * handler will do an 'up' when the 'exchange config data' 21851da177e4SLinus Torvalds * request completes or times out. Thus, the signal to go on 21861da177e4SLinus Torvalds * won't be lost utilizing this semaphore. 21871da177e4SLinus Torvalds * Furthermore, this 'adapter_reopen' action is 21881da177e4SLinus Torvalds * guaranteed to be the only action being there (highest action 21891da177e4SLinus Torvalds * which prevents other actions from being created). 21901da177e4SLinus Torvalds * Resulting from that, the wake signal recognized here 21911da177e4SLinus Torvalds * _must_ be the one belonging to the 'exchange config 21921da177e4SLinus Torvalds * data' request. 21931da177e4SLinus Torvalds */ 2194348447e8SMartin Peschke zfcp_rec_dbf_event_thread(6, adapter, 1); 21951da177e4SLinus Torvalds down(&adapter->erp_ready_sem); 2196348447e8SMartin Peschke zfcp_rec_dbf_event_thread(7, adapter, 1); 21971da177e4SLinus Torvalds if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { 21981da177e4SLinus Torvalds ZFCP_LOG_INFO("error: exchange of configuration data " 21991da177e4SLinus Torvalds "for adapter %s timed out\n", 22001da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 22011da177e4SLinus Torvalds break; 22021da177e4SLinus Torvalds } 220322753fa5SAndreas Herrmann 220422753fa5SAndreas Herrmann if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, 220522753fa5SAndreas Herrmann &adapter->status)) 220622753fa5SAndreas Herrmann break; 220722753fa5SAndreas Herrmann 22081da177e4SLinus Torvalds ZFCP_LOG_DEBUG("host connection still initialising... " 22091da177e4SLinus Torvalds "waiting and retrying...\n"); 22101da177e4SLinus Torvalds /* sleep a little bit before retry */ 221118edcdbdSChristof Schmitt ssleep(sleep); 221222753fa5SAndreas Herrmann sleep *= 2; 22131da177e4SLinus Torvalds } 22141da177e4SLinus Torvalds 2215c7f6b3a3SVolker Sameske atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, 2216c7f6b3a3SVolker Sameske &adapter->status); 2217c7f6b3a3SVolker Sameske 22181da177e4SLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, 22191da177e4SLinus Torvalds &adapter->status)) { 22201da177e4SLinus Torvalds ZFCP_LOG_INFO("error: exchange of configuration data for " 22211da177e4SLinus Torvalds "adapter %s failed\n", 22221da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 22231da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 22241da177e4SLinus Torvalds } 22251da177e4SLinus Torvalds 22261da177e4SLinus Torvalds return retval; 22271da177e4SLinus Torvalds } 22281da177e4SLinus Torvalds 2229aef4a983SMaxim Shchetynin static int 2230aef4a983SMaxim Shchetynin zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) 2231aef4a983SMaxim Shchetynin { 22322448c459SAndreas Herrmann int ret; 22332f8f3ed5SAndreas Herrmann struct zfcp_adapter *adapter; 2234aef4a983SMaxim Shchetynin 22352f8f3ed5SAndreas Herrmann adapter = erp_action->adapter; 2236aef4a983SMaxim Shchetynin atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); 2237aef4a983SMaxim Shchetynin 22389f09c548SHeiko Carstens write_lock_irq(&adapter->erp_lock); 2239aef4a983SMaxim Shchetynin zfcp_erp_action_to_running(erp_action); 22409f09c548SHeiko Carstens write_unlock_irq(&adapter->erp_lock); 22412f8f3ed5SAndreas Herrmann 224252ef11a7SSwen Schillig ret = zfcp_fsf_exchange_port_data(erp_action); 22432448c459SAndreas Herrmann if (ret == -EOPNOTSUPP) { 22442448c459SAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); 22452448c459SAndreas Herrmann return ZFCP_ERP_SUCCEEDED; 22462448c459SAndreas Herrmann } else if (ret) { 22472448c459SAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); 22482448c459SAndreas Herrmann return ZFCP_ERP_FAILED; 2249aef4a983SMaxim Shchetynin } 22502448c459SAndreas Herrmann debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); 2251aef4a983SMaxim Shchetynin 22522f8f3ed5SAndreas Herrmann ret = ZFCP_ERP_SUCCEEDED; 2253348447e8SMartin Peschke zfcp_rec_dbf_event_thread(8, adapter, 1); 2254aef4a983SMaxim Shchetynin down(&adapter->erp_ready_sem); 2255348447e8SMartin Peschke zfcp_rec_dbf_event_thread(9, adapter, 1); 2256aef4a983SMaxim Shchetynin if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { 22572f8f3ed5SAndreas Herrmann ZFCP_LOG_INFO("error: exchange port data timed out (adapter " 22582f8f3ed5SAndreas Herrmann "%s)\n", zfcp_get_busid_by_adapter(adapter)); 22592f8f3ed5SAndreas Herrmann ret = ZFCP_ERP_FAILED; 2260aef4a983SMaxim Shchetynin } 2261f6c0e7a7SAndreas Herrmann 2262f6c0e7a7SAndreas Herrmann /* don't treat as error for the sake of compatibility */ 2263f6c0e7a7SAndreas Herrmann if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) 2264f6c0e7a7SAndreas Herrmann ZFCP_LOG_INFO("warning: exchange port data failed (adapter " 22652f8f3ed5SAndreas Herrmann "%s\n", zfcp_get_busid_by_adapter(adapter)); 2266aef4a983SMaxim Shchetynin 22672f8f3ed5SAndreas Herrmann return ret; 2268aef4a983SMaxim Shchetynin } 2269aef4a983SMaxim Shchetynin 22701da177e4SLinus Torvalds static int 22711da177e4SLinus Torvalds zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action 22721da177e4SLinus Torvalds *erp_action) 22731da177e4SLinus Torvalds { 22741da177e4SLinus Torvalds int retval = ZFCP_ERP_SUCCEEDED; 22751da177e4SLinus Torvalds int temp_ret; 22761da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 22771da177e4SLinus Torvalds int i; 22781da177e4SLinus Torvalds 22791da177e4SLinus Torvalds adapter->status_read_failed = 0; 22801da177e4SLinus Torvalds for (i = 0; i < ZFCP_STATUS_READS_RECOM; i++) { 22811da177e4SLinus Torvalds temp_ret = zfcp_fsf_status_read(adapter, ZFCP_WAIT_FOR_SBAL); 22821da177e4SLinus Torvalds if (temp_ret < 0) { 22831da177e4SLinus Torvalds ZFCP_LOG_INFO("error: set-up of unsolicited status " 22841da177e4SLinus Torvalds "notification failed on adapter %s\n", 22851da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 22861da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 22871da177e4SLinus Torvalds i--; 22881da177e4SLinus Torvalds break; 22891da177e4SLinus Torvalds } 22901da177e4SLinus Torvalds } 22911da177e4SLinus Torvalds 22921da177e4SLinus Torvalds return retval; 22931da177e4SLinus Torvalds } 22941da177e4SLinus Torvalds 22951da177e4SLinus Torvalds /* 22961da177e4SLinus Torvalds * function: 22971da177e4SLinus Torvalds * 22981da177e4SLinus Torvalds * purpose: this routine executes the 'Reopen Physical Port' action 22991da177e4SLinus Torvalds * 23001da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 23011da177e4SLinus Torvalds * ZFCP_ERP_SUCCEEDED - action finished successfully 23021da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 23031da177e4SLinus Torvalds */ 23041da177e4SLinus Torvalds static int 23051da177e4SLinus Torvalds zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action) 23061da177e4SLinus Torvalds { 23071da177e4SLinus Torvalds int retval = ZFCP_ERP_FAILED; 23081da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 23091da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 23101da177e4SLinus Torvalds 23111da177e4SLinus Torvalds switch (erp_action->step) { 23121da177e4SLinus Torvalds 23131da177e4SLinus Torvalds /* 23141da177e4SLinus Torvalds * FIXME: 23151da177e4SLinus Torvalds * the ULP spec. begs for waiting for oustanding commands 23161da177e4SLinus Torvalds */ 23171da177e4SLinus Torvalds case ZFCP_ERP_STEP_UNINITIALIZED: 23181da177e4SLinus Torvalds zfcp_erp_port_strategy_clearstati(port); 23191da177e4SLinus Torvalds /* 23201da177e4SLinus Torvalds * it would be sufficient to test only the normal open flag 23211da177e4SLinus Torvalds * since the phys. open flag cannot be set if the normal 23221da177e4SLinus Torvalds * open flag is unset - however, this is for readabilty ... 23231da177e4SLinus Torvalds */ 23241da177e4SLinus Torvalds if (atomic_test_mask((ZFCP_STATUS_PORT_PHYS_OPEN | 23251da177e4SLinus Torvalds ZFCP_STATUS_COMMON_OPEN), 23261da177e4SLinus Torvalds &port->status)) { 23271da177e4SLinus Torvalds ZFCP_LOG_DEBUG("port 0x%016Lx is open -> trying " 23281da177e4SLinus Torvalds "close physical\n", port->wwpn); 23291da177e4SLinus Torvalds retval = 23301da177e4SLinus Torvalds zfcp_erp_port_forced_strategy_close(erp_action); 23311da177e4SLinus Torvalds } else 23321da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 23331da177e4SLinus Torvalds break; 23341da177e4SLinus Torvalds 23351da177e4SLinus Torvalds case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: 23361da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_PORT_PHYS_OPEN, 23371da177e4SLinus Torvalds &port->status)) { 23381da177e4SLinus Torvalds ZFCP_LOG_DEBUG("close physical failed for port " 23391da177e4SLinus Torvalds "0x%016Lx\n", port->wwpn); 23401da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 23411da177e4SLinus Torvalds } else 23421da177e4SLinus Torvalds retval = ZFCP_ERP_SUCCEEDED; 23431da177e4SLinus Torvalds break; 23441da177e4SLinus Torvalds } 23451da177e4SLinus Torvalds 23461da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "p_pfst/ret"); 23471da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t)); 23481da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int)); 23491da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &retval, sizeof (int)); 23501da177e4SLinus Torvalds 23511da177e4SLinus Torvalds return retval; 23521da177e4SLinus Torvalds } 23531da177e4SLinus Torvalds 23541da177e4SLinus Torvalds /* 23551da177e4SLinus Torvalds * function: 23561da177e4SLinus Torvalds * 23571da177e4SLinus Torvalds * purpose: this routine executes the 'Reopen Port' action 23581da177e4SLinus Torvalds * 23591da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 23601da177e4SLinus Torvalds * ZFCP_ERP_SUCCEEDED - action finished successfully 23611da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 23621da177e4SLinus Torvalds */ 23631da177e4SLinus Torvalds static int 23641da177e4SLinus Torvalds zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) 23651da177e4SLinus Torvalds { 23661da177e4SLinus Torvalds int retval = ZFCP_ERP_FAILED; 23671da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 23681da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 23691da177e4SLinus Torvalds 23701da177e4SLinus Torvalds switch (erp_action->step) { 23711da177e4SLinus Torvalds 23721da177e4SLinus Torvalds /* 23731da177e4SLinus Torvalds * FIXME: 23741da177e4SLinus Torvalds * the ULP spec. begs for waiting for oustanding commands 23751da177e4SLinus Torvalds */ 23761da177e4SLinus Torvalds case ZFCP_ERP_STEP_UNINITIALIZED: 23771da177e4SLinus Torvalds zfcp_erp_port_strategy_clearstati(port); 23781da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) { 23791da177e4SLinus Torvalds ZFCP_LOG_DEBUG("port 0x%016Lx is open -> trying " 23801da177e4SLinus Torvalds "close\n", port->wwpn); 23811da177e4SLinus Torvalds retval = zfcp_erp_port_strategy_close(erp_action); 23821da177e4SLinus Torvalds goto out; 23831da177e4SLinus Torvalds } /* else it's already closed, open it */ 23841da177e4SLinus Torvalds break; 23851da177e4SLinus Torvalds 23861da177e4SLinus Torvalds case ZFCP_ERP_STEP_PORT_CLOSING: 23871da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) { 23881da177e4SLinus Torvalds ZFCP_LOG_DEBUG("close failed for port 0x%016Lx\n", 23891da177e4SLinus Torvalds port->wwpn); 23901da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 23911da177e4SLinus Torvalds goto out; 23921da177e4SLinus Torvalds } /* else it's closed now, open it */ 23931da177e4SLinus Torvalds break; 23941da177e4SLinus Torvalds } 23951da177e4SLinus Torvalds if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) 23961da177e4SLinus Torvalds retval = ZFCP_ERP_EXIT; 23971da177e4SLinus Torvalds else 23981da177e4SLinus Torvalds retval = zfcp_erp_port_strategy_open(erp_action); 23991da177e4SLinus Torvalds 24001da177e4SLinus Torvalds out: 24011da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "p_pst/ret"); 24021da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t)); 24031da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int)); 24041da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &retval, sizeof (int)); 24051da177e4SLinus Torvalds 24061da177e4SLinus Torvalds return retval; 24071da177e4SLinus Torvalds } 24081da177e4SLinus Torvalds 24091da177e4SLinus Torvalds static int 24101da177e4SLinus Torvalds zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action) 24111da177e4SLinus Torvalds { 24121da177e4SLinus Torvalds int retval; 24131da177e4SLinus Torvalds 24141da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, 24151da177e4SLinus Torvalds &erp_action->port->status)) 24161da177e4SLinus Torvalds retval = zfcp_erp_port_strategy_open_nameserver(erp_action); 24171da177e4SLinus Torvalds else 24181da177e4SLinus Torvalds retval = zfcp_erp_port_strategy_open_common(erp_action); 24191da177e4SLinus Torvalds 24201da177e4SLinus Torvalds return retval; 24211da177e4SLinus Torvalds } 24221da177e4SLinus Torvalds 24231da177e4SLinus Torvalds static int 24241da177e4SLinus Torvalds zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) 24251da177e4SLinus Torvalds { 24261da177e4SLinus Torvalds int retval = 0; 24271da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 24281da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 24291da177e4SLinus Torvalds 24301da177e4SLinus Torvalds switch (erp_action->step) { 24311da177e4SLinus Torvalds 24321da177e4SLinus Torvalds case ZFCP_ERP_STEP_UNINITIALIZED: 24331da177e4SLinus Torvalds case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: 24341da177e4SLinus Torvalds case ZFCP_ERP_STEP_PORT_CLOSING: 2435ad757cdfSAndreas Herrmann if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) { 24366f71d9bcS if (port->wwpn != adapter->peer_wwpn) { 24376f71d9bcS ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx " 24386f71d9bcS "on adapter %s.\nPeer WWPN " 24396f71d9bcS "0x%016Lx does not match\n", 24406f71d9bcS port->wwpn, 24416f71d9bcS zfcp_get_busid_by_adapter(adapter), 24426f71d9bcS adapter->peer_wwpn); 2443698ec016SMartin Peschke zfcp_erp_port_failed(port, 25, 0); 24446f71d9bcS retval = ZFCP_ERP_FAILED; 24456f71d9bcS break; 24466f71d9bcS } 24476f71d9bcS port->d_id = adapter->peer_d_id; 24486f71d9bcS atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); 24496f71d9bcS retval = zfcp_erp_port_strategy_open_port(erp_action); 24506f71d9bcS break; 24516f71d9bcS } 24521da177e4SLinus Torvalds if (!(adapter->nameserver_port)) { 24531da177e4SLinus Torvalds retval = zfcp_nameserver_enqueue(adapter); 24541da177e4SLinus Torvalds if (retval != 0) { 24551da177e4SLinus Torvalds ZFCP_LOG_NORMAL("error: nameserver port " 24561da177e4SLinus Torvalds "unavailable for adapter %s\n", 24571da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 24581da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 24591da177e4SLinus Torvalds break; 24601da177e4SLinus Torvalds } 24611da177e4SLinus Torvalds } 24621da177e4SLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, 24631da177e4SLinus Torvalds &adapter->nameserver_port->status)) { 24641da177e4SLinus Torvalds ZFCP_LOG_DEBUG("nameserver port is not open -> open " 24651da177e4SLinus Torvalds "nameserver port\n"); 24661da177e4SLinus Torvalds /* nameserver port may live again */ 24671da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, 24681da177e4SLinus Torvalds &adapter->nameserver_port->status); 24691da177e4SLinus Torvalds if (zfcp_erp_port_reopen(adapter->nameserver_port, 0) 24701da177e4SLinus Torvalds >= 0) { 24711da177e4SLinus Torvalds erp_action->step = 24721da177e4SLinus Torvalds ZFCP_ERP_STEP_NAMESERVER_OPEN; 24731da177e4SLinus Torvalds retval = ZFCP_ERP_CONTINUES; 24741da177e4SLinus Torvalds } else 24751da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 24761da177e4SLinus Torvalds break; 24771da177e4SLinus Torvalds } 24781da177e4SLinus Torvalds /* else nameserver port is already open, fall through */ 24791da177e4SLinus Torvalds case ZFCP_ERP_STEP_NAMESERVER_OPEN: 24801da177e4SLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, 24811da177e4SLinus Torvalds &adapter->nameserver_port->status)) { 24821da177e4SLinus Torvalds ZFCP_LOG_DEBUG("open failed for nameserver port\n"); 24831da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 24841da177e4SLinus Torvalds } else { 24851da177e4SLinus Torvalds ZFCP_LOG_DEBUG("nameserver port is open -> " 24861da177e4SLinus Torvalds "nameserver look-up for port 0x%016Lx\n", 24871da177e4SLinus Torvalds port->wwpn); 24881da177e4SLinus Torvalds retval = zfcp_erp_port_strategy_open_common_lookup 24891da177e4SLinus Torvalds (erp_action); 24901da177e4SLinus Torvalds } 24911da177e4SLinus Torvalds break; 24921da177e4SLinus Torvalds 24931da177e4SLinus Torvalds case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: 24941da177e4SLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_PORT_DID_DID, &port->status)) { 24951da177e4SLinus Torvalds if (atomic_test_mask 24961da177e4SLinus Torvalds (ZFCP_STATUS_PORT_INVALID_WWPN, &port->status)) { 24971da177e4SLinus Torvalds ZFCP_LOG_DEBUG("nameserver look-up failed " 24981da177e4SLinus Torvalds "for port 0x%016Lx " 24991da177e4SLinus Torvalds "(misconfigured WWPN?)\n", 25001da177e4SLinus Torvalds port->wwpn); 2501698ec016SMartin Peschke zfcp_erp_port_failed(port, 26, 0); 25021da177e4SLinus Torvalds retval = ZFCP_ERP_EXIT; 25031da177e4SLinus Torvalds } else { 25041da177e4SLinus Torvalds ZFCP_LOG_DEBUG("nameserver look-up failed for " 25051da177e4SLinus Torvalds "port 0x%016Lx\n", port->wwpn); 25061da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 25071da177e4SLinus Torvalds } 25081da177e4SLinus Torvalds } else { 25091d589edfSChristof Schmitt ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> " 25101da177e4SLinus Torvalds "trying open\n", port->wwpn, port->d_id); 25111da177e4SLinus Torvalds retval = zfcp_erp_port_strategy_open_port(erp_action); 25121da177e4SLinus Torvalds } 25131da177e4SLinus Torvalds break; 25141da177e4SLinus Torvalds 25151da177e4SLinus Torvalds case ZFCP_ERP_STEP_PORT_OPENING: 25161da177e4SLinus Torvalds /* D_ID might have changed during open */ 25171da177e4SLinus Torvalds if (atomic_test_mask((ZFCP_STATUS_COMMON_OPEN | 25181da177e4SLinus Torvalds ZFCP_STATUS_PORT_DID_DID), 25191da177e4SLinus Torvalds &port->status)) { 25201da177e4SLinus Torvalds ZFCP_LOG_DEBUG("port 0x%016Lx is open\n", port->wwpn); 25211da177e4SLinus Torvalds retval = ZFCP_ERP_SUCCEEDED; 25221da177e4SLinus Torvalds } else { 25231da177e4SLinus Torvalds ZFCP_LOG_DEBUG("open failed for port 0x%016Lx\n", 25241da177e4SLinus Torvalds port->wwpn); 25251da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 25261da177e4SLinus Torvalds } 25271da177e4SLinus Torvalds break; 25281da177e4SLinus Torvalds 25291da177e4SLinus Torvalds default: 25301da177e4SLinus Torvalds ZFCP_LOG_NORMAL("bug: unknown erp step 0x%08x\n", 25311da177e4SLinus Torvalds erp_action->step); 25321da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 25331da177e4SLinus Torvalds } 25341da177e4SLinus Torvalds 25351da177e4SLinus Torvalds return retval; 25361da177e4SLinus Torvalds } 25371da177e4SLinus Torvalds 25381da177e4SLinus Torvalds static int 25391da177e4SLinus Torvalds zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action) 25401da177e4SLinus Torvalds { 25411da177e4SLinus Torvalds int retval; 25421da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 25431da177e4SLinus Torvalds 25441da177e4SLinus Torvalds switch (erp_action->step) { 25451da177e4SLinus Torvalds 25461da177e4SLinus Torvalds case ZFCP_ERP_STEP_UNINITIALIZED: 25471da177e4SLinus Torvalds case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: 25481da177e4SLinus Torvalds case ZFCP_ERP_STEP_PORT_CLOSING: 25491d589edfSChristof Schmitt ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> trying open\n", 25501da177e4SLinus Torvalds port->wwpn, port->d_id); 25511da177e4SLinus Torvalds retval = zfcp_erp_port_strategy_open_port(erp_action); 25521da177e4SLinus Torvalds break; 25531da177e4SLinus Torvalds 25541da177e4SLinus Torvalds case ZFCP_ERP_STEP_PORT_OPENING: 25551da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) { 25561da177e4SLinus Torvalds ZFCP_LOG_DEBUG("WKA port is open\n"); 25571da177e4SLinus Torvalds retval = ZFCP_ERP_SUCCEEDED; 25581da177e4SLinus Torvalds } else { 25591da177e4SLinus Torvalds ZFCP_LOG_DEBUG("open failed for WKA port\n"); 25601da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 25611da177e4SLinus Torvalds } 25621da177e4SLinus Torvalds /* this is needed anyway (dont care for retval of wakeup) */ 25631da177e4SLinus Torvalds ZFCP_LOG_DEBUG("continue other open port operations\n"); 25641da177e4SLinus Torvalds zfcp_erp_port_strategy_open_nameserver_wakeup(erp_action); 25651da177e4SLinus Torvalds break; 25661da177e4SLinus Torvalds 25671da177e4SLinus Torvalds default: 25681da177e4SLinus Torvalds ZFCP_LOG_NORMAL("bug: unknown erp step 0x%08x\n", 25691da177e4SLinus Torvalds erp_action->step); 25701da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 25711da177e4SLinus Torvalds } 25721da177e4SLinus Torvalds 25731da177e4SLinus Torvalds return retval; 25741da177e4SLinus Torvalds } 25751da177e4SLinus Torvalds 25761da177e4SLinus Torvalds /* 25771da177e4SLinus Torvalds * function: 25781da177e4SLinus Torvalds * 25791da177e4SLinus Torvalds * purpose: makes the erp thread continue with reopen (physical) port 25801da177e4SLinus Torvalds * actions which have been paused until the name server port 25811da177e4SLinus Torvalds * is opened (or failed) 25821da177e4SLinus Torvalds * 25831da177e4SLinus Torvalds * returns: 0 (a kind of void retval, its not used) 25841da177e4SLinus Torvalds */ 25851da177e4SLinus Torvalds static int 25861da177e4SLinus Torvalds zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action 25871da177e4SLinus Torvalds *ns_erp_action) 25881da177e4SLinus Torvalds { 25891da177e4SLinus Torvalds int retval = 0; 25901da177e4SLinus Torvalds unsigned long flags; 25911da177e4SLinus Torvalds struct zfcp_adapter *adapter = ns_erp_action->adapter; 25921da177e4SLinus Torvalds struct zfcp_erp_action *erp_action, *tmp; 25931da177e4SLinus Torvalds 25941da177e4SLinus Torvalds read_lock_irqsave(&adapter->erp_lock, flags); 25951da177e4SLinus Torvalds list_for_each_entry_safe(erp_action, tmp, &adapter->erp_running_head, 25961da177e4SLinus Torvalds list) { 25971da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "p_pstnsw_n"); 25981da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &erp_action->port->wwpn, 25991da177e4SLinus Torvalds sizeof (wwn_t)); 26001da177e4SLinus Torvalds if (erp_action->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) { 26011da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "p_pstnsw_w"); 26021da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, 26031da177e4SLinus Torvalds &erp_action->port->wwpn, sizeof (wwn_t)); 26041da177e4SLinus Torvalds if (atomic_test_mask( 26051da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ERP_FAILED, 26061da177e4SLinus Torvalds &adapter->nameserver_port->status)) 2607698ec016SMartin Peschke zfcp_erp_port_failed(erp_action->port, 27, 0); 26081da177e4SLinus Torvalds zfcp_erp_action_ready(erp_action); 26091da177e4SLinus Torvalds } 26101da177e4SLinus Torvalds } 26111da177e4SLinus Torvalds read_unlock_irqrestore(&adapter->erp_lock, flags); 26121da177e4SLinus Torvalds 26131da177e4SLinus Torvalds return retval; 26141da177e4SLinus Torvalds } 26151da177e4SLinus Torvalds 26161da177e4SLinus Torvalds /* 26171da177e4SLinus Torvalds * function: 26181da177e4SLinus Torvalds * 26191da177e4SLinus Torvalds * purpose: 26201da177e4SLinus Torvalds * 26211da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 26221da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 26231da177e4SLinus Torvalds */ 26241da177e4SLinus Torvalds static int 26251da177e4SLinus Torvalds zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action) 26261da177e4SLinus Torvalds { 26271da177e4SLinus Torvalds int retval; 26281da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 26291da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 26301da177e4SLinus Torvalds 26311da177e4SLinus Torvalds retval = zfcp_fsf_close_physical_port(erp_action); 26321da177e4SLinus Torvalds if (retval == -ENOMEM) { 26331da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "o_pfstc_nomem"); 26341da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 26351da177e4SLinus Torvalds retval = ZFCP_ERP_NOMEM; 26361da177e4SLinus Torvalds goto out; 26371da177e4SLinus Torvalds } 26381da177e4SLinus Torvalds erp_action->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING; 26391da177e4SLinus Torvalds if (retval != 0) { 26401da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "o_pfstc_cpf"); 26411da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 26421da177e4SLinus Torvalds /* could not send 'open', fail */ 26431da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 26441da177e4SLinus Torvalds goto out; 26451da177e4SLinus Torvalds } 26461da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "o_pfstc_cpok"); 26471da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t)); 26481da177e4SLinus Torvalds retval = ZFCP_ERP_CONTINUES; 26491da177e4SLinus Torvalds out: 26501da177e4SLinus Torvalds return retval; 26511da177e4SLinus Torvalds } 26521da177e4SLinus Torvalds 26531da177e4SLinus Torvalds static int 26541da177e4SLinus Torvalds zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) 26551da177e4SLinus Torvalds { 26561da177e4SLinus Torvalds int retval = 0; 26571da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 26581da177e4SLinus Torvalds 26591da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_pstclst"); 26601da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 26611da177e4SLinus Torvalds 26621da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | 26631da177e4SLinus Torvalds ZFCP_STATUS_COMMON_CLOSING | 26641da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ACCESS_DENIED | 26651da177e4SLinus Torvalds ZFCP_STATUS_PORT_DID_DID | 26661da177e4SLinus Torvalds ZFCP_STATUS_PORT_PHYS_CLOSING | 26671da177e4SLinus Torvalds ZFCP_STATUS_PORT_INVALID_WWPN, 26681da177e4SLinus Torvalds &port->status); 26691da177e4SLinus Torvalds return retval; 26701da177e4SLinus Torvalds } 26711da177e4SLinus Torvalds 26721da177e4SLinus Torvalds /* 26731da177e4SLinus Torvalds * function: 26741da177e4SLinus Torvalds * 26751da177e4SLinus Torvalds * purpose: 26761da177e4SLinus Torvalds * 26771da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 26781da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 26791da177e4SLinus Torvalds */ 26801da177e4SLinus Torvalds static int 26811da177e4SLinus Torvalds zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action) 26821da177e4SLinus Torvalds { 26831da177e4SLinus Torvalds int retval; 26841da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 26851da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 26861da177e4SLinus Torvalds 26871da177e4SLinus Torvalds retval = zfcp_fsf_close_port(erp_action); 26881da177e4SLinus Torvalds if (retval == -ENOMEM) { 26891da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_pstc_nomem"); 26901da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 26911da177e4SLinus Torvalds retval = ZFCP_ERP_NOMEM; 26921da177e4SLinus Torvalds goto out; 26931da177e4SLinus Torvalds } 26941da177e4SLinus Torvalds erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING; 26951da177e4SLinus Torvalds if (retval != 0) { 26961da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_pstc_cpf"); 26971da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 26981da177e4SLinus Torvalds /* could not send 'close', fail */ 26991da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 27001da177e4SLinus Torvalds goto out; 27011da177e4SLinus Torvalds } 27021da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "p_pstc_cpok"); 27031da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t)); 27041da177e4SLinus Torvalds retval = ZFCP_ERP_CONTINUES; 27051da177e4SLinus Torvalds out: 27061da177e4SLinus Torvalds return retval; 27071da177e4SLinus Torvalds } 27081da177e4SLinus Torvalds 27091da177e4SLinus Torvalds /* 27101da177e4SLinus Torvalds * function: 27111da177e4SLinus Torvalds * 27121da177e4SLinus Torvalds * purpose: 27131da177e4SLinus Torvalds * 27141da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 27151da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 27161da177e4SLinus Torvalds */ 27171da177e4SLinus Torvalds static int 27181da177e4SLinus Torvalds zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) 27191da177e4SLinus Torvalds { 27201da177e4SLinus Torvalds int retval; 27211da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 27221da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 27231da177e4SLinus Torvalds 27241da177e4SLinus Torvalds retval = zfcp_fsf_open_port(erp_action); 27251da177e4SLinus Torvalds if (retval == -ENOMEM) { 27261da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_psto_nomem"); 27271da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 27281da177e4SLinus Torvalds retval = ZFCP_ERP_NOMEM; 27291da177e4SLinus Torvalds goto out; 27301da177e4SLinus Torvalds } 27311da177e4SLinus Torvalds erp_action->step = ZFCP_ERP_STEP_PORT_OPENING; 27321da177e4SLinus Torvalds if (retval != 0) { 27331da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_psto_opf"); 27341da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 27351da177e4SLinus Torvalds /* could not send 'open', fail */ 27361da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 27371da177e4SLinus Torvalds goto out; 27381da177e4SLinus Torvalds } 27391da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "p_psto_opok"); 27401da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t)); 27411da177e4SLinus Torvalds retval = ZFCP_ERP_CONTINUES; 27421da177e4SLinus Torvalds out: 27431da177e4SLinus Torvalds return retval; 27441da177e4SLinus Torvalds } 27451da177e4SLinus Torvalds 27461da177e4SLinus Torvalds /* 27471da177e4SLinus Torvalds * function: 27481da177e4SLinus Torvalds * 27491da177e4SLinus Torvalds * purpose: 27501da177e4SLinus Torvalds * 27511da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 27521da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 27531da177e4SLinus Torvalds */ 27541da177e4SLinus Torvalds static int 27551da177e4SLinus Torvalds zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action) 27561da177e4SLinus Torvalds { 27571da177e4SLinus Torvalds int retval; 27581da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 27591da177e4SLinus Torvalds struct zfcp_port *port = erp_action->port; 27601da177e4SLinus Torvalds 27611da177e4SLinus Torvalds retval = zfcp_ns_gid_pn_request(erp_action); 27621da177e4SLinus Torvalds if (retval == -ENOMEM) { 27631da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem"); 27641da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 27651da177e4SLinus Torvalds retval = ZFCP_ERP_NOMEM; 27661da177e4SLinus Torvalds goto out; 27671da177e4SLinus Torvalds } 27681da177e4SLinus Torvalds erp_action->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; 27691da177e4SLinus Torvalds if (retval != 0) { 27701da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_pstn_ref"); 27711da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 27721da177e4SLinus Torvalds /* could not send nameserver request, fail */ 27731da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 27741da177e4SLinus Torvalds goto out; 27751da177e4SLinus Torvalds } 27761da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "p_pstn_reok"); 27771da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t)); 27781da177e4SLinus Torvalds retval = ZFCP_ERP_CONTINUES; 27791da177e4SLinus Torvalds out: 27801da177e4SLinus Torvalds return retval; 27811da177e4SLinus Torvalds } 27821da177e4SLinus Torvalds 27831da177e4SLinus Torvalds /* 27841da177e4SLinus Torvalds * function: 27851da177e4SLinus Torvalds * 27861da177e4SLinus Torvalds * purpose: this routine executes the 'Reopen Unit' action 27871da177e4SLinus Torvalds * currently no retries 27881da177e4SLinus Torvalds * 27891da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 27901da177e4SLinus Torvalds * ZFCP_ERP_SUCCEEDED - action finished successfully 27911da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 27921da177e4SLinus Torvalds */ 27931da177e4SLinus Torvalds static int 27941da177e4SLinus Torvalds zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) 27951da177e4SLinus Torvalds { 27961da177e4SLinus Torvalds int retval = ZFCP_ERP_FAILED; 27971da177e4SLinus Torvalds struct zfcp_unit *unit = erp_action->unit; 27981da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 27991da177e4SLinus Torvalds 28001da177e4SLinus Torvalds switch (erp_action->step) { 28011da177e4SLinus Torvalds 28021da177e4SLinus Torvalds /* 28031da177e4SLinus Torvalds * FIXME: 28041da177e4SLinus Torvalds * the ULP spec. begs for waiting for oustanding commands 28051da177e4SLinus Torvalds */ 28061da177e4SLinus Torvalds case ZFCP_ERP_STEP_UNINITIALIZED: 28071da177e4SLinus Torvalds zfcp_erp_unit_strategy_clearstati(unit); 28081da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) { 28091da177e4SLinus Torvalds ZFCP_LOG_DEBUG("unit 0x%016Lx is open -> " 28101da177e4SLinus Torvalds "trying close\n", unit->fcp_lun); 28111da177e4SLinus Torvalds retval = zfcp_erp_unit_strategy_close(erp_action); 28121da177e4SLinus Torvalds break; 28131da177e4SLinus Torvalds } 28141da177e4SLinus Torvalds /* else it's already closed, fall through */ 28151da177e4SLinus Torvalds case ZFCP_ERP_STEP_UNIT_CLOSING: 28161da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) { 28171da177e4SLinus Torvalds ZFCP_LOG_DEBUG("close failed for unit 0x%016Lx\n", 28181da177e4SLinus Torvalds unit->fcp_lun); 28191da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 28201da177e4SLinus Torvalds } else { 28211da177e4SLinus Torvalds if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) 28221da177e4SLinus Torvalds retval = ZFCP_ERP_EXIT; 28231da177e4SLinus Torvalds else { 28241da177e4SLinus Torvalds ZFCP_LOG_DEBUG("unit 0x%016Lx is not open -> " 28251da177e4SLinus Torvalds "trying open\n", unit->fcp_lun); 28261da177e4SLinus Torvalds retval = 28271da177e4SLinus Torvalds zfcp_erp_unit_strategy_open(erp_action); 28281da177e4SLinus Torvalds } 28291da177e4SLinus Torvalds } 28301da177e4SLinus Torvalds break; 28311da177e4SLinus Torvalds 28321da177e4SLinus Torvalds case ZFCP_ERP_STEP_UNIT_OPENING: 28331da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) { 28341da177e4SLinus Torvalds ZFCP_LOG_DEBUG("unit 0x%016Lx is open\n", 28351da177e4SLinus Torvalds unit->fcp_lun); 28361da177e4SLinus Torvalds retval = ZFCP_ERP_SUCCEEDED; 28371da177e4SLinus Torvalds } else { 28381da177e4SLinus Torvalds ZFCP_LOG_DEBUG("open failed for unit 0x%016Lx\n", 28391da177e4SLinus Torvalds unit->fcp_lun); 28401da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 28411da177e4SLinus Torvalds } 28421da177e4SLinus Torvalds break; 28431da177e4SLinus Torvalds } 28441da177e4SLinus Torvalds 28451da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "u_ust/ret"); 28461da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof (fcp_lun_t)); 28471da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int)); 28481da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &retval, sizeof (int)); 28491da177e4SLinus Torvalds return retval; 28501da177e4SLinus Torvalds } 28511da177e4SLinus Torvalds 28521da177e4SLinus Torvalds static int 28531da177e4SLinus Torvalds zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) 28541da177e4SLinus Torvalds { 28551da177e4SLinus Torvalds int retval = 0; 28561da177e4SLinus Torvalds struct zfcp_adapter *adapter = unit->port->adapter; 28571da177e4SLinus Torvalds 28581da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "u_ustclst"); 28591da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); 28601da177e4SLinus Torvalds 28611da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | 28621da177e4SLinus Torvalds ZFCP_STATUS_COMMON_CLOSING | 28631da177e4SLinus Torvalds ZFCP_STATUS_COMMON_ACCESS_DENIED | 28641da177e4SLinus Torvalds ZFCP_STATUS_UNIT_SHARED | 28651da177e4SLinus Torvalds ZFCP_STATUS_UNIT_READONLY, 28661da177e4SLinus Torvalds &unit->status); 28671da177e4SLinus Torvalds 28681da177e4SLinus Torvalds return retval; 28691da177e4SLinus Torvalds } 28701da177e4SLinus Torvalds 28711da177e4SLinus Torvalds /* 28721da177e4SLinus Torvalds * function: 28731da177e4SLinus Torvalds * 28741da177e4SLinus Torvalds * purpose: 28751da177e4SLinus Torvalds * 28761da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 28771da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 28781da177e4SLinus Torvalds */ 28791da177e4SLinus Torvalds static int 28801da177e4SLinus Torvalds zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) 28811da177e4SLinus Torvalds { 28821da177e4SLinus Torvalds int retval; 28831da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 28841da177e4SLinus Torvalds struct zfcp_unit *unit = erp_action->unit; 28851da177e4SLinus Torvalds 28861da177e4SLinus Torvalds retval = zfcp_fsf_close_unit(erp_action); 28871da177e4SLinus Torvalds if (retval == -ENOMEM) { 28881da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "u_ustc_nomem"); 28891da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, 28901da177e4SLinus Torvalds sizeof (fcp_lun_t)); 28911da177e4SLinus Torvalds retval = ZFCP_ERP_NOMEM; 28921da177e4SLinus Torvalds goto out; 28931da177e4SLinus Torvalds } 28941da177e4SLinus Torvalds erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING; 28951da177e4SLinus Torvalds if (retval != 0) { 28961da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "u_ustc_cuf"); 28971da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, 28981da177e4SLinus Torvalds sizeof (fcp_lun_t)); 28991da177e4SLinus Torvalds /* could not send 'close', fail */ 29001da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 29011da177e4SLinus Torvalds goto out; 29021da177e4SLinus Torvalds } 29031da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "u_ustc_cuok"); 29041da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t)); 29051da177e4SLinus Torvalds retval = ZFCP_ERP_CONTINUES; 29061da177e4SLinus Torvalds 29071da177e4SLinus Torvalds out: 29081da177e4SLinus Torvalds return retval; 29091da177e4SLinus Torvalds } 29101da177e4SLinus Torvalds 29111da177e4SLinus Torvalds /* 29121da177e4SLinus Torvalds * function: 29131da177e4SLinus Torvalds * 29141da177e4SLinus Torvalds * purpose: 29151da177e4SLinus Torvalds * 29161da177e4SLinus Torvalds * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) 29171da177e4SLinus Torvalds * ZFCP_ERP_FAILED - action finished unsuccessfully 29181da177e4SLinus Torvalds */ 29191da177e4SLinus Torvalds static int 29201da177e4SLinus Torvalds zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) 29211da177e4SLinus Torvalds { 29221da177e4SLinus Torvalds int retval; 29231da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 29241da177e4SLinus Torvalds struct zfcp_unit *unit = erp_action->unit; 29251da177e4SLinus Torvalds 29261da177e4SLinus Torvalds retval = zfcp_fsf_open_unit(erp_action); 29271da177e4SLinus Torvalds if (retval == -ENOMEM) { 29281da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "u_usto_nomem"); 29291da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, 29301da177e4SLinus Torvalds sizeof (fcp_lun_t)); 29311da177e4SLinus Torvalds retval = ZFCP_ERP_NOMEM; 29321da177e4SLinus Torvalds goto out; 29331da177e4SLinus Torvalds } 29341da177e4SLinus Torvalds erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING; 29351da177e4SLinus Torvalds if (retval != 0) { 29361da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "u_usto_ouf"); 29371da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, 29381da177e4SLinus Torvalds sizeof (fcp_lun_t)); 29391da177e4SLinus Torvalds /* could not send 'open', fail */ 29401da177e4SLinus Torvalds retval = ZFCP_ERP_FAILED; 29411da177e4SLinus Torvalds goto out; 29421da177e4SLinus Torvalds } 29431da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "u_usto_ouok"); 29441da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t)); 29451da177e4SLinus Torvalds retval = ZFCP_ERP_CONTINUES; 29461da177e4SLinus Torvalds out: 29471da177e4SLinus Torvalds return retval; 29481da177e4SLinus Torvalds } 29491da177e4SLinus Torvalds 29502abbe866SAndreas Herrmann void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req) 29511da177e4SLinus Torvalds { 29522abbe866SAndreas Herrmann BUG_ON(!fsf_req->erp_action); 29532abbe866SAndreas Herrmann fsf_req->timer.function = zfcp_erp_timeout_handler; 29542abbe866SAndreas Herrmann fsf_req->timer.data = (unsigned long) fsf_req->erp_action; 29552abbe866SAndreas Herrmann fsf_req->timer.expires = jiffies + ZFCP_ERP_FSFREQ_TIMEOUT; 29562abbe866SAndreas Herrmann add_timer(&fsf_req->timer); 29571da177e4SLinus Torvalds } 29581da177e4SLinus Torvalds 29591da177e4SLinus Torvalds /* 29601da177e4SLinus Torvalds * function: 29611da177e4SLinus Torvalds * 29621da177e4SLinus Torvalds * purpose: enqueue the specified error recovery action, if needed 29631da177e4SLinus Torvalds * 29641da177e4SLinus Torvalds * returns: 29651da177e4SLinus Torvalds */ 29661da177e4SLinus Torvalds static int 29671da177e4SLinus Torvalds zfcp_erp_action_enqueue(int action, 29681da177e4SLinus Torvalds struct zfcp_adapter *adapter, 29691da177e4SLinus Torvalds struct zfcp_port *port, struct zfcp_unit *unit) 29701da177e4SLinus Torvalds { 29711da177e4SLinus Torvalds int retval = 1; 29721da177e4SLinus Torvalds struct zfcp_erp_action *erp_action = NULL; 29731da177e4SLinus Torvalds int stronger_action = 0; 29741da177e4SLinus Torvalds u32 status = 0; 29751da177e4SLinus Torvalds 29761da177e4SLinus Torvalds /* 29771da177e4SLinus Torvalds * We need some rules here which check whether we really need 29781da177e4SLinus Torvalds * this action or whether we should just drop it. 29791da177e4SLinus Torvalds * E.g. if there is a unfinished 'Reopen Port' request then we drop a 29801da177e4SLinus Torvalds * 'Reopen Unit' request for an associated unit since we can't 29811da177e4SLinus Torvalds * satisfy this request now. A 'Reopen Port' action will trigger 29821da177e4SLinus Torvalds * 'Reopen Unit' actions when it completes. 29831da177e4SLinus Torvalds * Thus, there are only actions in the queue which can immediately be 29841da177e4SLinus Torvalds * executed. This makes the processing of the action queue more 29851da177e4SLinus Torvalds * efficient. 29861da177e4SLinus Torvalds */ 29871da177e4SLinus Torvalds 29881da177e4SLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, 29891da177e4SLinus Torvalds &adapter->status)) 29901da177e4SLinus Torvalds return -EIO; 29911da177e4SLinus Torvalds 29921da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &action, sizeof (int)); 29931da177e4SLinus Torvalds /* check whether we really need this */ 29941da177e4SLinus Torvalds switch (action) { 29951da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_UNIT: 29961da177e4SLinus Torvalds if (atomic_test_mask 29971da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) { 29981da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "u_actenq_drp"); 29991da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &port->wwpn, 30001da177e4SLinus Torvalds sizeof (wwn_t)); 30011da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &unit->fcp_lun, 30021da177e4SLinus Torvalds sizeof (fcp_lun_t)); 30031da177e4SLinus Torvalds goto out; 30041da177e4SLinus Torvalds } 30051da177e4SLinus Torvalds if (!atomic_test_mask 30061da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_RUNNING, &port->status) || 30071da177e4SLinus Torvalds atomic_test_mask 30081da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { 30091da177e4SLinus Torvalds goto out; 30101da177e4SLinus Torvalds } 30111da177e4SLinus Torvalds if (!atomic_test_mask 30121da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) { 30131da177e4SLinus Torvalds stronger_action = ZFCP_ERP_ACTION_REOPEN_PORT; 30141da177e4SLinus Torvalds unit = NULL; 30151da177e4SLinus Torvalds } 30161da177e4SLinus Torvalds /* fall through !!! */ 30171da177e4SLinus Torvalds 30181da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT: 30191da177e4SLinus Torvalds if (atomic_test_mask 30201da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) { 30211da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "p_actenq_drp"); 30221da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &port->wwpn, 30231da177e4SLinus Torvalds sizeof (wwn_t)); 30241da177e4SLinus Torvalds goto out; 30251da177e4SLinus Torvalds } 30261da177e4SLinus Torvalds /* fall through !!! */ 30271da177e4SLinus Torvalds 30281da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: 30293734d24bSAndreas Herrmann if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, 30303734d24bSAndreas Herrmann &port->status)) { 30313734d24bSAndreas Herrmann if (port->erp_action.action != 30321da177e4SLinus Torvalds ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) { 30333734d24bSAndreas Herrmann ZFCP_LOG_INFO("dropped erp action %i (port " 30343734d24bSAndreas Herrmann "0x%016Lx, action in use: %i)\n", 30353734d24bSAndreas Herrmann action, port->wwpn, 30363734d24bSAndreas Herrmann port->erp_action.action); 30373734d24bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 4, 30383734d24bSAndreas Herrmann "pf_actenq_drp"); 30393734d24bSAndreas Herrmann } else 30403734d24bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 4, 30413734d24bSAndreas Herrmann "pf_actenq_drpcp"); 30421da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &port->wwpn, 30431da177e4SLinus Torvalds sizeof (wwn_t)); 30441da177e4SLinus Torvalds goto out; 30451da177e4SLinus Torvalds } 30461da177e4SLinus Torvalds if (!atomic_test_mask 30471da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_RUNNING, &adapter->status) || 30481da177e4SLinus Torvalds atomic_test_mask 30491da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { 30501da177e4SLinus Torvalds goto out; 30511da177e4SLinus Torvalds } 30521da177e4SLinus Torvalds if (!atomic_test_mask 30531da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) { 30541da177e4SLinus Torvalds stronger_action = ZFCP_ERP_ACTION_REOPEN_ADAPTER; 30551da177e4SLinus Torvalds port = NULL; 30561da177e4SLinus Torvalds } 30571da177e4SLinus Torvalds /* fall through !!! */ 30581da177e4SLinus Torvalds 30591da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 30601da177e4SLinus Torvalds if (atomic_test_mask 30611da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) { 30621da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "a_actenq_drp"); 30631da177e4SLinus Torvalds goto out; 30641da177e4SLinus Torvalds } 30651da177e4SLinus Torvalds break; 30661da177e4SLinus Torvalds 30671da177e4SLinus Torvalds default: 30681da177e4SLinus Torvalds debug_text_exception(adapter->erp_dbf, 1, "a_actenq_bug"); 30691da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 1, &action, sizeof (int)); 30701da177e4SLinus Torvalds ZFCP_LOG_NORMAL("bug: unknown erp action requested " 30711da177e4SLinus Torvalds "on adapter %s (action=%d)\n", 30721da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter), action); 30731da177e4SLinus Torvalds goto out; 30741da177e4SLinus Torvalds } 30751da177e4SLinus Torvalds 30761da177e4SLinus Torvalds /* check whether we need something stronger first */ 30771da177e4SLinus Torvalds if (stronger_action) { 30781da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "a_actenq_str"); 30791da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &stronger_action, 30801da177e4SLinus Torvalds sizeof (int)); 30811da177e4SLinus Torvalds ZFCP_LOG_DEBUG("stronger erp action %d needed before " 30821da177e4SLinus Torvalds "erp action %d on adapter %s\n", 30831da177e4SLinus Torvalds stronger_action, action, 30841da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 30851da177e4SLinus Torvalds action = stronger_action; 30861da177e4SLinus Torvalds } 30871da177e4SLinus Torvalds 30881da177e4SLinus Torvalds /* mark adapter to have some error recovery pending */ 30891da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); 30901da177e4SLinus Torvalds 30911da177e4SLinus Torvalds /* setup error recovery action */ 30921da177e4SLinus Torvalds switch (action) { 30931da177e4SLinus Torvalds 30941da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_UNIT: 30951da177e4SLinus Torvalds zfcp_unit_get(unit); 30961da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); 30971da177e4SLinus Torvalds erp_action = &unit->erp_action; 30981da177e4SLinus Torvalds if (!atomic_test_mask 30991da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_RUNNING, &unit->status)) 31001da177e4SLinus Torvalds status = ZFCP_STATUS_ERP_CLOSE_ONLY; 31011da177e4SLinus Torvalds break; 31021da177e4SLinus Torvalds 31031da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT: 31041da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: 31051da177e4SLinus Torvalds zfcp_port_get(port); 31061da177e4SLinus Torvalds zfcp_erp_action_dismiss_port(port); 31071da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); 31081da177e4SLinus Torvalds erp_action = &port->erp_action; 31091da177e4SLinus Torvalds if (!atomic_test_mask 31101da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_RUNNING, &port->status)) 31111da177e4SLinus Torvalds status = ZFCP_STATUS_ERP_CLOSE_ONLY; 31121da177e4SLinus Torvalds break; 31131da177e4SLinus Torvalds 31141da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 31151da177e4SLinus Torvalds zfcp_adapter_get(adapter); 31161da177e4SLinus Torvalds zfcp_erp_action_dismiss_adapter(adapter); 31171da177e4SLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); 31181da177e4SLinus Torvalds erp_action = &adapter->erp_action; 31191da177e4SLinus Torvalds if (!atomic_test_mask 31201da177e4SLinus Torvalds (ZFCP_STATUS_COMMON_RUNNING, &adapter->status)) 31211da177e4SLinus Torvalds status = ZFCP_STATUS_ERP_CLOSE_ONLY; 31221da177e4SLinus Torvalds break; 31231da177e4SLinus Torvalds } 31241da177e4SLinus Torvalds 31251da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "a_actenq"); 31261da177e4SLinus Torvalds 31271da177e4SLinus Torvalds memset(erp_action, 0, sizeof (struct zfcp_erp_action)); 31281da177e4SLinus Torvalds erp_action->adapter = adapter; 31291da177e4SLinus Torvalds erp_action->port = port; 31301da177e4SLinus Torvalds erp_action->unit = unit; 31311da177e4SLinus Torvalds erp_action->action = action; 31321da177e4SLinus Torvalds erp_action->status = status; 31331da177e4SLinus Torvalds 31341da177e4SLinus Torvalds ++adapter->erp_total_count; 31351da177e4SLinus Torvalds 31361da177e4SLinus Torvalds /* finally put it into 'ready' queue and kick erp thread */ 313786e8dfc5SMartin Peschke list_add_tail(&erp_action->list, &adapter->erp_ready_head); 31381da177e4SLinus Torvalds up(&adapter->erp_ready_sem); 3139348447e8SMartin Peschke zfcp_rec_dbf_event_thread(1, adapter, 0); 31401da177e4SLinus Torvalds retval = 0; 31411da177e4SLinus Torvalds out: 31421da177e4SLinus Torvalds return retval; 31431da177e4SLinus Torvalds } 31441da177e4SLinus Torvalds 31451da177e4SLinus Torvalds static int 31461da177e4SLinus Torvalds zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) 31471da177e4SLinus Torvalds { 31481da177e4SLinus Torvalds int retval = 0; 31491da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 31501da177e4SLinus Torvalds 31511da177e4SLinus Torvalds --adapter->erp_total_count; 31521da177e4SLinus Torvalds if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { 31531da177e4SLinus Torvalds --adapter->erp_low_mem_count; 31541da177e4SLinus Torvalds erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; 31551da177e4SLinus Torvalds } 31561da177e4SLinus Torvalds 31571da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 4, "a_actdeq"); 31581da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int)); 31591da177e4SLinus Torvalds list_del(&erp_action->list); 31601da177e4SLinus Torvalds switch (erp_action->action) { 31611da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_UNIT: 31621da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, 31631da177e4SLinus Torvalds &erp_action->unit->status); 31641da177e4SLinus Torvalds break; 31651da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: 31661da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT: 31671da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, 31681da177e4SLinus Torvalds &erp_action->port->status); 31691da177e4SLinus Torvalds break; 31701da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 31711da177e4SLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, 31721da177e4SLinus Torvalds &erp_action->adapter->status); 31731da177e4SLinus Torvalds break; 31741da177e4SLinus Torvalds default: 31751da177e4SLinus Torvalds /* bug */ 31761da177e4SLinus Torvalds break; 31771da177e4SLinus Torvalds } 31781da177e4SLinus Torvalds return retval; 31791da177e4SLinus Torvalds } 31801da177e4SLinus Torvalds 31811da177e4SLinus Torvalds /** 31821da177e4SLinus Torvalds * zfcp_erp_action_cleanup 31831da177e4SLinus Torvalds * 3184575c9687SAdrian Bunk * Register unit with scsi stack if appropriate and fix reference counts. 31851da177e4SLinus Torvalds * Note: Temporary units are not registered with scsi stack. 31861da177e4SLinus Torvalds */ 31871da177e4SLinus Torvalds static void 31881da177e4SLinus Torvalds zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, 31891da177e4SLinus Torvalds struct zfcp_port *port, struct zfcp_unit *unit, 31901da177e4SLinus Torvalds int result) 31911da177e4SLinus Torvalds { 31921da177e4SLinus Torvalds switch (action) { 31931da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_UNIT: 31941da177e4SLinus Torvalds if ((result == ZFCP_ERP_SUCCEEDED) 31951da177e4SLinus Torvalds && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, 31961da177e4SLinus Torvalds &unit->status)) 31973859f6a2SAndreas Herrmann && !unit->device 3198ad58f7dbSAndreas Herrmann && port->rport) { 3199ad58f7dbSAndreas Herrmann atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, 3200ad58f7dbSAndreas Herrmann &unit->status); 32015f852be9SChristof Schmitt if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, 32025f852be9SChristof Schmitt &unit->status) == 0) 32035f852be9SChristof Schmitt zfcp_erp_schedule_work(unit); 3204ad58f7dbSAndreas Herrmann } 32051da177e4SLinus Torvalds zfcp_unit_put(unit); 32061da177e4SLinus Torvalds break; 32071da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: 32081da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_PORT: 3209338151e0SAndreas Herrmann if (atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, 3210338151e0SAndreas Herrmann &port->status)) { 3211338151e0SAndreas Herrmann zfcp_port_put(port); 3212338151e0SAndreas Herrmann break; 3213338151e0SAndreas Herrmann } 3214338151e0SAndreas Herrmann 32153859f6a2SAndreas Herrmann if ((result == ZFCP_ERP_SUCCEEDED) 32163859f6a2SAndreas Herrmann && !port->rport) { 32173859f6a2SAndreas Herrmann struct fc_rport_identifiers ids; 32183859f6a2SAndreas Herrmann ids.node_name = port->wwnn; 32193859f6a2SAndreas Herrmann ids.port_name = port->wwpn; 32203859f6a2SAndreas Herrmann ids.port_id = port->d_id; 32213859f6a2SAndreas Herrmann ids.roles = FC_RPORT_ROLE_FCP_TARGET; 32223859f6a2SAndreas Herrmann port->rport = 32233859f6a2SAndreas Herrmann fc_remote_port_add(adapter->scsi_host, 0, &ids); 32243859f6a2SAndreas Herrmann if (!port->rport) 32253859f6a2SAndreas Herrmann ZFCP_LOG_NORMAL("failed registration of rport" 32263859f6a2SAndreas Herrmann "(adapter %s, wwpn=0x%016Lx)\n", 32273859f6a2SAndreas Herrmann zfcp_get_busid_by_port(port), 32283859f6a2SAndreas Herrmann port->wwpn); 322975bfc283SRalph Wuerthner else { 32305f852be9SChristof Schmitt scsi_target_unblock(&port->rport->dev); 323175bfc283SRalph Wuerthner port->rport->maxframe_size = port->maxframe_size; 323275bfc283SRalph Wuerthner port->rport->supported_classes = 323375bfc283SRalph Wuerthner port->supported_classes; 323475bfc283SRalph Wuerthner } 32353859f6a2SAndreas Herrmann } 3236338151e0SAndreas Herrmann if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { 3237338151e0SAndreas Herrmann fc_remote_port_delete(port->rport); 3238338151e0SAndreas Herrmann port->rport = NULL; 3239338151e0SAndreas Herrmann } 32401da177e4SLinus Torvalds zfcp_port_put(port); 32411da177e4SLinus Torvalds break; 32421da177e4SLinus Torvalds case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 3243338151e0SAndreas Herrmann if (result != ZFCP_ERP_SUCCEEDED) { 3244338151e0SAndreas Herrmann list_for_each_entry(port, &adapter->port_list_head, list) 3245338151e0SAndreas Herrmann if (port->rport && 3246338151e0SAndreas Herrmann !atomic_test_mask(ZFCP_STATUS_PORT_WKA, 3247338151e0SAndreas Herrmann &port->status)) { 3248338151e0SAndreas Herrmann fc_remote_port_delete(port->rport); 3249338151e0SAndreas Herrmann port->rport = NULL; 3250338151e0SAndreas Herrmann } 3251338151e0SAndreas Herrmann } 32521da177e4SLinus Torvalds zfcp_adapter_put(adapter); 32531da177e4SLinus Torvalds break; 32541da177e4SLinus Torvalds default: 32551da177e4SLinus Torvalds break; 32561da177e4SLinus Torvalds } 32571da177e4SLinus Torvalds } 32581da177e4SLinus Torvalds 32591da177e4SLinus Torvalds 326081654286SAndreas Herrmann static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) 32611da177e4SLinus Torvalds { 32621da177e4SLinus Torvalds struct zfcp_port *port; 32631da177e4SLinus Torvalds 32641da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "a_actab"); 32651da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) 32661da177e4SLinus Torvalds zfcp_erp_action_dismiss(&adapter->erp_action); 32671da177e4SLinus Torvalds else 32681da177e4SLinus Torvalds list_for_each_entry(port, &adapter->port_list_head, list) 32691da177e4SLinus Torvalds zfcp_erp_action_dismiss_port(port); 32701da177e4SLinus Torvalds } 32711da177e4SLinus Torvalds 3272f6c0e7a7SAndreas Herrmann static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) 32731da177e4SLinus Torvalds { 32741da177e4SLinus Torvalds struct zfcp_unit *unit; 32751da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 32761da177e4SLinus Torvalds 32771da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "p_actab"); 32781da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); 32791da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) 32801da177e4SLinus Torvalds zfcp_erp_action_dismiss(&port->erp_action); 32811da177e4SLinus Torvalds else 32821da177e4SLinus Torvalds list_for_each_entry(unit, &port->unit_list_head, list) 32831da177e4SLinus Torvalds zfcp_erp_action_dismiss_unit(unit); 32841da177e4SLinus Torvalds } 32851da177e4SLinus Torvalds 3286f6c0e7a7SAndreas Herrmann static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) 32871da177e4SLinus Torvalds { 32881da177e4SLinus Torvalds struct zfcp_adapter *adapter = unit->port->adapter; 32891da177e4SLinus Torvalds 32901da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 5, "u_actab"); 32911da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); 32921da177e4SLinus Torvalds if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) 32931da177e4SLinus Torvalds zfcp_erp_action_dismiss(&unit->erp_action); 32941da177e4SLinus Torvalds } 32951da177e4SLinus Torvalds 3296364c8558SHeiko Carstens static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) 32971da177e4SLinus Torvalds { 32981da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 32991da177e4SLinus Torvalds 33001da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "a_toru"); 33011da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int)); 33021da177e4SLinus Torvalds list_move(&erp_action->list, &erp_action->adapter->erp_running_head); 33031da177e4SLinus Torvalds } 33041da177e4SLinus Torvalds 3305364c8558SHeiko Carstens static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) 33061da177e4SLinus Torvalds { 33071da177e4SLinus Torvalds struct zfcp_adapter *adapter = erp_action->adapter; 33081da177e4SLinus Torvalds 33091da177e4SLinus Torvalds debug_text_event(adapter->erp_dbf, 6, "a_tore"); 33101da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int)); 33111da177e4SLinus Torvalds list_move(&erp_action->list, &erp_action->adapter->erp_ready_head); 33121da177e4SLinus Torvalds } 33131da177e4SLinus Torvalds 3314698ec016SMartin Peschke void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, u64 ref) 3315d736a27bSAndreas Herrmann { 3316d736a27bSAndreas Herrmann struct zfcp_adapter *adapter = port->adapter; 3317d736a27bSAndreas Herrmann unsigned long flags; 3318d736a27bSAndreas Herrmann 3319d736a27bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "p_access_boxed"); 3320d736a27bSAndreas Herrmann debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); 3321d736a27bSAndreas Herrmann read_lock_irqsave(&zfcp_data.config_lock, flags); 3322698ec016SMartin Peschke zfcp_erp_modify_port_status(port, id, ref, 3323698ec016SMartin Peschke ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); 3324d736a27bSAndreas Herrmann read_unlock_irqrestore(&zfcp_data.config_lock, flags); 3325d736a27bSAndreas Herrmann zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED); 3326d736a27bSAndreas Herrmann } 3327d736a27bSAndreas Herrmann 3328698ec016SMartin Peschke void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, u64 ref) 3329d736a27bSAndreas Herrmann { 3330d736a27bSAndreas Herrmann struct zfcp_adapter *adapter = unit->port->adapter; 3331d736a27bSAndreas Herrmann 3332d736a27bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "u_access_boxed"); 3333d736a27bSAndreas Herrmann debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); 3334698ec016SMartin Peschke zfcp_erp_modify_unit_status(unit, id, ref, 3335698ec016SMartin Peschke ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); 3336d736a27bSAndreas Herrmann zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED); 3337d736a27bSAndreas Herrmann } 3338d736a27bSAndreas Herrmann 3339698ec016SMartin Peschke void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, u64 ref) 33401da177e4SLinus Torvalds { 33411da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 33421da177e4SLinus Torvalds unsigned long flags; 33431da177e4SLinus Torvalds 3344d736a27bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "p_access_denied"); 33451da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); 33461da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 3347698ec016SMartin Peschke zfcp_erp_modify_port_status(port, id, ref, 3348d736a27bSAndreas Herrmann ZFCP_STATUS_COMMON_ERP_FAILED | 3349698ec016SMartin Peschke ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); 33501da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 33511da177e4SLinus Torvalds } 33521da177e4SLinus Torvalds 3353698ec016SMartin Peschke void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, u64 ref) 33541da177e4SLinus Torvalds { 33551da177e4SLinus Torvalds struct zfcp_adapter *adapter = unit->port->adapter; 33561da177e4SLinus Torvalds 3357d736a27bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "u_access_denied"); 33581da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); 3359698ec016SMartin Peschke zfcp_erp_modify_unit_status(unit, id, ref, 3360d736a27bSAndreas Herrmann ZFCP_STATUS_COMMON_ERP_FAILED | 3361698ec016SMartin Peschke ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); 33621da177e4SLinus Torvalds } 33631da177e4SLinus Torvalds 33641da177e4SLinus Torvalds void 33651da177e4SLinus Torvalds zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) 33661da177e4SLinus Torvalds { 33671da177e4SLinus Torvalds struct zfcp_port *port; 33681da177e4SLinus Torvalds unsigned long flags; 33691da177e4SLinus Torvalds 3370aef4a983SMaxim Shchetynin if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) 3371aef4a983SMaxim Shchetynin return; 3372aef4a983SMaxim Shchetynin 3373d736a27bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); 337406506d00SAndreas Herrmann debug_event(adapter->erp_dbf, 3, zfcp_get_busid_by_adapter(adapter), 8); 33751da177e4SLinus Torvalds 33761da177e4SLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 33776f71d9bcS if (adapter->nameserver_port) 33786f71d9bcS zfcp_erp_port_access_changed(adapter->nameserver_port); 33791da177e4SLinus Torvalds list_for_each_entry(port, &adapter->port_list_head, list) 33801da177e4SLinus Torvalds if (port != adapter->nameserver_port) 33811da177e4SLinus Torvalds zfcp_erp_port_access_changed(port); 33821da177e4SLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 33831da177e4SLinus Torvalds } 33841da177e4SLinus Torvalds 33851da177e4SLinus Torvalds void 33861da177e4SLinus Torvalds zfcp_erp_port_access_changed(struct zfcp_port *port) 33871da177e4SLinus Torvalds { 33881da177e4SLinus Torvalds struct zfcp_adapter *adapter = port->adapter; 33891da177e4SLinus Torvalds struct zfcp_unit *unit; 33901da177e4SLinus Torvalds 3391d736a27bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "p_access_recover"); 33921da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); 33931da177e4SLinus Torvalds 33941da177e4SLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, 3395d736a27bSAndreas Herrmann &port->status) && 3396d736a27bSAndreas Herrmann !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED, 33971da177e4SLinus Torvalds &port->status)) { 33981da177e4SLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) 33991da177e4SLinus Torvalds list_for_each_entry(unit, &port->unit_list_head, list) 34001da177e4SLinus Torvalds zfcp_erp_unit_access_changed(unit); 34011da177e4SLinus Torvalds return; 34021da177e4SLinus Torvalds } 34031da177e4SLinus Torvalds 34041da177e4SLinus Torvalds ZFCP_LOG_NORMAL("reopen of port 0x%016Lx on adapter %s " 34051da177e4SLinus Torvalds "(due to ACT update)\n", 34061da177e4SLinus Torvalds port->wwpn, zfcp_get_busid_by_adapter(adapter)); 34071da177e4SLinus Torvalds if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED) != 0) 34081da177e4SLinus Torvalds ZFCP_LOG_NORMAL("failed reopen of port" 34091da177e4SLinus Torvalds "(adapter %s, wwpn=0x%016Lx)\n", 34101da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter), port->wwpn); 34111da177e4SLinus Torvalds } 34121da177e4SLinus Torvalds 34131da177e4SLinus Torvalds void 34141da177e4SLinus Torvalds zfcp_erp_unit_access_changed(struct zfcp_unit *unit) 34151da177e4SLinus Torvalds { 34161da177e4SLinus Torvalds struct zfcp_adapter *adapter = unit->port->adapter; 34171da177e4SLinus Torvalds 3418d736a27bSAndreas Herrmann debug_text_event(adapter->erp_dbf, 3, "u_access_recover"); 34191da177e4SLinus Torvalds debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); 34201da177e4SLinus Torvalds 3421d736a27bSAndreas Herrmann if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, 3422d736a27bSAndreas Herrmann &unit->status) && 3423d736a27bSAndreas Herrmann !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED, 3424d736a27bSAndreas Herrmann &unit->status)) 34251da177e4SLinus Torvalds return; 34261da177e4SLinus Torvalds 34271da177e4SLinus Torvalds ZFCP_LOG_NORMAL("reopen of unit 0x%016Lx on port 0x%016Lx " 34281da177e4SLinus Torvalds " on adapter %s (due to ACT update)\n", 34291da177e4SLinus Torvalds unit->fcp_lun, unit->port->wwpn, 34301da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 34311da177e4SLinus Torvalds if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED) != 0) 34321da177e4SLinus Torvalds ZFCP_LOG_NORMAL("failed reopen of unit (adapter %s, " 34331da177e4SLinus Torvalds "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n", 34341da177e4SLinus Torvalds zfcp_get_busid_by_adapter(adapter), 34351da177e4SLinus Torvalds unit->port->wwpn, unit->fcp_lun); 34361da177e4SLinus Torvalds } 34371da177e4SLinus Torvalds 34381da177e4SLinus Torvalds #undef ZFCP_LOG_AREA 3439