zfcp_fsf.c revision 869b2b444c58302e3233ce0b671fabf28135a37d
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 24a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann * This file is part of the zfcp device driver for 34a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann * FCP adapters for IBM System z9 and zSeries. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 54a9d2d8bf989c77b54add430932fa5ed8a80dba9Andreas Herrmann * (C) Copyright IBM Corp. 2002, 2006 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * any later version. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "zfcp_ext.h" 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *); 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *); 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_open_port_handler(struct zfcp_fsf_req *); 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_close_port_handler(struct zfcp_fsf_req *); 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *); 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *); 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *); 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *); 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_fcp_command_task_management_handler( 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *); 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *); 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *); 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int zfcp_fsf_req_sbal_check( 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *, struct zfcp_qdio_queue *, int); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int zfcp_use_one_sbal( 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scatterlist *, int, struct scatterlist *, int); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct zfcp_fsf_req *zfcp_fsf_req_alloc(mempool_t *, int); 452abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmannstatic int zfcp_fsf_req_send(struct zfcp_fsf_req *); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); 49aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetyninstatic void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *, 50aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin struct fsf_link_down_info *); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* association between FSF command and FSF QTCB type */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 fsf_qtcb_type[] = { 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_FCP_CMND] = FSF_IO_COMMAND, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_ABORT_FCP_CMND] = FSF_SUPPORT_COMMAND, 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_OPEN_PORT_WITH_DID] = FSF_SUPPORT_COMMAND, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_OPEN_LUN] = FSF_SUPPORT_COMMAND, 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_LUN] = FSF_SUPPORT_COMMAND, 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_PORT] = FSF_SUPPORT_COMMAND, 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_PHYSICAL_PORT] = FSF_SUPPORT_COMMAND, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_SEND_ELS] = FSF_SUPPORT_COMMAND, 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_SEND_GENERIC] = FSF_SUPPORT_COMMAND, 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND, 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_EXCHANGE_PORT_DATA] = FSF_PORT_COMMAND, 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND, 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char zfcp_act_subtable_type[5][8] = { 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unknown", "OS", "WWPN", "DID", "LUN" 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************/ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************** FSF related Functions *************************/ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************/ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_alloc 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Obtains an fsf_req and potentially a qtcb (for all but 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsolicited requests) via helper functions 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Does some initial fsf request set-up. 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: pointer to allocated fsf_req if successfull 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL otherwise 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: none 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct zfcp_fsf_req * 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_alloc(mempool_t *pool, int req_flags) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t size; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *ptr; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req_flags & ZFCP_REQ_NO_QTCB) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = sizeof(struct zfcp_fsf_req); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 103dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens size = sizeof(struct zfcp_fsf_req_qtcb); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 105dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens if (likely(pool)) 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = mempool_alloc(pool, GFP_ATOMIC); 107dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens else { 108dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens if (req_flags & ZFCP_REQ_NO_QTCB) 109dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens ptr = kmalloc(size, GFP_ATOMIC); 110dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens else 111dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens ptr = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache, 11254e6ecb23951b195d02433a741c7f7cb0b796c78Christoph Lameter GFP_ATOMIC); 113dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens } 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 115dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens if (unlikely(!ptr)) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(ptr, 0, size); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req_flags & ZFCP_REQ_NO_QTCB) { 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = (struct zfcp_fsf_req *) ptr; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 123dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens fsf_req = &((struct zfcp_fsf_req_qtcb *) ptr)->fsf_req; 124dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens fsf_req->qtcb = &((struct zfcp_fsf_req_qtcb *) ptr)->qtcb; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->pool = pool; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fsf_req; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_free 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Frees the memory of an fsf_req (and potentially a qtcb) or 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns it into the pool via helper functions. 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: sod all 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: none 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1431db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmannvoid 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 146dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens if (likely(fsf_req->pool)) { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(fsf_req, fsf_req->pool); 148dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens return; 149dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens } 150dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens 151dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens if (fsf_req->qtcb) { 152dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, fsf_req); 153dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens return; 154dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens } 155dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens 156dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens kfree(fsf_req); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 159869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke/* 160869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke * Never ever call this without shutting down the adapter first. 161869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke * Otherwise the adapter would continue using and corrupting s390 storage. 162869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke * Included BUG_ON() call to ensure this is done. 163869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke * ERP is supposed to be the only user of this function. 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1656fcc47111ae14f284007e1b9a5002babb01d913cSwen Schilligvoid zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 167869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke struct zfcp_fsf_req *fsf_req, *tmp; 168fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske unsigned long flags; 1696fcc47111ae14f284007e1b9a5002babb01d913cSwen Schillig LIST_HEAD(remove_queue); 170869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke unsigned int i; 171fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske 172869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke BUG_ON(atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)); 173fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_lock_irqsave(&adapter->req_list_lock, flags); 174fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske atomic_set(&adapter->reqs_active, 0); 175869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke for (i = 0; i < REQUEST_LIST_SIZE; i++) 1766fcc47111ae14f284007e1b9a5002babb01d913cSwen Schillig list_splice_init(&adapter->req_list[i], &remove_queue); 177fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_unlock_irqrestore(&adapter->req_list_lock, flags); 178fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske 179869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) { 180869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke list_del(&fsf_req->list); 181869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; 182869b2b444c58302e3233ce0b671fabf28135a37dMartin Peschke zfcp_fsf_req_complete(fsf_req); 1836fcc47111ae14f284007e1b9a5002babb01d913cSwen Schillig } 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_complete 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Updates active counts and timers for openfcp-reqs 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * May cleanup request after req_eval returns 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - success 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * !0 - failure 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * context: 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req) 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cleanup; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) { 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Status read response received\n"); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: all cleanup handling is done in the callchain of 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the function call-chain below. 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_status_read_handler(fsf_req); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2112abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann } else { 2122abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann del_timer(&fsf_req->timer); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_protstatus_eval(fsf_req); 2142abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann } 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fsf_req may be deleted due to waking up functions, so 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cleanup is saved here and used later 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cleanup = 1; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cleanup = 0; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_COMPLETED; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* cleanup request if requested by initiator */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(cleanup)) { 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("removing FSF request %p\n", fsf_req); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lock must not be held here since it will be 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * grabed by the called routine, too 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2341db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann zfcp_fsf_req_free(fsf_req); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* notify initiator waiting for the requests completion */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("waking initiator of FSF request %p\n",fsf_req); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: Race! We must not access fsf_req here as it might have been 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cleaned up already due to the set ZFCP_STATUS_FSFREQ_COMPLETED 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * flag. It's an improbable case. But, we have the same paranoia for 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the cleanup flag already. 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Might better be handled using complete()? 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (setting the flag and doing wakeup ought to be atomic 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with regard to checking the flag as long as waitqueue is 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * part of the to be released structure) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up(&fsf_req->completion_wq); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_protstatus_eval 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates the QTCB of the finished FSF request 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and initiates appropriate actions 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (usually calling FSF command specific handlers) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * context: 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 2738a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin struct fsf_qtcb *qtcb = fsf_req->qtcb; 2748a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin union fsf_prot_status_qual *prot_status_qual = 2758a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin &qtcb->prefix.prot_status_qual; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2778a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_hba_dbf_event_fsf_response(fsf_req); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("fsf_req 0x%lx has been dismissed\n", 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long) fsf_req); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_protstatus; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* log additional information provided by FSF (if any) */ 288862794fa3fd4c8a44ee22582418736c93e0d3c3aHeiko Carstens if (likely(qtcb->header.log_length)) { 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do not trust them ;-) */ 290862794fa3fd4c8a44ee22582418736c93e0d3c3aHeiko Carstens if (unlikely(qtcb->header.log_start > 291862794fa3fd4c8a44ee22582418736c93e0d3c3aHeiko Carstens sizeof(struct fsf_qtcb))) { 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: ULP (FSF logging) log data starts " 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "beyond end of packet header. Ignored. " 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(start=%i, size=%li)\n", 2968a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->header.log_start, 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct fsf_qtcb)); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto forget_log; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 300862794fa3fd4c8a44ee22582418736c93e0d3c3aHeiko Carstens if (unlikely((size_t) (qtcb->header.log_start + 301862794fa3fd4c8a44ee22582418736c93e0d3c3aHeiko Carstens qtcb->header.log_length) > 302862794fa3fd4c8a44ee22582418736c93e0d3c3aHeiko Carstens sizeof(struct fsf_qtcb))) { 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends " 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "beyond end of packet header. Ignored. " 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(start=%i, length=%i, size=%li)\n", 3068a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->header.log_start, 3078a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->header.log_length, 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct fsf_qtcb)); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto forget_log; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("ULP log data: \n"); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 3138a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin (char *) qtcb + qtcb->header.log_start, 3148a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->header.log_length); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds forget_log: 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF Protocol Status */ 3198a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin switch (qtcb->prefix.prot_status) { 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_GOOD: 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_FSF_STATUS_PRESENTED: 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_QTCB_VERSION_ERROR: 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: The adapter %s contains " 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "microcode of version 0x%x, the device driver " 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "only supports 0x%x. Aborting.\n", 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 3308a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin prot_status_qual->version_error.fsf_version, 3318a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_QTCB_VERSION); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_SEQ_NUMB_ERROR: 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Sequence number mismatch between " 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "driver (0x%x) and adapter %s (0x%x). " 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Restarting all operations on this adapter.\n", 3408a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->prefix.req_seq_no, 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 3428a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin prot_status_qual->sequence_error.exp_req_seq_no); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_UNSUPP_QTCB_TYPE: 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: Packet header type used by the " 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "device driver is incompatible with " 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that used on adapter %s. " 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this adapter.\n", 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_HOST_CONNECTION_INITIALIZING: 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(adapter->status)); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_DUPLICATE_REQUEST_ID: 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx " 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to the adapter %s is ambiguous. " 367aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "Stopping all operations on this adapter.\n", 368aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin *(unsigned long long*) 369aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin (&qtcb->bottom.support.req_handle), 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_LINK_DOWN: 376aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, 377aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin &prot_status_qual->link_down_info); 3782f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann zfcp_erp_adapter_reopen(adapter, 0); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_REEST_QUEUE: 3838a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter with " 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s was re-plugged. " 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Re-starting operations on this adapter.\n", 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* All ports should be marked as ready to run again */ 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_modify_adapter_status(adapter, 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_COMMON_RUNNING, 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_SET); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_COMMON_ERP_FAILED); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_ERROR_STATE: 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: The adapter %s " 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "has entered the error state. " 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Restarting all operations on this " 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter.\n", 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Transfer protocol status information " 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "provided by the adapter %s " 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is not compatible with the device driver. " 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this adapter. " 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x).\n", 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 4158a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->prefix.prot_status); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_protstatus: 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always call specific handlers to give them a chance to do 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * something meaningful even in error cases 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_fsfstatus_eval(fsf_req); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_fsfstatus_eval 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FSF status of completed FSF request 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and acts accordingly 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req) 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF Status */ 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_COMMAND: 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Command issued by the device driver is " 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "not known by the adapter %s " 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this adapter. " 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x).\n", 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(fsf_req->adapter), 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_command); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_RSP_AVAILABLE: 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("FCP Sense data will be presented to the " 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "SCSI stack.\n"); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_fsfstatus_qual_eval(fsf_req); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always call specific handlers to give them a chance to do 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * something meaningful even in error cases 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_dispatch(fsf_req); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_fsfstatus_qual_eval 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FSF status-qualifier of completed FSF request 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and acts accordingly 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_FCP_RSP_AVAILABLE: 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_RETRY_IF_POSSIBLE: 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The SCSI-stack may now issue retries or escalate */ 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_COMMAND_ABORTED: 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Carry the aborted state on to upper layer */ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTED; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_NO_RECOM: 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: No recommendation could be given for a" 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "problem on the adapter %s " 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this adapter. ", 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(fsf_req->adapter)); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_PROGRAMMING_ERROR: 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer " 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s)\n", 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(fsf_req->adapter)); 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_NO_RETRY_POSSIBLE: 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dealt with in the respective functions */ 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Additional status info could " 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "not be interpreted properly.\n"); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 536aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin/** 537aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin * zfcp_fsf_link_down_info_eval - evaluate link down information block 538aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin */ 539aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetyninstatic void 540aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetyninzfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, 541aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin struct fsf_link_down_info *link_down) 542aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin{ 543ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, 544ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin &adapter->status)) 545ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin return; 546ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin 547ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); 548ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin 5492f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann if (link_down == NULL) 5502f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann goto out; 551ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin 552aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin switch (link_down->error_code) { 553aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_LIGHT: 554aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 555aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(no light detected)\n", 556aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 557aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 558aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_WRAP_PLUG: 559aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 560aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(wrap plug detected)\n", 561aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 562aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 563aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_FCP: 564aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 565aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(adjacent node on link does not support FCP)\n", 566aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 567aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 568aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_FIRMWARE_UPDATE: 569aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 570aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(firmware update in progress)\n", 571aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 572aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 573aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_INVALID_WWPN: 574aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 575aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(duplicate or invalid WWPN detected)\n", 576aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 577aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 578aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_NPIV_SUPPORT: 579aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 580aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(no support for NPIV by Fabric)\n", 581aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 582aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 583aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_FCP_RESOURCES: 584aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 585aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(out of resource in FCP daughtercard)\n", 586aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 587aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 588aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_FABRIC_RESOURCES: 589aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 590aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(out of resource in Fabric)\n", 591aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 592aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 593aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE: 594aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 595aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(unable to Fabric login)\n", 596aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 597aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 598aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED: 599aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("WWPN assignment file corrupted on adapter %s\n", 600aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 601aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 602aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED: 603aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("Mode table corrupted on adapter %s\n", 604aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 605aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 606aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT: 607aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("No WWPN for assignment table on adapter %s\n", 608aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 609aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 610aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin default: 611aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter %s is down " 612aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "(warning: unknown reason code %d)\n", 613aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter), 614aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin link_down->error_code); 615aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin } 616aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 617aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) 618aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_DEBUG("Debug information to link down: " 619aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "primary_status=0x%02x " 620aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "ioerr_code=0x%02x " 621aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "action_code=0x%02x " 622aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "reason_code=0x%02x " 623aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "explanation_code=0x%02x " 624aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "vendor_specific_code=0x%02x\n", 625aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin link_down->primary_status, 626aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin link_down->ioerr_code, 627aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin link_down->action_code, 628aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin link_down->reason_code, 629aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin link_down->explanation_code, 630aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin link_down->vendor_specific_code); 631aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 6322f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann out: 6332f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann zfcp_erp_adapter_failed(adapter); 634aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin} 635aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_dispatch 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: calls the appropriate command specific handler 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_erp_action *erp_action = fsf_req->erp_action; 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->fsf_command) { 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_FCP_CMND: 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_fcp_command_handler(fsf_req); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_ABORT_FCP_CMND: 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_abort_fcp_command_handler(fsf_req); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_SEND_GENERIC: 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_ct_handler(fsf_req); 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_OPEN_PORT_WITH_DID: 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_open_port_handler(fsf_req); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_OPEN_LUN: 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_open_unit_handler(fsf_req); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_CLOSE_LUN: 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_close_unit_handler(fsf_req); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_CLOSE_PORT: 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_close_port_handler(fsf_req); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_CLOSE_PHYSICAL_PORT: 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_close_physical_port_handler(fsf_req); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_EXCHANGE_CONFIG_DATA: 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_exchange_config_data_handler(fsf_req); 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_EXCHANGE_PORT_DATA: 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_exchange_port_data_handler(fsf_req); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_SEND_ELS: 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_els_handler(fsf_req); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_DOWNLOAD_CONTROL_FILE: 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_control_file_handler(fsf_req); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_UPLOAD_CONTROL_FILE: 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_control_file_handler(fsf_req); 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Command issued by the device driver is " 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "not supported by the adapter %s\n", 7098a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->fsf_command != fsf_req->qtcb->header.fsf_command) 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Command issued by the device driver differs " 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "from the command returned by the adapter %s " 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x, 0x%x).\n", 7158a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_get_busid_by_adapter(adapter), 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->fsf_command, 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_command); 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!erp_action) 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_async_handler(erp_action, 0); 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_status_read 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: initiates a Status Read command at the specified adapter 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_status_read_buffer *status_buffer; 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS, 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_flags | ZFCP_REQ_NO_QTCB, 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->pool.fsf_req_status_read, 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create unsolicited status " 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "buffer for adapter %s.\n", 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req_create; 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_STATUS; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY; 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = 2; 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer = 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_alloc(adapter->pool.data_status_read, GFP_ATOMIC); 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!status_buffer) { 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: could not get some buffer\n"); 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_buf; 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer)); 768059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) status_buffer; 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* insert pointer to respective buffer */ 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_curr(fsf_req); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale->addr = (void *) status_buffer; 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale->length = sizeof(struct fsf_status_read_buffer); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7752abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: Could not set-up unsolicited status " 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "environment.\n"); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req_send; 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Status Read request initiated (adapter%s)\n", 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req_send: 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(status_buffer, adapter->pool.data_status_read); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_buf: 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req_create: 7928a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req) 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_status_read_buffer *status_buffer; 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 806059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(port, &adapter->port_list_head, list) 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port->d_id == (status_buffer->d_id & ZFCP_DID_MASK)) 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!port || (port->d_id != (status_buffer->d_id & ZFCP_DID_MASK))) { 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Reopen port indication received for" 8171d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "nonexisting port with d_id 0x%06x on " 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s. Ignored.\n", 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer->d_id & ZFCP_DID_MASK, 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (status_buffer->status_subtype) { 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT: 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "unsol_pc_phys:"); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(port, 0); 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SUB_ERROR_PORT: 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "unsol_pc_err:"); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_shutdown(port, 0); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "unsol_unk_sub:"); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &status_buffer->status_subtype, sizeof (u32)); 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Undefined status subtype received " 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for a reopen indication on port with " 8421d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "d_id 0x%06x on the adapter %s. " 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Ignored. (debug info 0x%x)\n", 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer->d_id, 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer->status_subtype); 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_status_read_handler 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Open Port command 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_status_read_buffer *status_buffer = 865059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann (struct fsf_status_read_buffer *) fsf_req->data; 866b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner struct fsf_bit_error_payload *fsf_bit_error; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { 8698a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer); 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(status_buffer, adapter->pool.data_status_read); 8711db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann zfcp_fsf_req_free(fsf_req); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8758a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_hba_dbf_event_fsf_unsol("read", adapter, status_buffer); 8768a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (status_buffer->status_type) { 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_PORT_CLOSED: 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_status_read_port_closed(fsf_req); 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_INCOMING_ELS: 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_incoming_els(fsf_req); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SENSE_DATA_AVAIL: 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n", 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: 893b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error = (struct fsf_bit_error_payload *) 894b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner status_buffer->payload; 895b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner ZFCP_LOG_NORMAL("Warning: bit error threshold data " 896b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "received (adapter %s, " 897b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "link failures = %i, loss of sync errors = %i, " 898b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "loss of signal errors = %i, " 899b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "primitive sequence errors = %i, " 900b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "invalid transmission word errors = %i, " 901b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "CRC errors = %i)\n", 902b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner zfcp_get_busid_by_adapter(adapter), 903b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->link_failure_error_count, 904b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->loss_of_sync_error_count, 905b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->loss_of_signal_error_count, 906b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->primitive_sequence_error_count, 907b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->invalid_transmission_word_error_count, 908b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->crc_error_count); 909b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner ZFCP_LOG_INFO("Additional bit error threshold data " 910b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "(adapter %s, " 911b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "primitive sequence event time-outs = %i, " 912b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "elastic buffer overrun errors = %i, " 913b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "advertised receive buffer-to-buffer credit = %i, " 914b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "current receice buffer-to-buffer credit = %i, " 915b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "advertised transmit buffer-to-buffer credit = %i, " 916b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner "current transmit buffer-to-buffer credit = %i)\n", 917b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner zfcp_get_busid_by_adapter(adapter), 918b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->primitive_sequence_event_timeout_count, 919b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->elastic_buffer_overrun_error_count, 920b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->advertised_receive_b2b_credit, 921b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->current_receive_b2b_credit, 922b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->advertised_transmit_b2b_credit, 923b7a52fa7fff2309031a2f849bc489206afd2fa4aRalph Wuerthner fsf_bit_error->current_transmit_b2b_credit); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_LINK_DOWN: 927aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin switch (status_buffer->status_subtype) { 928aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: 929aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_INFO("Physical link to adapter %s is down\n", 930aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 931ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, 932ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin (struct fsf_link_down_info *) 933ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin &status_buffer->payload); 934aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 935aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_STATUS_READ_SUB_FDISC_FAILED: 936aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_INFO("Local link to adapter %s is down " 937aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "due to failed FDISC login\n", 938ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 939ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, 940ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin (struct fsf_link_down_info *) 941ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin &status_buffer->payload); 942aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 943aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: 944aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_INFO("Local link to adapter %s is down " 945aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "due to firmware update on adapter\n", 946aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 947ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, NULL); 948aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 949aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin default: 950aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_INFO("Local link to adapter %s is down " 951aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "due to unknown reason\n", 952aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 953ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, NULL); 954aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin }; 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_LINK_UP: 958aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " 959ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin "Restarting operations on this adapter\n", 960ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* All ports should be marked as ready to run again */ 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_modify_adapter_status(adapter, 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_COMMON_RUNNING, 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_SET); 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_COMMON_ERP_FAILED); 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9709eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin case FSF_STATUS_READ_NOTIFICATION_LOST: 9719eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: " 9729eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin "adapter %s%s%s%s%s%s%s%s%s\n", 9739eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin zfcp_get_busid_by_adapter(adapter), 9749eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin (status_buffer->status_subtype & 9759eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_INCOMING_ELS) ? 9769eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ", incoming ELS" : "", 9779eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin (status_buffer->status_subtype & 9789eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_SENSE_DATA) ? 9799eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ", sense data" : "", 9809eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin (status_buffer->status_subtype & 9819eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_LINK_STATUS) ? 9829eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ", link status change" : "", 9839eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin (status_buffer->status_subtype & 9849eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_PORT_CLOSED) ? 9859eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ", port close" : "", 9869eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin (status_buffer->status_subtype & 9879eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ? 9889eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ", bit error exception" : "", 9899eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin (status_buffer->status_subtype & 9909eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_ACT_UPDATED) ? 9919eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ", ACT update" : "", 9929eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin (status_buffer->status_subtype & 9939eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_ACT_HARDENED) ? 9949eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ", ACT hardening" : "", 9959eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin (status_buffer->status_subtype & 9969eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ? 9979eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin ", adapter feature change" : ""); 9989eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin 9999eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin if (status_buffer->status_subtype & 10009eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_STATUS_READ_SUB_ACT_UPDATED) 10019eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin zfcp_erp_adapter_access_changed(adapter); 10029eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin break; 10039eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_CFDC_UPDATED: 10058a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_access_changed(adapter); 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_CFDC_HARDENED: 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (status_buffer->status_subtype) { 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE: 10138a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("CFDC of adapter %s saved on SE\n", 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2: 10178a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("CFDC of adapter %s has been copied " 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to the secondary SE\n", 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 10228a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("CFDC of adapter %s has been hardened\n", 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1027aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: 1028aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin debug_text_event(adapter->erp_dbf, 2, "unsol_features:"); 1029aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_INFO("List of supported features on adapter %s has " 1030aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin "been changed from 0x%08X to 0x%08X\n", 1031aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_get_busid_by_adapter(adapter), 1032aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin *(u32*) (status_buffer->payload + 4), 1033aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin *(u32*) (status_buffer->payload)); 1034aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin adapter->adapter_features = *(u32*) status_buffer->payload; 1035aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 1036aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 10388a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown " 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "type was received (debug info 0x%x)\n", 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer->status_type); 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Dump of status_read_buffer %p:\n", 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer); 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) status_buffer, 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fsf_status_read_buffer)); 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(status_buffer, adapter->pool.data_status_read); 10491db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann zfcp_fsf_req_free(fsf_req); 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * recycle buffer and start new request repeat until outbound 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * queue is empty or adapter shutdown is requested 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(qdio): 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we may wait in the req_create for 5s during shutdown, so 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qdio_cleanup will have to wait at least that long before returning 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with failure to allow us a proper cleanup under all circumstances 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocation failure possible? (Is this code needed?) 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_status_read(adapter, 0); 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Failed to create unsolicited status read " 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request for the adapter %s.\n", 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* temporary fix to avoid status read buffer shortage */ 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->status_read_failed++; 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ZFCP_STATUS_READS_RECOM - adapter->status_read_failed) 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds < ZFCP_STATUS_READ_FAILED_THRESHOLD) { 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("restart adapter %s due to status read " 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "buffer shortage\n", 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_abort_fcp_command 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: tells FSF to abort a running SCSI command 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(design): should be watched by a timeout !!! 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(design) shouldn't this be modified to return an int 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * also...don't know how though 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct zfcp_fsf_req * 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_abort_fcp_command(unsigned long old_req_id, 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter, 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit, int req_flags) 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 11022abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann unsigned long lock_flags; 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_flags, adapter->pool.fsf_req_abort, 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Failed to create an abort command " 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request for lun 0x%016Lx on port 0x%016Lx " 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s.\n", 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1123059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) unit; 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handles of unit and its parent port in QTCB */ 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handle of request which should be aborted */ 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id; 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11322abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT); 11332abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Failed to send abort command request " 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n", 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, unit->fcp_lun); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Abort FCP Command request initiated " 11451d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter%s, port d_id=0x%06x, " 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit x%016Lx, old_req_id=0x%lx)\n", 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->d_id, 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, old_req_id); 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fsf_req; 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_abort_fcp_command_handler 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Abort FCP Command request 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 1166059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit; 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char status_qual = 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->qtcb->header.fsf_status_qual.word[0]; 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */ 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1175059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) new_fsf_req->data; 1176059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (new_fsf_req->qtcb->header.fsf_status) { 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status_qual >> 4 != status_qual % 0xf) { 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv0"); 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * In this case a command that was sent prior to a port 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reopen was aborted (handles are different). This is 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fine. 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for " 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s invalid. " 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally.\n", 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &new_fsf_req->qtcb->header. 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual, 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Let's hope this sorts out the mess */ 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv1"); 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status_qual >> 4 != status_qual % 0xf) { 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2 */ 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv0"); 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * In this case a command that was sent prior to a unit 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reopen was aborted (handles are different). 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is fine. 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("Warning: Temporary LUN identifier 0x%x of LUN " 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen in rare cases. " 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Trying to re-establish link.\n", 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Status qualifier data:\n"); 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &new_fsf_req->qtcb->header. 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual, 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Let's hope this sorts out the mess */ 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv1"); 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_COMMAND_DOES_NOT_EXIST: 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_no_exist"); 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to " 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be reopened\n", unit->port->wwpn, 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 2, 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_pboxed"); 1255d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_BOXED: 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s needs " 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to be reopened\n", 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); 1267d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_unit_boxed(unit); 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) { 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 127765a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SCSI stack will escalate */ 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->qtcb->header.fsf_status_qual.word[0]); 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 0, 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(new_fsf_req->adapter->erp_dbf, 0, 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &new_fsf_req->qtcb->header. 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual.word[0], sizeof (u32)); 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED; 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->qtcb->header.fsf_status); 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 0, 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_inval:"); 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(new_fsf_req->adapter->erp_dbf, 0, 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &new_fsf_req->qtcb->header.fsf_status, 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_use_one_sbal - checks whether req buffer and resp bother each fit into 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one SBALE 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Two scatter-gather lists are passed, one for the reqeust and one for the 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response. 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_use_one_sbal(struct scatterlist *req, int req_count, 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scatterlist *resp, int resp_count) 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((req_count == 1) && 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (resp_count == 1) && 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (((unsigned long) zfcp_sg_to_address(&req[0]) & 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAGE_MASK) == 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((unsigned long) (zfcp_sg_to_address(&req[0]) + 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req[0].length - 1) & PAGE_MASK)) && 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (((unsigned long) zfcp_sg_to_address(&resp[0]) & 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAGE_MASK) == 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((unsigned long) (zfcp_sg_to_address(&resp[0]) + 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resp[0].length - 1) & PAGE_MASK))); 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS) 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ct: pointer to struct zfcp_send_ct which conatins all needed data for 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the request 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: pointer to memory pool, if non-null this pool is used to allocate 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a struct zfcp_fsf_req 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @erp_action: pointer to erp_action, if non-null the Generic Service request 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is sent within error recovery 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_erp_action *erp_action) 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = ct->port; 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = port->adapter; 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC, 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool, &lock_flags, &fsf_req); 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create CT request (FC-GS) for " 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter: %s\n", 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req; 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_use_one_sbal(ct->req, ct->req_count, 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->resp, ct->resp_count)){ 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* both request buffer and response buffer 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fit into one sbale each */ 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].addr = zfcp_sg_to_address(&ct->req[0]); 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].length = ct->req[0].length; 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].length = ct->resp[0].length; 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; 1386aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin } else if (adapter->adapter_features & 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_FEATURE_ELS_CT_CHAINED_SBALS) { 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try to use chained SBALs */ 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->req, ct->req_count, 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_CT_REQ); 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of CT request failed " 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.req_buf_length = bytes; 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->resp, ct->resp_count, 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_CT_REQ); 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of CT request failed " 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.resp_buf_length = bytes; 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reject send generic request */ 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "error: microcode does not support chained SBALs," 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CT request too big (adapter %s)\n", 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EOPNOTSUPP; 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* settings in QTCB */ 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = port->handle; 143406506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann fsf_req->qtcb->bottom.support.service_class = 143506506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT; 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.timeout = ct->timeout; 1437059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) ct; 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14398a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_ct_request(fsf_req); 14408a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 14412abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann if (erp_action) { 14422abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 14432abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 14442abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 14452abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann } else 14462abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 14472abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 14482abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann ret = zfcp_fsf_req_send(fsf_req); 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: initiation of CT request failed " 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), port->wwpn); 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("CT request initiated (adapter %s, port 0x%016Lx)\n", 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), port->wwpn); 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_send: 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (erp_action != NULL) { 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req: 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_ct_handler - handler for Generic Service requests 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1476059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Data specific for the Generic Service request is passed using 1477059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * fsf_req->data. There we find the pointer to struct zfcp_send_ct. 1478059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Usually a specific handler for the CT request is called which is 1479059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * found in this structure. 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_send_ct *send_ct; 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 1493059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann send_ct = (struct zfcp_send_ct *) fsf_req->data; 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = send_ct->port; 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 15058a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_ct_response(fsf_req); 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 151006506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_LOG_INFO("error: adapter %s does not support fc " 151106506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann "class %d.\n", 151206506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann zfcp_get_busid_by_port(port), 151306506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT); 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]){ 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reopening link to port */ 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_test_link(port); 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x " 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "arrived.\n", 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("access denied, cannot send generic service " 15431d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "command (adapter %s, port d_id=0x%06x)\n", 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GENERIC_COMMAND_REJECTED: 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("generic service command rejected " 15651d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id=0x%06x)\n", 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej"); 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Temporary port identifier 0x%x for port " 15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may " 15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "happen occasionally.\n", port->handle, 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv"); 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("port needs to be reopened " 15911d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id=0x%06x)\n", 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); 1594d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(port); 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* following states should never occure, all cases avoided 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in zfcp_fsf_send_ct - but who knows ... */ 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PAYLOAD_SIZE_MISMATCH: 16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("payload size mismatch (adapter: %s, " 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "req_buf_length=%d, resp_buf_length=%d)\n", 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_REQUEST_SIZE_TOO_LARGE: 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("request size too large (adapter: %s, " 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "req_buf_length=%d)\n", 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length); 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_RESPONSE_SIZE_TOO_LARGE: 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("response size too large (adapter: %s, " 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SBAL_MISMATCH: 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, " 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", header->fsf_status); 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:"); 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof (u32)); 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_ct->status = retval; 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (send_ct->handler != NULL) 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_ct->handler(send_ct->handler_data); 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_els - initiate an ELS command (FC-FS) 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @els: pointer to struct zfcp_send_els which contains all needed data for 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the command. 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_els(struct zfcp_send_els *els) 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 165813e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann u32 d_id; 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d_id = els->d_id; 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = els->adapter; 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_REQ_AUTO_CLEANUP, 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, &lock_flags, &fsf_req); 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of ELS request failed " 16721d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id: 0x%06x)\n", 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req; 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_use_one_sbal(els->req, els->req_count, 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds els->resp, els->resp_count)){ 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* both request buffer and response buffer 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fit into one sbale each */ 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].addr = zfcp_sg_to_address(&els->req[0]); 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].length = els->req[0].length; 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].length = els->resp[0].length; 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; 1688aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin } else if (adapter->adapter_features & 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_FEATURE_ELS_CT_CHAINED_SBALS) { 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try to use chained SBALs */ 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds els->req, els->req_count, 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_ELS_REQ); 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of ELS request failed " 16971d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id: 0x%06x)\n", 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) { 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.req_buf_length = bytes; 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds els->resp, els->resp_count, 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_ELS_REQ); 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of ELS request failed " 17141d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id: 0x%06x)\n", 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) { 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.resp_buf_length = bytes; 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reject request */ 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: microcode does not support chained SBALs" 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ", ELS request too big (adapter %s, " 17281d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "port d_id: 0x%06x)\n", 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EOPNOTSUPP; 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* settings in QTCB */ 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.d_id = d_id; 173606506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann fsf_req->qtcb->bottom.support.service_class = 173706506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT; 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; 1739059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) els; 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17438a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_els_request(fsf_req); 17448a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 17452abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 17462abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann ret = zfcp_fsf_req_send(fsf_req); 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: initiation of ELS request failed " 17491d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id: 0x%06x)\n", 17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port d_id: " 17551d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_send: 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req: 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_els_handler - handler for ELS commands 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1773059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Data specific for the ELS command is passed using 1774059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * fsf_req->data. There we find the pointer to struct zfcp_send_els. 1775059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Usually a specific handler for the ELS command is called which is 1776059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * found in this structure. 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 178213e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann u32 d_id; 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_send_els *send_els; 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1789059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann send_els = (struct zfcp_send_els *) fsf_req->data; 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = send_els->adapter; 179164b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann port = send_els->port; 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d_id = send_els->d_id; 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 18028a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_els_response(fsf_req); 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 180706506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_LOG_INFO("error: adapter %s does not support fc " 180806506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann "class %d.\n", 180906506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann zfcp_get_busid_by_adapter(adapter), 181006506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT); 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]){ 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); 182164b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann if (port && (send_els->ls_code != ZFCP_LS_ADISC)) 182264b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann zfcp_test_link(port); 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_handle_els_rjt(header->fsf_status_qual.word[1], 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (struct zfcp_ls_rjt_par *) 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[2]); 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_RETRY_IF_POSSIBLE: 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry"); 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x\n", 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char*)header->fsf_status_qual.word, 16); 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ELS_COMMAND_REJECTED: 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("ELS has been rejected because command filter " 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "prohibited sending " 18481d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter: %s, port d_id: 0x%06x)\n", 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PAYLOAD_SIZE_MISMATCH: 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ELS request size and ELS response size must be either " 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "both 0, or both greater than 0 " 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, req_buf_length=%d resp_buf_length=%d)\n", 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_REQUEST_SIZE_TOO_LARGE: 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Length of the ELS request buffer, " 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "specified in QTCB bottom, " 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "exceeds the size of the buffers " 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that have been allocated for ELS request data " 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, req_buf_length=%d)\n", 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length); 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_RESPONSE_SIZE_TOO_LARGE: 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Length of the ELS response buffer, " 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "specified in QTCB bottom, " 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "exceeds the size of the buffers " 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that have been allocated for ELS response data " 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, resp_buf_length=%d)\n", 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SBAL_MISMATCH: 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* should never occure, avoided in zfcp_fsf_send_els */ 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, " 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("access denied, cannot send ELS command " 18961d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id=0x%06x)\n", 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port != NULL) 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bug: An unknown FSF Status was presented " 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, fsf_status=0x%08x)\n", 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval"); 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof(u32)); 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_els->status = retval; 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (send_els->handler != 0) 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_els->handler(send_els->handler_data); 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 19432abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_EXCHANGE_CONFIG_DATA, 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_REQ_AUTO_CLEANUP, 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 19522abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create exchange configuration " 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "data request for adapter %s.\n", 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19602abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19642abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->bottom.config.feature_selection = 1965aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_CFDC | 1966aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_LUN_SHARING | 19679eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_FEATURE_NOTIFICATION_LOST | 1968aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_UPDATE_ALERT; 19692abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 19702abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19722abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 19732abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO 19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("error: Could not send exchange configuration data " 19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "command on the adapter %s\n", 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 19792abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("exchange configuration data request initiated " 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s)\n", 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_config_evaluate 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: fsf_req which belongs to xchg config data request 19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @xchg_ok: specifies if xchg config data was incomplete or complete (0/1) 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: -EIO on error, 0 otherwise 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_config *bottom; 20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 200613e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann struct Scsi_Host *shost = adapter->scsi_host; 20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.config; 20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->low_qtcb_version, bottom->high_qtcb_version); 20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fsf_lic_version = bottom->lic_version; 2012aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin adapter->adapter_features = bottom->adapter_features; 2013aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin adapter->connection_features = bottom->connection_features; 20146f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwpn = 0; 20156f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwnn = 0; 20166f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_d_id = 0; 20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (xchg_ok) { 201913e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_node_name(shost) = bottom->nport_serv_param.wwnn; 202013e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_name(shost) = bottom->nport_serv_param.wwpn; 202113e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; 202213e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_speed(shost) = bottom->fc_link_speed; 202313e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; 20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hydra_version = bottom->adapter_type; 2025ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann if (fc_host_permanent_port_name(shost) == -1) 2026ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_permanent_port_name(shost) = 2027ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_name(shost); 2028ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann if (bottom->fc_topology == FSF_TOPO_P2P) { 2029ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; 2030ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann adapter->peer_wwpn = bottom->plogi_payload.wwpn; 2031ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann adapter->peer_wwnn = bottom->plogi_payload.wwnn; 2032ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_PTP; 2033ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann } else if (bottom->fc_topology == FSF_TOPO_FABRIC) 2034ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_NPORT; 2035ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann else if (bottom->fc_topology == FSF_TOPO_AL) 2036ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; 2037ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann else 2038ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; 20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 204013e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_node_name(shost) = 0; 204113e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_name(shost) = 0; 204213e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_id(shost) = 0; 204313e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 2044ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; 20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hydra_version = 0; 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2048aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hardware_version = bottom->hardware_version; 205013e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann memcpy(fc_host_serial_number(shost), bottom->serial_number, 205113e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann min(FC_SERIAL_NUMBER_SIZE, 17)); 205213e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann EBCASC(fc_host_serial_number(shost), 205313e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann min(FC_SERIAL_NUMBER_SIZE, 17)); 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20566f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n" 205713e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "WWNN 0x%016Lx, " 205813e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "WWPN 0x%016Lx, " 20591d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "S_ID 0x%06x,\n" 206013e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "adapter version 0x%x, " 206113e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "LIC version 0x%x, " 206213e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "FC link speed %d Gb/s\n", 206313e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann zfcp_get_busid_by_adapter(adapter), 206413e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann (wwn_t) fc_host_node_name(shost), 206513e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann (wwn_t) fc_host_port_name(shost), 206613e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_id(shost), 206713e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann adapter->hydra_version, 206813e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann adapter->fsf_lic_version, 206913e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_speed(shost)); 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) { 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: the adapter %s " 20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "only supports newer control block " 20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "versions in comparison to this device " 20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "driver (try updated device driver)\n", 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "low_qtcb_ver"); 20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ZFCP_QTCB_VERSION > bottom->high_qtcb_version) { 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: the adapter %s " 20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "only supports older control block " 20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "versions than this device driver uses" 20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(consider a microcode upgrade)\n", 20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "high_qtcb_ver"); 20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_exchange_config_data_handler 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Exchange Configuration Data command 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_config *bottom; 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 2105aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin struct fsf_qtcb *qtcb = fsf_req->qtcb; 21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2110aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin switch (qtcb->header.fsf_status) { 21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) 21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2116ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann switch (fc_host_port_type(adapter->scsi_host)) { 2117ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann case FC_PORTTYPE_PTP: 21186f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> ZFCP_LOG_NORMAL("Point-to-Point fibrechannel " 21196f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "configuration detected at adapter %s\n" 21206f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "Peer WWNN 0x%016llx, " 21216f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "peer WWPN 0x%016llx, " 21226f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "peer d_id 0x%06x\n", 21236f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> zfcp_get_busid_by_adapter(adapter), 21246f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwnn, 21256f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwpn, 21266f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_d_id); 21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "top-p-to-p"); 21296f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> break; 2130ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann case FC_PORTTYPE_NLPORT: 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel " 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "topology detected at adapter %s " 21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unsupported, shutting down adapter\n", 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "top-al"); 21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 2139ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann case FC_PORTTYPE_NPORT: 2140aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("Switched fabric fibrechannel " 21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "network detected at adapter %s.\n", 21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The fibrechannel topology " 21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "reported by the exchange " 21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "configuration command for " 21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the adapter %s is not " 21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "of a type known to the zfcp " 21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "driver, shutting down adapter\n", 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unknown-topo"); 21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2157aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin bottom = &qtcb->bottom.config; 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { 21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " 21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "allowed by the adapter %s " 21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is lower than the minimum " 21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "required by the driver (%ld bytes).\n", 21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->max_qtcb_size, 21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct fsf_qtcb)); 21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "qtcb-size"); 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_event(fsf_req->adapter->erp_dbf, 0, 21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &bottom->max_qtcb_size, sizeof (u32)); 21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, 21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &adapter->status); 21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: 21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "xchg-inco"); 21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) 21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2182aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); 2183aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 2184aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, 2185aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin &qtcb->header.fsf_status_qual.link_down_info); 21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); 21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_event(fsf_req->adapter->erp_dbf, 0, 21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, sizeof (u32)); 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data - request information about local port 2199aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin * @erp_action: ERP action for the adapter for which port data is requested 22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: for which port data is requested 22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @data: response to exchange port data request 22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 2204aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetyninzfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, 2205aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin struct zfcp_adapter *adapter, 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_port *data) 22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 22102abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann unsigned long lock_flags; 22112abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann int retval = 0; 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2213aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: exchange port data " 22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "command not supported by adapter %s\n", 22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 22222448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0, 2223d2c993d845781d160a7ef759a3e65c6892c4a270Heiko Carstens NULL, &lock_flags, &fsf_req); 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Out of resources. Could not create an " 22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "exchange port data request for" 22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the adapter %s.\n", 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 22312448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann return retval; 2232aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin } 2233aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 2234aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (data) 22352448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann fsf_req->data = (unsigned long) data; 2236059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22412448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann if (erp_action) { 22422448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann erp_action->fsf_req = fsf_req; 22432448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann fsf_req->erp_action = erp_action; 22442abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 22452abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann } else 22462abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22482abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an exchange port data " 22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "command on the adapter %s\n", 22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 2254aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (erp_action) 2255aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin erp_action->fsf_req = NULL; 22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 22582448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann return retval; 22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22612448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22632448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann if (!erp_action) { 22642448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann wait_event(fsf_req->completion_wq, 22652448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 22662448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann zfcp_fsf_req_free(fsf_req); 22672448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann } 22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22712f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann/** 22722f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann * zfcp_fsf_exchange_port_evaluate 22732f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann * @fsf_req: fsf_req which belongs to xchg port data request 22742f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann * @xchg_ok: specifies if xchg port data was incomplete or complete (0/1) 22752f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann */ 22762f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmannstatic void 22772f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmannzfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) 22782f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann{ 22792f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct zfcp_adapter *adapter; 22802f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct fsf_qtcb *qtcb; 22812f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct fsf_qtcb_bottom_port *bottom, *data; 22822f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct Scsi_Host *shost; 22832f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann 22842f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann adapter = fsf_req->adapter; 22852f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann qtcb = fsf_req->qtcb; 22862f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann bottom = &qtcb->bottom.port; 22872f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann shost = adapter->scsi_host; 22882f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann 22892f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann data = (struct fsf_qtcb_bottom_port*) fsf_req->data; 22902f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann if (data) 22912f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); 22922f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann 22932f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) 22942f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann fc_host_permanent_port_name(shost) = bottom->wwpn; 22952f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann else 22962f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann fc_host_permanent_port_name(shost) = fc_host_port_name(shost); 22972f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann fc_host_maxframe_size(shost) = bottom->maximum_frame_size; 22982f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann fc_host_supported_speeds(shost) = bottom->supported_speed; 22992f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann} 23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request 23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) 23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23082f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct zfcp_adapter *adapter; 23092f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct fsf_qtcb *qtcb; 23102f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann 23112f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann adapter = fsf_req->adapter; 23122f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann qtcb = fsf_req->qtcb; 23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 23161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2317aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin switch (qtcb->header.fsf_status) { 23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 23192f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann zfcp_fsf_exchange_port_evaluate(fsf_req, 1); 2320aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); 2321aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 2322aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: 23232f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann zfcp_fsf_exchange_port_evaluate(fsf_req, 0); 2324aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); 2325aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, 2326aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin &qtcb->header.fsf_status_qual.link_down_info); 23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2329aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng"); 2330aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin debug_event(adapter->erp_dbf, 0, 23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, sizeof(u32)); 23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 23371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_port 23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 23401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_port(struct zfcp_erp_action *erp_action) 23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 23482abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_OPEN_PORT_WITH_DID, 23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 23572abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create open port request " 23601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s.\n", 23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 23631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23662abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 23671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 23691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23702abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; 23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); 23722abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->port; 23732abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 23742abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23762abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 23772abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send open port request for " 23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s.\n", 23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 23832abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("open port request initiated " 23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_port_handler 24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Open Port command 24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) 24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_plogi *plogi; 24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2414059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 24231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_ALREADY_OPEN: 24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: remote port 0x%016Lx on adapter %s " 24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is already open.\n", 24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_popen"); 24311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a bug, however operation should continue normally 24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if it is simply ignored 24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot open port 0x%016Lx " 24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: 24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: The FSF adapter is out of resources. " 24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The remote port 0x%016Lx on adapter %s " 24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "could not be opened. Disabling it.\n", 24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_max_ports"); 24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_failed(port); 24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_NO_RETRY_POSSIBLE: 24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("The remote port 0x%016Lx on " 24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s could not be opened. " 24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Disabling it.\n", 24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port)); 24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_no_retry"); 24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_failed(port); 24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save port handle assigned by FSF */ 25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle = header->port_handle; 25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("The remote port 0x%016Lx via adapter %s " 25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was opened, it's port handle is 0x%x\n", 25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port), 25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle); 25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark port as open */ 25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPEN | 25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 2519d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 2520d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann ZFCP_STATUS_COMMON_ACCESS_BOXED, 2521d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann &port->status); 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check whether D_ID has changed during open */ 25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: This check is not airtight, as the FCP channel does 25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not monitor closures of target port connections caused on 25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the remote side. Thus, they might miss out on invalidating 25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locally cached WWPNs (and other N_Port parameters) of gone 25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * target ports. So, our heroic attempt to make things safe 25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could be undermined by 'open port' response data tagged with 25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * obsolete WWPNs. Another reason to monitor potential 25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connection closures ourself at least (by interpreting 25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * incoming ELS' and unsolicited status). It just crosses my 25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mind that one should be able to cross-check by means of 25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * another GID_PN straight after a port has been opened. 25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alternately, an ADISC/PDISC ELS should suffice, as well. 25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds plogi = (struct fsf_plogi *) fsf_req->qtcb->bottom.support.els; 25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, &port->status)) 25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->qtcb->bottom.support.els1_length < 254275bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner sizeof (struct fsf_plogi)) { 25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "warning: insufficient length of " 25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "PLOGI payload (%i)\n", 25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.els1_length); 25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_short_plogi:"); 25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* skip sanity check and assume wwpn is ok */ 25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (plogi->serv_param.wwpn != port->wwpn) { 25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("warning: d_id of port " 25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx changed during " 25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "open\n", port->wwpn); 25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event( 25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_did_change:"); 25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask( 25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_PORT_DID_DID, 25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &port->status); 256175bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner } else { 25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwnn = plogi->serv_param.wwnn; 256375bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner zfcp_plogi_evaluate(port, plogi); 256475bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner } 25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_OP_SUBTYPE: 25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* should never occure, subtype not set in zfcp_fsf_open_port */ 25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("unknown operation subtype (adapter: %s, " 25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "op_subtype=0x%x)\n", 25731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), 25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.operation_subtype); 25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &port->status); 25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_port 25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: submit FSF command "close port" 25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_port(struct zfcp_erp_action *erp_action) 26031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 26052abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_PORT, 26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 26142abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create a close port request " 26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s.\n", 26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26232abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); 26282abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->port; 26292abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 26302abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.port_handle = erp_action->port->handle; 26312abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 26322abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 26332abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 26342abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 26352abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 26361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 26371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send a close port request for " 26381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s.\n", 26391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 26401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 26412abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 26421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 26431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 26441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("close port request initiated " 26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 26481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 26491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 26501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 26511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 26521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 26531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 26541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 26571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_port_handler 26581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 26591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close Port FSF command 26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req) 26651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 26671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 26681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2669059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 26701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 26721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 26731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 26741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 26771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 26781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 26801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may happen " 26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "occasionally.\n", port->handle, 26831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 26841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 26861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 26871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 26881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 26901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(port->adapter, 0); 26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 26921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note: FSF has actually closed the port in this case. 26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The status code is just daft. Fingers crossed for a change 26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 26991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("remote port 0x016%Lx on adapter %s closed, " 27031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port handle 0x%x\n", port->wwpn, 27041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->handle); 27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_modify_port_status(port, 27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_COMMON_OPEN, 27071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_CLEAR); 27081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 27131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 27141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status); 27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 27161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, 27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &port->status); 27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 27251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_physical_port 27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: submit FSF command "close physical port" 27311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 27331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 27341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 27351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) 27371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 27392abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 27402abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann unsigned long lock_flags; 27412abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann int retval = 0; 27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_PHYSICAL_PORT, 27461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 27471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 27482abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 27491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create close physical port " 27511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request (adapter %s, port 0x%016Lx)\n", 27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 27561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27582abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark port as being closed */ 27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, 27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &erp_action->port->status); 27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save a pointer to this port */ 27662abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->port; 27672abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.port_handle = erp_action->port->handle; 27682abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 27692abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 27702abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 27712abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 27722abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 27741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send close physical port " 27751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request (adapter %s, port 0x%016Lx)\n", 27761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 27771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 27782abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 27811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("close physical port request initiated " 27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 27871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 27881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 27891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 27901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 27911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 27941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_physical_port_handler 27951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close Physical Port FSF command 27971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 27991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 28001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 28011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) 28021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 28051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2809059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 28131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x invalid" 28221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx). " 28231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally.\n", 28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle, 28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), 28261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn); 28271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 28291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 28301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 28311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 28331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(port->adapter, 0); 28341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 28351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot close " 28391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "physical port 0x%016Lx on adapter %s\n", 28401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 28411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 28431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 28561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter " 28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s needs to be reopened but it was attempted " 28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to close it physically.\n", 28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port)); 28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_pboxed"); 2866d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(port); 28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 28691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 28731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 28741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This will now be escalated by ERP */ 28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 28801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 28811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 28841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 28901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 28911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 28921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof (u32)); 28941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Remote port 0x%016Lx via adapter %s " 29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "physically closed, port handle 0x%x\n", 29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 29021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->handle); 29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* can't use generic zfcp_erp_modify_port_status because 29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ZFCP_STATUS_COMMON_OPEN must not be reset for the port 29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 29071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(unit, &port->unit_list_head, list) 29081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 29091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 29101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 29131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, &port->status); 29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 29251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_unit 29291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 29301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 29311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 29321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 29341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * assumptions: This routine does not check whether the associated 29351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remote port has already been opened. This should be 29361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done by calling routines. Otherwise some status 29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may be presented by FSF 29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) 29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 29421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 29432abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 29451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 29461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 29481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 29491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_OPEN_LUN, 29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 29522abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create open unit request for " 29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s.\n", 29561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->port->wwpn, 29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29622abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 29631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 29641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29662abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.port_handle = erp_action->port->handle; 29672abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun; 2968aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE)) 29692abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->bottom.support.option = 297006506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann FSF_OPEN_LUN_SUPPRESS_BOXING; 29711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); 29722abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->unit; 29732abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 29742abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 29751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29762abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 29772abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(erp_action->fsf_req); 29781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 29791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an open unit request " 29801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s, port 0x%016Lx for " 29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx\n", 29821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 29841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun); 29852abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 29871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 29881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Open LUN request initiated (adapter %s, " 29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 29921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, erp_action->unit->fcp_lun); 29941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 29961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 29981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 30011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_unit_handler 30021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Open LUN command 30041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 30061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) 30091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 30101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 30111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 30141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_queue_designator *queue_designator; 30161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 3017aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin int exclusive, readwrite; 30181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3019059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 30201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 30221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change unit status in our bookkeeping */ 30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 30241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 30271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 30291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator = &header->fsf_status_qual.fsf_queue_designator; 30301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 3032b64ddf96456cde17be22bf74cafed381a29d58baHeiko Carstens ZFCP_STATUS_COMMON_ACCESS_BOXED | 30331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_UNIT_SHARED | 30341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_UNIT_READONLY, 30351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 30361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 30381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 30391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 30411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x " 30421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s invalid " 30431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally\n", 30441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 30451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 30461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 30471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 30481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 30501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_ph_nv"); 30511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 30521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_ALREADY_OPEN: 30561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Attempted to open unit 0x%016Lx on " 30571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port 0x%016Lx on adapter %s twice.\n", 30581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, 30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_uopen"); 30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 30661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot open unit 0x%016Lx on " 30671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port 0x%016Lx on adapter %s\n", 30681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 30691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 30701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 30711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 30721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 30731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 30741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 30751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 30761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 30771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 30781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 30791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 30801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 30841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 30851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); 30861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); 30871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 30911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 30921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 30931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 30941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); 3095d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 30961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 30971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 30981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_SHARING_VIOLATION: 31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (header->fsf_status_qual.word[0] != 0) { 31021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port " 31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "with WWPN 0x%Lx " 31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "connected to the adapter %s " 31051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is already in use in LPAR%d, CSS%d\n", 31061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 31071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 31081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 31091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator->hla, 31101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator->cssid); 31111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 31121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[4]; 31131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[5]; 31141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 31151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 31161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 31171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 31181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 31191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access to FCP-LUN 0x%Lx at the " 31201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port with WWPN 0x%Lx " 31211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "connected to the adapter %s " 31221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is denied (%s rule %d)\n", 31231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 31241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 31251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 31261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], 31271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule); 31281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 31321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 31331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 31341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 31351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, 31361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_l_sh_vio"); 31371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 31381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); 31391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); 31401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: 31441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: The adapter ran out of resources. " 31451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "There is no handle (temporary port identifier) " 31461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "available for unit 0x%016Lx on port 0x%016Lx " 31471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 31481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 31491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 31501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 31511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 31521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_max_units"); 31531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 31541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 31581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 31591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 31601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Re-establish link to port */ 31611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 31621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 316365a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 31641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 31671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 31681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 31691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 31701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 31731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 31741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 31751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 31761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, 31771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 31781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 31791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 31801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 31811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_INVALID_COMMAND_OPTION: 31851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 31861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Invalid option 0x%x has been specified " 31871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "in QTCB bottom sent to the adapter %s\n", 31881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option, 31891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 31901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 31921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 31951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save LUN handle assigned by FSF */ 31961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle = header->lun_handle; 31971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("unit 0x%016Lx on remote port 0x%016Lx on " 31981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s opened, port handle 0x%x\n", 31991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 32021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 32031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark unit as open */ 32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 3205aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 3206aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) && 3207aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) && 3208aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin (adapter->ccw_device->id.dev_model != ZFCP_DEVICE_MODEL_PRIV)) { 3209aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin exclusive = (bottom->lun_access_info & 3210aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_UNIT_ACCESS_EXCLUSIVE); 3211aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin readwrite = (bottom->lun_access_info & 3212aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_UNIT_ACCESS_OUTBOUND_TRANSFER); 3213aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 32141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!exclusive) 32151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, 32161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 32171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!readwrite) { 32191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, 32201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 32211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("read-only access for unit " 32221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, wwpn=0x%016Lx, " 32231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fcp_lun=0x%016Lx)\n", 32241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 32251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 32271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exclusive && !readwrite) { 32301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("exclusive access of read-only " 32311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit not supported\n"); 32321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 32331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_shutdown(unit, 0); 32351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!exclusive && readwrite) { 32361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("shared access of read-write " 32371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit not supported\n"); 32381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 32391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_shutdown(unit, 0); 32411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 32451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 32481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 32491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 32501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 32511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_s_inval:"); 32521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 32531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 32541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 32581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status); 32591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 32601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 32611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 32631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_unit 32641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 32661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of fsf_req - request successfully initiated 32681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - 32691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * assumptions: This routine does not check whether the associated 32711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remote port/lun has already been opened. This should be 32721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done by calling routines. Otherwise some status 32731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may be presented by FSF 32741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 32751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 32761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) 32771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 32781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 32792abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 32801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 32811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 32821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 32841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 32851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_LUN, 32861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 32871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 32882abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 32891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 32901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create close unit request for " 32911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s.\n", 32921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 32931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 32941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 32951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 32961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32982abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 32991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 33001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 33011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33022abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.port_handle = erp_action->port->handle; 33032abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; 33041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); 33052abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->unit; 33062abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 33072abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 33081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33092abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 33102abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(erp_action->fsf_req); 33111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 33121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send a close unit request for " 33131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx onadapter %s.\n", 33141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 33151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 33161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 33172abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 33181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 33191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 33201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Close LUN request initiated (adapter %s, " 33231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 33241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 33251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, erp_action->unit->fcp_lun); 33261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 33271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 33281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 33291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 33301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 33311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 33331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_unit_handler 33341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 33351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close LUN FSF command 33361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 33371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 33381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 33391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 33401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) 33411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 33421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 33431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 33441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3345059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 33461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 33481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change unit status in our bookkeeping */ 33491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 33501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 33531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 33541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 33561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 33571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may " 33581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "happen in rare circumstances\n", 33591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 33601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 33611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 33621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 33631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 33641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 33651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 33661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 33671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 33681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 33691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 33701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 33711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 33731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary LUN identifier 0x%x of unit " 33741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 33751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen occasionally.\n", 33761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 33771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 33781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 33791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 33801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Status qualifier data:\n"); 33811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 33821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 33831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 33841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 33851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv"); 33861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 33871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 33881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 33891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 33911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 33921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 33931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 33941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 33951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); 3396d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 33971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 33981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 33991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 34021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { 34031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 34041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* re-establish link to port */ 34051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 34061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 340765a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 34081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 34091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 34111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 34121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 34131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 34141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 34151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 34171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 34181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 34191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status_qual.word[0]); 34201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 34211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 34221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 34231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 34241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status_qual.word[0], 34251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 34261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 34311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("unit 0x%016Lx on port 0x%016Lx on adapter %s " 34321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "closed, port handle 0x%x\n", 34331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 34341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 34351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 34361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 34371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark unit as closed */ 34381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 34391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 34401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 34431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 34441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 34451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status); 34461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 34471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 34481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, 34491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 34501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 34541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &unit->status); 34551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 34561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 34571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 34591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) 34601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: adapter where scsi command is issued 34611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @unit: unit where command is sent to 34621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scsi_cmnd: scsi command to be sent 34631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @timer: timer to be started when request is initiated 34641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @req_flags: flags for fsf_request 34651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 34661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 34671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, 34681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit, 34691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_cmnd * scsi_cmnd, 34702abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann int use_timer, int req_flags) 34711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 34721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 34731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu; 34741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int sbtype; 34751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 34761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int real_bytes = 0; 34771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 34781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mask; 34791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 34811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, 34821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->pool.fsf_req_scsi, 34831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 34841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval < 0)) { 34851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: Could not create FCP command request " 34861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for unit 0x%016Lx on port 0x%016Lx on " 34871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 34881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 34891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 34901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 34911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req_create; 34921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3494059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_get(unit); 3495059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->unit = unit; 34961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3497059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann /* associate FSF request with SCSI request (for look up on abort) */ 34984eff4a36516d72e4f6ede901141214a7e05607e7Andreas Herrmann scsi_cmnd->host_scribble = (unsigned char *) fsf_req->req_id; 3499059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 3500059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann /* associate SCSI command with FSF request */ 3501059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) scsi_cmnd; 35021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handles of unit and its parent port in QTCB */ 35041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 35051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 35061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FSF does not define the structure of the FCP_CMND IU */ 35081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu = (struct fcp_cmnd_iu *) 35091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 35101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 35121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set depending on data direction: 35131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in SBALE (SB Type) 35141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in QTCB 35151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in FCP_CMND IU 35161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 35171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (scsi_cmnd->sc_data_direction) { 35181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_NONE: 35191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; 35201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 35211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(qdio): 35221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * what is the correct type for commands 35231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without 'real' data buffers? 35241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 35251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_READ; 35261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_FROM_DEVICE: 35281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ; 35291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_READ; 35301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->rddata = 1; 35311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_TO_DEVICE: 35331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE; 35341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_WRITE; 35351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->wddata = 1; 35361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_BIDIRECTIONAL: 35381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 35391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 35401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dummy, catch this condition earlier 35411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in zfcp_scsi_queuecommand 35421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 35431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_scsi_cmnd; 35441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 35451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FC service class in QTCB (3 per default) */ 354706506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; 35481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FCP_LUN in FCP_CMND IU in QTCB */ 35501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->fcp_lun = unit->fcp_lun; 35511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = ZFCP_STATUS_UNIT_READONLY | ZFCP_STATUS_UNIT_SHARED; 35531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set task attributes in FCP_CMND IU in QTCB */ 35551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely((scsi_cmnd->device->simple_tags) || 35561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (atomic_test_mask(mask, &unit->status)))) 35571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_attribute = SIMPLE_Q; 35581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 35591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_attribute = UNTAGGED; 35601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set additional length of FCP_CDB in FCP_CMND IU in QTCB, if needed */ 35621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH)) { 35631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length 35641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds = (scsi_cmnd->cmd_len - FCP_CDB_LENGTH) >> 2; 35651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("SCSI CDB length is 0x%x, " 35661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "additional FCP_CDB length is 0x%x " 35671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(shifted right 2 bits)\n", 35681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmnd->cmd_len, 35691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length); 35701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 35711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 35721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy SCSI CDB (including additional length, if any) to 35731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FCP_CDB in FCP_CMND IU in QTCB 35741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 35751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len); 35761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FCP CMND IU length in QTCB */ 35781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length = 35791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_cmnd_iu) + 35801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length + sizeof (fcp_dl_t); 35811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* generate SBALEs from data buffer */ 35831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds real_bytes = zfcp_qdio_sbals_from_scsicmnd(fsf_req, sbtype, scsi_cmnd); 35841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(real_bytes < 0)) { 35851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->sbal_number < ZFCP_MAX_SBALS_PER_REQ) { 35861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG( 35871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Data did not fit into available buffer(s), " 35881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "waiting for more...\n"); 35891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 35901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 35911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: No truncation implemented but " 35921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "required. Shutting down unit " 35931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx, " 35941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx)\n", 35951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 35961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 35971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 35981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_shutdown(unit, 0); 35991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 36001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 36011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_fit; 36021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 36031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set length of FCP data length in FCP_CMND IU in QTCB */ 36051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes); 36061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Sending SCSI command:\n"); 36081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 36091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) scsi_cmnd->cmnd, scsi_cmnd->cmd_len); 36101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36112abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann if (use_timer) 36122abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 36132abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 36142abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 36151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval < 0)) { 36161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send FCP command request " 36171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n", 36181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 36191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 36201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 36211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto send_failed; 36221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 36231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Send FCP Command initiated (adapter %s, " 36251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 36261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 36271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 36281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 36291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto success; 36301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_failed: 36321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds no_fit: 36331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_scsi_cmnd: 3634059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_put(unit); 36351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 36361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 36371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmnd->host_scribble = NULL; 36381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds success: 36391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req_create: 36401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 36411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 36421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 36431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct zfcp_fsf_req * 36451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, 36461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit, 36471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 tm_flags, int req_flags) 36481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 36491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 36501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 36511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu; 36521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 36531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 36541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 36561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, 36571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->pool.fsf_req_scsi, 36581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 36591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 36601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create FCP command (task " 36611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "management) request for adapter %s, port " 36621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " 0x%016Lx, unit 0x%016Lx.\n", 36631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 36641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, unit->fcp_lun); 36651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 36661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 36671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 36691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used to decide on proper handler in the return path, 36701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could be either zfcp_fsf_send_fcp_command_task_handler or 36711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_fcp_command_task_management_handler */ 36721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT; 36741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 36761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hold a pointer to the unit being target of this 36771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * task management request 36781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3679059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) unit; 36801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FSF related fields in QTCB */ 36821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 36831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 36841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; 368506506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; 36861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length = 36871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t); 36881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 36901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; 36911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 36921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FCP related fields in FCP_CMND IU in QTCB */ 36941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu = (struct fcp_cmnd_iu *) 36951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 36961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->fcp_lun = unit->fcp_lun; 36971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_management_flags = tm_flags; 36981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36992abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT); 37002abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 37011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 37021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an FCP-command (task " 37031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "management) on adapter %s, port 0x%016Lx for " 37041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit LUN 0x%016Lx\n", 37051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 37061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 37071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 37081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 37091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 37101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 37111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Send FCP Command (task management function) initiated " 37141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx, unit 0x%016Lx, " 37151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tm_flags=0x%x)\n", 37161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 37171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 37181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 37191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tm_flags); 37201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 37211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 37221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fsf_req; 37231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 37241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 37261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_handler 37271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 37281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Send FCP Command 37291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 37301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 37311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 37321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 37331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) 37341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 37351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 37361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 37371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 37381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 37391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 37411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) 3743059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 37441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3745059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = fsf_req->unit; 37461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 37481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* go directly to calls of special handlers */ 37491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 37501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 37531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 37541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 37561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 37571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid\n", 37581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 37591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 37601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 37611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 37621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 37631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 37641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 37651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 37661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 37671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 37701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary LUN identifier 0x%x for unit " 37711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 37721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen occasionally.\n", 37731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 37741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 37751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 37761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 37771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Status qualifier data:\n"); 37781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 37791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 37801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 37811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 37821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_uhand_nv"); 37831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 37841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 37851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_HANDLE_MISMATCH: 37881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The port handle 0x%x has changed " 37891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unexpectedly. (adapter %s, port 0x%016Lx, " 37901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx)\n", 37911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 37921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 37931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 37941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 37951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("status qualifier:\n"); 37961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 37971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 37981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 37991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 38001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_hand_mis"); 38011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 38021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 380606506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_LOG_INFO("error: adapter %s does not support fc " 380706506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann "class %d.\n", 380806506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann zfcp_get_busid_by_unit(unit), 380906506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT); 38101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 38111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 38121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_class_nsup"); 38131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 38141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCPLUN_NOT_VALID: 38181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: unit 0x%016Lx on port 0x%016Lx on " 38191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s does not have correct unit " 38201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "handle 0x%x\n", 38211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 38221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 38231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 38241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 38251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 38261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 38271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 38281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 38291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 38301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_fcp_lun_nv"); 38311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 38321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 38361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot send FCP command to " 38371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on " 38381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", unit->fcp_lun, unit->port->wwpn, 38391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 38401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 38411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 38421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 38431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 38441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 38451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 38461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 38471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 38481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 38491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 38501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 38541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 38551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_DIRECTION_INDICATOR_NOT_VALID: 38591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Invalid data direction given for unit " 38601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s " 38611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info %d)\n", 38621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 38631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 38641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 38651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction); 38661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 38671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 38681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_dir_ind_nv"); 38691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 38701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CMND_LENGTH_NOT_VALID: 38741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 38751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: An invalid control-data-block length field " 38761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was found in a command for unit 0x%016Lx on port " 38771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s " "(debug info %d)\n", 38781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 38791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 38801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length); 38811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 38821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 38831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_cmd_len_nv"); 38841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 38851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 38891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 38901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 38911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 38921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); 3893d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 38941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 38951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 38961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_BOXED: 38991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("unit needs to be reopened (adapter %s, " 39001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n", 39011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 39021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, unit->fcp_lun); 39031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); 3904d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_unit_boxed(unit); 39051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 39061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 39071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 39101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 39111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 39121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* re-establish link to port */ 39131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 39141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 391565a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 39161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 39181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME(hw) need proper specs for proper action */ 39191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* let scsi stack deal with retries and escalation */ 39201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 39211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 39221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 39241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 3925516a4201bacfd61ea957039d6f47276ee9c32a0dAndreas Herrmann ("Unknown status qualifier 0x%x arrived.\n", 39261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 39271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 39281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 39291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 39301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 39311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(u32)); 39321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3934516a4201bacfd61ea957039d6f47276ee9c32a0dAndreas Herrmann fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 39351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 39381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_RSP_AVAILABLE: 39411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 39441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 39451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 39461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof(u32)); 39471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 39511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) { 39521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 39531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_fcp_command_task_management_handler(fsf_req); 39541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 39551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req); 3956059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->unit = NULL; 3957059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_put(unit); 39581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 39601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 39611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 39631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_task_handler 39641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 39651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FCP_RSP IU 39661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 39671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 39681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 39691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 39701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) 39711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 39721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 39731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_cmnd *scpnt; 39741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) 39751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_rsp); 39761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu = (struct fcp_cmnd_iu *) 39771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 39781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 sns_len; 39791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); 39801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 3981059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit = fsf_req->unit; 39821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_lock_irqsave(&fsf_req->adapter->abort_lock, flags); 3984059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann scpnt = (struct scsi_cmnd *) fsf_req->data; 39851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(!scpnt)) { 39861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG 39871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("Command with fsf_req %p is not associated to " 39881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "a scsi command anymore. Aborted?\n", fsf_req); 39891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 39901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTED)) { 39921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME: (design) mid-layer should handle DID_ABORT like 39931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DID_SOFT_ERROR by retrying the request for devices 39941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that allow retries. 39951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 39961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Setting DID_SOFT_ERROR and SUGGEST_RETRY\n"); 39971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_SOFT_ERROR); 39981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_driver_byte(&scpnt->result, SUGGEST_RETRY); 39991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 40001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 40031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Setting DID_ERROR\n"); 40041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 40051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 40061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set message byte of result in SCSI command */ 40091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result |= COMMAND_COMPLETE << 8; 40101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 40121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy SCSI status code of FCP_STATUS of FCP_RSP IU to status byte 40131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of result in SCSI command 40141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 40151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result |= fcp_rsp_iu->scsi_status; 40161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->scsi_status)) { 40171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* DEBUG */ 40181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status for SCSI Command:\n"); 40191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 40201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->cmnd, scpnt->cmd_len); 40211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("SCSI status code 0x%x\n", 40221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->scsi_status); 40231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 40241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) fcp_rsp_iu, sizeof (struct fcp_rsp_iu)); 40251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 40261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), 40271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_sns_len); 40281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check FCP_RSP_INFO */ 40311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) { 40321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("rsp_len is valid\n"); 40331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fcp_rsp_info[3]) { 40341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_GOOD: 40351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ok, continue */ 40361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("no failure or Task Management " 40371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Function complete\n"); 40381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_OK); 40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_LENGTH_MISMATCH: 40411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* hardware bug */ 40421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: FCP response code indictates " 40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that the fibrechannel protocol data " 40441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "length differs from the burst length. " 40451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on unit 0x%016Lx " 40461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on port 0x%016Lx on adapter %s", 40471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 40481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 40491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 40511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 40521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 40531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 40541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 40551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 40561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_FIELD_INVALID: 40571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* driver or hardware bug */ 40581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: FCP response code indictates " 40591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that the fibrechannel protocol data " 40601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fields were incorrectly set up. " 40611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on the unit " 40621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on " 40631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s", 40641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 40651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 40661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 40671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 40681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 40691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 40701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 40711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 40721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 40731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_RO_MISMATCH: 40741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* hardware bug */ 40751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The FCP response code indicates " 40761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that conflicting values for the " 40771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fibrechannel payload offset from the " 40781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "header were found. " 40791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on unit 0x%016Lx " 40801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on port 0x%016Lx on adapter %s.\n", 40811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 40821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 40831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 40841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 40851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 40861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 40871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 40881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 40891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 40901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 40911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An invalid FCP response " 40921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "code was detected for a command. " 40931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on the unit " 40941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on " 40951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s (debug info 0x%x)\n", 40961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 40971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 40981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 40991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_info[3]); 41001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 41011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 41021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 41031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 41041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 41056f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> goto skip_fsfstatus; 41061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for sense data */ 41101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) { 41111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = FSF_FCP_RSP_SIZE - 41121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_rsp_iu) + fcp_rsp_iu->fcp_rsp_len; 41131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("room for %i bytes sense data in QTCB\n", 41141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len); 41151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE); 41161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("room for %i bytes sense data in SCSI command\n", 41171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_SENSE_BUFFERSIZE); 41181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len); 41191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n", 41201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result); 41211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 41221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) &scpnt->cmnd, scpnt->cmd_len); 41231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n", 41251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_sns_len); 41261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&scpnt->sense_buffer, 41271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len); 41281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 41291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) &scpnt->sense_buffer, sns_len); 41301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for overrun */ 41331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_over)) { 41341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("A data overrun was detected for a command. " 41351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s. " 41361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The response data length is " 41371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d, the original length was %d.\n", 41381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 41401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 41411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_resid, 41421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (int) zfcp_get_fcp_dl(fcp_cmnd_iu)); 41431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for underrun */ 41461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) { 41471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("A data underrun was detected for a command. " 41481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s. " 41491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The response data length is " 41501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d, the original length was %d.\n", 41511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 41531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 41541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_resid, 41551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (int) zfcp_get_fcp_dl(fcp_cmnd_iu)); 41561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->resid = fcp_rsp_iu->fcp_resid; 41581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (scpnt->request_bufflen - scpnt->resid < scpnt->underflow) 41596f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> set_host_byte(&scpnt->result, DID_ERROR); 41601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 41631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); 41641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41658a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (scpnt->result != 0) 4166ed829ad607a9c334cea490d3a8c0f874153fb42dMaxim Shchetynin zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req); 41678a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin else if (scpnt->retries > 0) 4168ed829ad607a9c334cea490d3a8c0f874153fb42dMaxim Shchetynin zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req); 41698a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin else 4170ed829ad607a9c334cea490d3a8c0f874153fb42dMaxim Shchetynin zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req); 41711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* cleanup pointer (need this especially for abort) */ 41731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->host_scribble = NULL; 41741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* always call back */ 41761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (scpnt->scsi_done) (scpnt); 41771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 41791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We must hold this lock until scsi_done has been called. 41801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise we may call scsi_done after abort regarding this 41811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command has completed. 41821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: scsi_done must not block! 41831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 41851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_unlock_irqrestore(&fsf_req->adapter->abort_lock, flags); 41861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 41871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 41881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 41901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_task_management_handler 41911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FCP_RSP IU 41931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 41951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 41971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req) 41981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 41991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 42001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) 42011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_rsp); 42021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); 4203059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data; 42041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 42061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 42071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 42081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check FCP_RSP_INFO */ 42111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fcp_rsp_info[3]) { 42121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_GOOD: 42131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ok, continue */ 42141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("no failure or Task Management " 42151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Function complete\n"); 42161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 42171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_TASKMAN_UNSUPP: 42181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: A reuested task management function " 42191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is not supported on the target device " 42201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s\n ", 42211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 42221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 42231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 42241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP; 42251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 42261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_TASKMAN_FAILED: 42271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: A reuested task management function " 42281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "failed to complete successfully. " 42291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s.\n", 42301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 42311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 42321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 42331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 42341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 42351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 42361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An invalid FCP response " 42371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "code was detected for a command. " 42381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s " 42391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 42401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 42411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 42421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 42431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_info[3]); 42441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 42451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 42481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 42491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 42501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 42531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_control_file 42541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 42551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Initiator of the control file upload/download FSF requests 42561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 42571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - FSF request is successfuly created and queued 42581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EOPNOTSUPP - The FCP adapter does not have Control File support 42591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - Invalid direction specified 42601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENOMEM - Insufficient memory 42611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EPERM - Cannot create FSF request or place it in QDIO queue 42621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 42631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 42641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_control_file(struct zfcp_adapter *adapter, 42651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req **fsf_req_ptr, 42661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 fsf_command, 42671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 option, 42681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_sg_list *sg_list) 42691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 42701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 42711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 42721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 42731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 42741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int req_flags = 0; 42751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int direction; 42761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 42771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4278aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) { 42791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", 42801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 42811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EOPNOTSUPP; 42821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 42831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_command) { 42861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_DOWNLOAD_CONTROL_FILE: 42881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds direction = SBAL_FLAGS0_TYPE_WRITE; 42891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((option != FSF_CFDC_OPTION_FULL_ACCESS) && 42901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (option != FSF_CFDC_OPTION_RESTRICTED_ACCESS)) 42911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_flags = ZFCP_WAIT_FOR_SBAL; 42921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 42931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_UPLOAD_CONTROL_FILE: 42951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds direction = SBAL_FLAGS0_TYPE_READ; 42961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 42971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 42991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Invalid FSF command code 0x%08x\n", fsf_command); 43001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 43011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 43021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags, 43051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, &lock_flags, &fsf_req); 43061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 43071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create FSF request for the " 43081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 43091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 43111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto unlock_queue_lock; 43121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 43151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= direction; 43161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 43181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; 43191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option = option; 43201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sg_list->count > 0) { 43221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 43231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, direction, 43251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sg_list->sg, sg_list->count, 43261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_REQ); 43271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes != ZFCP_CFDC_MAX_CONTROL_FILE_SIZE) { 43281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 43291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "error: Could not create sufficient number of " 43301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "SBALS for an FSF request to the adapter %s\n", 43311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -ENOMEM; 43331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto free_fsf_req; 43341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 43361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 43371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43382abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 43392abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 43401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 43411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("initiation of cfdc up/download failed" 43421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s)\n", 43431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 43451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto free_fsf_req; 43461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 43481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Control file %s FSF request has been sent to the " 43501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 43511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ? 43521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "download" : "upload", 43531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_event(fsf_req->completion_wq, 43561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 43571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fsf_req_ptr = fsf_req; 43592abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann goto out; 43601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_fsf_req: 43621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 43631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_queue_lock: 43641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 43651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 43661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 43671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 43681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 43711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_control_file_handler 43721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 43731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Handler of the control file upload/download FSF requests 43741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 43751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - FSF request successfuly processed 43761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EAGAIN - Operation has to be repeated because of a temporary problem 43771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EACCES - There is no permission to execute an operation 43781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EPERM - The control file is not in a right format 43791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO - There is a problem with the FCP adapter 43801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - Invalid operation 43811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EFAULT - User space memory I/O operation fault 43821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 43831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 43841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req) 43851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 43861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 43871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header = &fsf_req->qtcb->header; 43881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom = &fsf_req->qtcb->bottom.support; 43891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 43901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 43921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 43931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 43941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 43971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 43991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The FSF request has been successfully completed " 44011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s\n", 44021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_OPERATION_PARTIALLY_SUCCESSFUL: 44061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) { 44071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 44081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44096f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> case FSF_SQ_CFDC_HARDENED_ON_SE: 44106f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> ZFCP_LOG_NORMAL( 44116f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "CFDC on the adapter %s has being " 44126f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "hardened on primary and secondary SE\n", 44136f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> zfcp_get_busid_by_adapter(adapter)); 44146f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> break; 44156f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> 44161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE: 44171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC of the adapter %s could not " 44191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be saved on the SE\n", 44201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2: 44241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC of the adapter %s could not " 44261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be copied to the secondary SE\n", 44271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 44311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC could not be hardened " 44331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s\n", 44341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EAGAIN; 44391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_AUTHORIZATION_FAILURE: 44421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Adapter %s does not accept privileged commands\n", 44441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EACCES; 44471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CFDC_ERROR_DETECTED: 44501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Error at position %d in the CFDC, " 44521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC is discarded by the adapter %s\n", 44531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0], 44541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 44571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONTROL_FILE_UPDATE_ERROR: 44601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Adapter %s cannot harden the control file, " 44621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "file is discarded\n", 44631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 44661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONTROL_FILE_TOO_LARGE: 44691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Control file is too large, file is discarded " 44711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "by the adapter %s\n", 44721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 44751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_CONFLICT_DETECTED: 44781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) 44791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC has been discarded by the adapter %s, " 44811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "because activation would impact " 44821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d active connection(s)\n", 44831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 44841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 44851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 44871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONFLICTS_OVERRULED: 44901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) 44911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC has been activated on the adapter %s, " 44931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "but activation has impacted " 44941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d active connection(s)\n", 44951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 44961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 44971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 44991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_OP_SUBTYPE: 45021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("unknown operation subtype (adapter: %s, " 45031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "op_subtype=0x%x)\n", 45041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 45051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->operation_subtype); 45061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 45081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_INVALID_COMMAND_OPTION: 45111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Invalid option 0x%x has been specified " 45131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "in QTCB bottom sent to the adapter %s\n", 45141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option, 45151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 45181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 45211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bug: An unknown/unexpected FSF status 0x%08x " 45231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was presented on the adapter %s\n", 45241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status, 45251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval"); 45271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 45281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof(u32)); 45291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 45311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 45351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 45361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 45371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 45391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_sbal_check(unsigned long *flags, 45401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *queue, int needed) 45411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 45421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_lock_irqsave(&queue->queue_lock, *flags); 45431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(atomic_read(&queue->free_count) >= needed)) 45441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 45451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&queue->queue_lock, *flags); 45461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 45471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 45481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 45501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set qtcb pointer in fsf_req and initialize QTCB 45511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 45524d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic void 45538a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetyninzfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) 45541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 45551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->qtcb != NULL)) { 4556fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->qtcb->prefix.req_seq_no = 4557fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->adapter->fsf_req_seq_no; 4558fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->qtcb->prefix.req_id = fsf_req->req_id; 45591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; 4560fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->qtcb->prefix.qtcb_type = 4561fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_qtcb_type[fsf_req->fsf_command]; 45621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; 4563fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->qtcb->header.req_handle = fsf_req->req_id; 45648a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; 45651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 45671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 45691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_req_sbal_get - try to get one SBAL in the request queue 45701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: adapter for which request queue is examined 45711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @req_flags: flags indicating whether to wait for needed SBAL or not 45721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @lock_flags: lock_flags if queue_lock is taken 45731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return: 0 on success, otherwise -EIO, or -ERESTARTSYS 45741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Locks: lock adapter->request_queue->queue_lock on success 45751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 45761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 45771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags, 45781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *lock_flags) 45791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 45801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long ret; 45811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue = &adapter->request_queue; 45821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) { 45841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = wait_event_interruptible_timeout(adapter->request_wq, 45851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1), 45861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_SBAL_TIMEOUT); 45871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 45881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 45891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) 45901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 45911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1)) 45921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 45931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 45951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 45961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 45981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_create 45991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 46001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: create an FSF request at the specified adapter and 46011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * setup common fields 46021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 46031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: -ENOMEM if there was insufficient memory for a request 46041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO if no qdio buffers could be allocate to the request 46051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL/-EPERM on bug conditions in req_dequeue 46061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 in success 46071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 46081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * note: The created request is returned by reference. 46091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 46101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: lock of concerned request queue must not be held, 46111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but is held on completion (write, irqsave) 46121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 46131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 46141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, 46151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_t *pool, unsigned long *lock_flags, 46161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req **fsf_req_p) 46171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 46181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 46191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 46201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 46211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue = &adapter->request_queue; 46221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate new FSF request */ 46241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = zfcp_fsf_req_alloc(pool, req_flags); 46251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(NULL == fsf_req)) { 46261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: Could not put an FSF request into" 46271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the outbound (send) queue.\n"); 46281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 46291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_fsf_req; 46301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 46311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46328a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->adapter = adapter; 46338a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->fsf_command = fsf_cmd; 4634fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske INIT_LIST_HEAD(&fsf_req->list); 46352abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann init_timer(&fsf_req->timer); 46361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* initialize waitqueue which may be used to wait on 46381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this request completion */ 46391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&fsf_req->completion_wq); 46401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_sbal_get(adapter, req_flags, lock_flags); 4642801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt if (ret < 0) 46431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_sbals; 4644801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt 4645801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt /* this is serialized (we are holding req_queue-lock of adapter) */ 4646801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt if (adapter->req_no == 0) 4647801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt adapter->req_no++; 4648801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt fsf_req->req_id = adapter->req_no++; 4649801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt 4650801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt zfcp_fsf_req_qtcb_init(fsf_req); 46511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 46531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We hold queue_lock here. Check if QDIOUP is set and let request fail 46541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if it is not set (see also *_open_qdio and *_close_qdio). 46551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 46561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) { 46581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&req_queue->queue_lock, *lock_flags); 46591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EIO; 46601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_sbals; 46611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 46621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46638a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (fsf_req->qtcb) { 46648a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->seq_no = adapter->fsf_req_seq_no; 46658a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; 46668a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin } 46671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_number = 1; 46681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_first = req_queue->free_index; 46691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_curr = req_queue->free_index; 46701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = 1; 46711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP)) { 46731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 46741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 46751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 46771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup common SBALE fields */ 4679fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske sbale[0].addr = (void *) fsf_req->req_id; 46801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_COMMAND; 46811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->qtcb != NULL)) { 46821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].addr = (void *) fsf_req->qtcb; 46831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].length = sizeof(struct fsf_qtcb); 46841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 46851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("got %i free BUFFERs starting at index %i\n", 46871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_number, fsf_req->sbal_first); 46881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto success; 46901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_sbals: 46921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* dequeue new FSF request previously enqueued */ 46931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 46941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 46951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_fsf_req: 46971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_lock_irqsave(&req_queue->queue_lock, *lock_flags); 46981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds success: 46991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fsf_req_p = fsf_req; 47001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 47011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 47021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 47041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_send 47051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 47061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: start transfer of FSF request via QDIO 47071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 47081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - request transfer succesfully started 47091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * !0 - start of request transfer failed 47101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 47112abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmannstatic int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req) 47121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 47131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 47141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue; 47151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 47168a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin int inc_seq_no; 47171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int new_distance_from_int; 4718fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske u64 dbg_tmp[2]; 47191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 47201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 47221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue = &adapter->request_queue, 47231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME(debug): remove it later */ 47261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_first, 0); 47271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("SBALE0 flags=0x%x\n", sbale[0].flags); 47281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("HEX DUMP OF SBALE1 PAYLOAD:\n"); 47291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, 47301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].length); 47311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4732fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske /* put allocated FSF request into hash table */ 4733fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_lock(&adapter->req_list_lock); 4734fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske zfcp_reqlist_add(adapter, fsf_req); 4735fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_unlock(&adapter->req_list_lock); 47361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47378a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin inc_seq_no = (fsf_req->qtcb != NULL); 47388a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 47391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("request queue of adapter %s: " 47401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "next free SBAL is %i, %i free SBALs\n", 47411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 47421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index, 47431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&req_queue->free_count)); 47441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("calling do_QDIO adapter %s, flags=0x%x, queue_no=%i, " 47461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "index_in_queue=%i, count=%i, buffers=%p\n", 47471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 47481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QDIO_FLAG_SYNC_OUTPUT, 47491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, fsf_req->sbal_first, fsf_req->sbal_number, 47501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &req_queue->buffer[fsf_req->sbal_first]); 47511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 47531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adjust the number of free SBALs in request queue as well as 47541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * position of first one 47551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 47561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_sub(fsf_req->sbal_number, &req_queue->free_count); 47571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("free_count=%d\n", atomic_read(&req_queue->free_count)); 47581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index += fsf_req->sbal_number; /* increase */ 47591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap if needed */ 47601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req); 47611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47628a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->issued = get_clock(); 47638a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 47641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = do_QDIO(adapter->ccw_device, 47651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QDIO_FLAG_SYNC_OUTPUT, 47661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); 47671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4768fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske dbg_tmp[0] = (unsigned long) sbale[0].addr; 4769fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske dbg_tmp[1] = (u64) retval; 4770fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); 4771fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske 47721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval)) { 47731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Queues are down..... */ 47741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 47752abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann del_timer(&fsf_req->timer); 4776fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_lock(&adapter->req_list_lock); 4777ca2d02c2f9ea476062ae181eec60b8bcd97857d6Heiko Carstens zfcp_reqlist_remove(adapter, fsf_req); 4778fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_unlock(&adapter->req_list_lock); 4779fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske /* undo changes in request queue made for this request */ 47801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_qdio_zero_sbals(req_queue->buffer, 47811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_first, fsf_req->sbal_number); 47821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_add(fsf_req->sbal_number, &req_queue->free_count); 4783fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske req_queue->free_index -= fsf_req->sbal_number; 47841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q; 47851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ 4786fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske zfcp_erp_adapter_reopen(adapter, 0); 47871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 47881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->distance_from_int = new_distance_from_int; 47891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 47901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * increase FSF sequence counter - 47911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this must only be done for request successfully enqueued to 47921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * QDIO this rejected requests may be cleaned up by calling 47931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routines resulting in missing sequence counter values 47941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * otherwise, 47951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 47968a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 47971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't increase for unsolicited status */ 47988a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (inc_seq_no) 47991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fsf_req_seq_no++; 48008a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 48011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* count FSF requests pending */ 4802fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske atomic_inc(&adapter->reqs_active); 48031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 48041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 48051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 48061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef ZFCP_LOG_AREA 4808