zfcp_fsf.c revision 3f0ca62add34010241db682e63bb68ba765bf4a9
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 * 8341fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * 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. 8641fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * 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 * 19541fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * 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 /* 21741fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * fsf_req may be deleted due to waking up functions, so 21841fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * 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 * 26241fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * returns: 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 26441fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * 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 * 64141fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * 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 * 85741fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * 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 * 109141fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * 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 1119951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt if (unlikely(!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, 1120951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt &unit->status))) 1121951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt goto unit_blocked; 1122951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1127059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) unit; 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handles of unit and its parent port in QTCB */ 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handle of request which should be aborted */ 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id; 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11362abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT); 11372abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 1138951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt if (!retval) 1139951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt goto out; 1140951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt 1141951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt unit_blocked: 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fsf_req; 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_abort_fcp_command_handler 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Abort FCP Command request 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 115541fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * returns: 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 1161059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit; 11628627533c115c546649693d68fed6a74762c47d51Christof Schmitt union fsf_status_qual *fsf_stat_qual = 11638627533c115c546649693d68fed6a74762c47d51Christof Schmitt &new_fsf_req->qtcb->header.fsf_status_qual; 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */ 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1170059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) new_fsf_req->data; 1171059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (new_fsf_req->qtcb->header.fsf_status) { 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 11768627533c115c546649693d68fed6a74762c47d51Christof Schmitt if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) { 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv0"); 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * In this case a command that was sent prior to a port 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reopen was aborted (handles are different). This is 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fine. 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for " 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s invalid. " 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally.\n", 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &new_fsf_req->qtcb->header. 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual, 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Let's hope this sorts out the mess */ 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv1"); 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 12058627533c115c546649693d68fed6a74762c47d51Christof Schmitt if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) { 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv0"); 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * In this case a command that was sent prior to a unit 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reopen was aborted (handles are different). 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is fine. 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("Warning: Temporary LUN identifier 0x%x of LUN " 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen in rare cases. " 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Trying to re-establish link.\n", 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Status qualifier data:\n"); 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &new_fsf_req->qtcb->header. 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual, 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Let's hope this sorts out the mess */ 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv1"); 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_COMMAND_DOES_NOT_EXIST: 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_no_exist"); 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to " 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be reopened\n", unit->port->wwpn, 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 2, 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_pboxed"); 1249d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_BOXED: 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s needs " 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to be reopened\n", 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); 1261d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_unit_boxed(unit); 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) { 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 127165a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SCSI stack will escalate */ 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->qtcb->header.fsf_status_qual.word[0]); 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 0, 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(new_fsf_req->adapter->erp_dbf, 0, 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &new_fsf_req->qtcb->header. 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual.word[0], sizeof (u32)); 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED; 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->qtcb->header.fsf_status); 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 0, 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_inval:"); 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(new_fsf_req->adapter->erp_dbf, 0, 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &new_fsf_req->qtcb->header.fsf_status, 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_use_one_sbal - checks whether req buffer and resp bother each fit into 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one SBALE 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Two scatter-gather lists are passed, one for the reqeust and one for the 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response. 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_use_one_sbal(struct scatterlist *req, int req_count, 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scatterlist *resp, int resp_count) 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((req_count == 1) && 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (resp_count == 1) && 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (((unsigned long) zfcp_sg_to_address(&req[0]) & 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAGE_MASK) == 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((unsigned long) (zfcp_sg_to_address(&req[0]) + 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req[0].length - 1) & PAGE_MASK)) && 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (((unsigned long) zfcp_sg_to_address(&resp[0]) & 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAGE_MASK) == 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((unsigned long) (zfcp_sg_to_address(&resp[0]) + 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resp[0].length - 1) & PAGE_MASK))); 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS) 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ct: pointer to struct zfcp_send_ct which conatins all needed data for 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the request 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: pointer to memory pool, if non-null this pool is used to allocate 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a struct zfcp_fsf_req 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @erp_action: pointer to erp_action, if non-null the Generic Service request 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is sent within error recovery 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_erp_action *erp_action) 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = ct->port; 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = port->adapter; 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC, 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool, &lock_flags, &fsf_req); 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create CT request (FC-GS) for " 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter: %s\n", 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req; 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_use_one_sbal(ct->req, ct->req_count, 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->resp, ct->resp_count)){ 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* both request buffer and response buffer 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fit into one sbale each */ 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].addr = zfcp_sg_to_address(&ct->req[0]); 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].length = ct->req[0].length; 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].length = ct->resp[0].length; 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; 1380aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin } else if (adapter->adapter_features & 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_FEATURE_ELS_CT_CHAINED_SBALS) { 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try to use chained SBALs */ 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->req, ct->req_count, 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_CT_REQ); 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of CT request failed " 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.req_buf_length = bytes; 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->resp, ct->resp_count, 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_CT_REQ); 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of CT request failed " 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.resp_buf_length = bytes; 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reject send generic request */ 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "error: microcode does not support chained SBALs," 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CT request too big (adapter %s)\n", 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EOPNOTSUPP; 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* settings in QTCB */ 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = port->handle; 142806506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann fsf_req->qtcb->bottom.support.service_class = 142906506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT; 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.timeout = ct->timeout; 1431059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) ct; 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14338a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_ct_request(fsf_req); 14348a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 14352abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann if (erp_action) { 14362abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 14372abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 14382abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 14392abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann } else 14402abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 14412abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 14422abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann ret = zfcp_fsf_req_send(fsf_req); 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: initiation of CT request failed " 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), port->wwpn); 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("CT request initiated (adapter %s, port 0x%016Lx)\n", 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), port->wwpn); 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_send: 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (erp_action != NULL) { 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req: 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_ct_handler - handler for Generic Service requests 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1470059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Data specific for the Generic Service request is passed using 1471059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * fsf_req->data. There we find the pointer to struct zfcp_send_ct. 1472059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Usually a specific handler for the CT request is called which is 1473059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * found in this structure. 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_send_ct *send_ct; 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 1487059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann send_ct = (struct zfcp_send_ct *) fsf_req->data; 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = send_ct->port; 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 14998a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_ct_response(fsf_req); 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 150406506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_LOG_INFO("error: adapter %s does not support fc " 150506506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann "class %d.\n", 150606506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann zfcp_get_busid_by_port(port), 150706506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT); 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]){ 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reopening link to port */ 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_test_link(port); 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x " 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "arrived.\n", 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("access denied, cannot send generic service " 15371d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "command (adapter %s, port d_id=0x%06x)\n", 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GENERIC_COMMAND_REJECTED: 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("generic service command rejected " 15591d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id=0x%06x)\n", 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej"); 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Temporary port identifier 0x%x for port " 15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may " 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "happen occasionally.\n", port->handle, 15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv"); 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("port needs to be reopened " 15851d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id=0x%06x)\n", 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); 1588d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(port); 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* following states should never occure, all cases avoided 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in zfcp_fsf_send_ct - but who knows ... */ 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PAYLOAD_SIZE_MISMATCH: 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("payload size mismatch (adapter: %s, " 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "req_buf_length=%d, resp_buf_length=%d)\n", 15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_REQUEST_SIZE_TOO_LARGE: 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("request size too large (adapter: %s, " 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "req_buf_length=%d)\n", 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length); 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_RESPONSE_SIZE_TOO_LARGE: 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("response size too large (adapter: %s, " 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SBAL_MISMATCH: 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, " 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", header->fsf_status); 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:"); 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof (u32)); 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_ct->status = retval; 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (send_ct->handler != NULL) 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_ct->handler(send_ct->handler_data); 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_els - initiate an ELS command (FC-FS) 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @els: pointer to struct zfcp_send_els which contains all needed data for 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the command. 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_els(struct zfcp_send_els *els) 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 165213e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann u32 d_id; 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d_id = els->d_id; 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = els->adapter; 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_REQ_AUTO_CLEANUP, 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, &lock_flags, &fsf_req); 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of ELS request failed " 16661d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id: 0x%06x)\n", 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req; 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16713f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt if (unlikely(!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, 16723f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt &els->port->status))) { 16733f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt ret = -EBUSY; 16743f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt goto port_blocked; 16753f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt } 16763f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt 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 17583f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt port_blocked: 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_send: 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req: 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_els_handler - handler for ELS commands 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1774059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Data specific for the ELS command is passed using 1775059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * fsf_req->data. There we find the pointer to struct zfcp_send_els. 1776059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Usually a specific handler for the ELS command is called which is 1777059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * found in this structure. 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 178313e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann u32 d_id; 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_send_els *send_els; 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1790059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann send_els = (struct zfcp_send_els *) fsf_req->data; 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = send_els->adapter; 179264b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann port = send_els->port; 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d_id = send_els->d_id; 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 18038a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_els_response(fsf_req); 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 180806506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_LOG_INFO("error: adapter %s does not support fc " 180906506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann "class %d.\n", 181006506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann zfcp_get_busid_by_adapter(adapter), 181106506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT); 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]){ 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); 182264b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann if (port && (send_els->ls_code != ZFCP_LS_ADISC)) 182364b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann zfcp_test_link(port); 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_handle_els_rjt(header->fsf_status_qual.word[1], 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (struct zfcp_ls_rjt_par *) 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[2]); 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_RETRY_IF_POSSIBLE: 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry"); 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x\n", 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char*)header->fsf_status_qual.word, 16); 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ELS_COMMAND_REJECTED: 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("ELS has been rejected because command filter " 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "prohibited sending " 18491d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter: %s, port d_id: 0x%06x)\n", 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PAYLOAD_SIZE_MISMATCH: 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ELS request size and ELS response size must be either " 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "both 0, or both greater than 0 " 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, req_buf_length=%d resp_buf_length=%d)\n", 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_REQUEST_SIZE_TOO_LARGE: 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Length of the ELS request buffer, " 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "specified in QTCB bottom, " 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "exceeds the size of the buffers " 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that have been allocated for ELS request data " 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, req_buf_length=%d)\n", 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length); 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_RESPONSE_SIZE_TOO_LARGE: 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Length of the ELS response buffer, " 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "specified in QTCB bottom, " 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "exceeds the size of the buffers " 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that have been allocated for ELS response data " 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, resp_buf_length=%d)\n", 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SBAL_MISMATCH: 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* should never occure, avoided in zfcp_fsf_send_els */ 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, " 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("access denied, cannot send ELS command " 18971d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "(adapter %s, port d_id=0x%06x)\n", 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port != NULL) 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bug: An unknown FSF Status was presented " 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, fsf_status=0x%08x)\n", 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval"); 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof(u32)); 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_els->status = retval; 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1934aa551daf5cc6fb6c6e09bb993737f9cd46dc7145Heiko Carstens if (send_els->handler) 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_els->handler(send_els->handler_data); 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) 19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 19442abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 194552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig struct zfcp_adapter *adapter = erp_action->adapter; 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 194752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig int retval; 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 195052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig retval = zfcp_fsf_req_create(adapter, 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_EXCHANGE_CONFIG_DATA, 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_REQ_AUTO_CLEANUP, 195352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig adapter->pool.fsf_req_erp, 19542abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 195552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (retval) { 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create exchange configuration " 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "data request for adapter %s.\n", 195852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 195952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig write_unlock_irqrestore(&adapter->request_queue.queue_lock, 196052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig lock_flags); 196152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return retval; 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19642abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 196552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 196652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19682abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->bottom.config.feature_selection = 1969aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_CFDC | 1970aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_LUN_SHARING | 19719eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_FEATURE_NOTIFICATION_LOST | 1972aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_UPDATE_ALERT; 19732abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 19742abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19762abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 19772abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 197852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig write_unlock_irqrestore(&adapter->request_queue.queue_lock, 197952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig lock_flags); 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 198152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_INFO("error: Could not send exchange configuration " 198252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "data command on the adapter %s\n", 198352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 19842abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 198752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig else 198852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_DEBUG("exchange configuration data request initiated " 198952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "(adapter %s)\n", 199052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 199252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return retval; 199352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig} 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 199552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schilligint 199652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schilligzfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, 199752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig struct fsf_qtcb_bottom_config *data) 199852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{ 199952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig volatile struct qdio_buffer_element *sbale; 200052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig struct zfcp_fsf_req *fsf_req; 200152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig unsigned long lock_flags; 200252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig int retval; 200352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 200452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig /* setup new FSF request */ 200552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, 200652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 0, NULL, &lock_flags, &fsf_req); 200752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (retval) { 200852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_INFO("error: Could not create exchange configuration " 200952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "data request for adapter %s.\n", 201052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 201152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig write_unlock_irqrestore(&adapter->request_queue.queue_lock, 201252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig lock_flags); 201352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return retval; 201452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig } 201552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 201652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 201752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 201852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 201952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 202052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig fsf_req->qtcb->bottom.config.feature_selection = 202152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FSF_FEATURE_CFDC | 202252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FSF_FEATURE_LUN_SHARING | 202352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FSF_FEATURE_NOTIFICATION_LOST | 202452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FSF_FEATURE_UPDATE_ALERT; 202552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 202652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (data) 202752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig fsf_req->data = (unsigned long) data; 202852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 202952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 203052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig retval = zfcp_fsf_req_send(fsf_req); 203152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig write_unlock_irqrestore(&adapter->request_queue.queue_lock, 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 203352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (retval) 203452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_INFO("error: Could not send exchange configuration " 203552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "data command on the adapter %s\n", 203652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 203752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig else 203852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig wait_event(fsf_req->completion_wq, 203952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 204052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 204152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_fsf_req_free(fsf_req); 204252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_config_evaluate 20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: fsf_req which belongs to xchg config data request 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @xchg_ok: specifies if xchg config data was incomplete or complete (0/1) 20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: -EIO on error, 0 otherwise 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_config *bottom; 20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 205813e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann struct Scsi_Host *shost = adapter->scsi_host; 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.config; 20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", 20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->low_qtcb_version, bottom->high_qtcb_version); 20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fsf_lic_version = bottom->lic_version; 2064aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin adapter->adapter_features = bottom->adapter_features; 2065aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin adapter->connection_features = bottom->connection_features; 20666f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwpn = 0; 20676f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwnn = 0; 20686f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_d_id = 0; 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (xchg_ok) { 207152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 207252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (fsf_req->data) 207352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig memcpy((struct fsf_qtcb_bottom_config *) fsf_req->data, 207452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig bottom, sizeof (struct fsf_qtcb_bottom_config)); 207552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 207613e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_node_name(shost) = bottom->nport_serv_param.wwnn; 207713e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_name(shost) = bottom->nport_serv_param.wwpn; 207813e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; 207913e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_speed(shost) = bottom->fc_link_speed; 208052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig fc_host_supported_classes(shost) = 208152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FC_COS_CLASS2 | FC_COS_CLASS3; 20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hydra_version = bottom->adapter_type; 2083ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann if (fc_host_permanent_port_name(shost) == -1) 2084ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_permanent_port_name(shost) = 2085ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_name(shost); 2086ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann if (bottom->fc_topology == FSF_TOPO_P2P) { 2087ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; 2088ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann adapter->peer_wwpn = bottom->plogi_payload.wwpn; 2089ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann adapter->peer_wwnn = bottom->plogi_payload.wwnn; 2090ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_PTP; 2091ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann } else if (bottom->fc_topology == FSF_TOPO_FABRIC) 2092ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_NPORT; 2093ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann else if (bottom->fc_topology == FSF_TOPO_AL) 2094ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; 2095ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann else 2096ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 209813e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_node_name(shost) = 0; 209913e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_name(shost) = 0; 210013e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_id(shost) = 0; 210113e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 2102ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; 21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hydra_version = 0; 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2106aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hardware_version = bottom->hardware_version; 210813e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann memcpy(fc_host_serial_number(shost), bottom->serial_number, 210913e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann min(FC_SERIAL_NUMBER_SIZE, 17)); 211013e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann EBCASC(fc_host_serial_number(shost), 211113e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann min(FC_SERIAL_NUMBER_SIZE, 17)); 21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_NORMAL("The adapter %s reported the following " 211552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "characteristics:\n" 211613e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "WWNN 0x%016Lx, " 211713e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "WWPN 0x%016Lx, " 21181d589edf9eeb60c9c8e62753d05cf4c8e094e5a7Christof Schmitt "S_ID 0x%06x,\n" 211913e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "adapter version 0x%x, " 212013e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "LIC version 0x%x, " 212113e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann "FC link speed %d Gb/s\n", 212213e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann zfcp_get_busid_by_adapter(adapter), 212313e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann (wwn_t) fc_host_node_name(shost), 212413e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann (wwn_t) fc_host_port_name(shost), 212513e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_port_id(shost), 212613e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann adapter->hydra_version, 212713e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann adapter->fsf_lic_version, 212813e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann fc_host_speed(shost)); 21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) { 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: the adapter %s " 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "only supports newer control block " 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "versions in comparison to this device " 21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "driver (try updated device driver)\n", 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "low_qtcb_ver"); 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ZFCP_QTCB_VERSION > bottom->high_qtcb_version) { 21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: the adapter %s " 21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "only supports older control block " 21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "versions than this device driver uses" 21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(consider a microcode upgrade)\n", 21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "high_qtcb_ver"); 21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 215252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig/** 21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_exchange_config_data_handler 21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Exchange Configuration Data command 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) 21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_config *bottom; 21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 2164aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin struct fsf_qtcb *qtcb = fsf_req->qtcb; 21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2169aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin switch (qtcb->header.fsf_status) { 21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) 21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2175ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann switch (fc_host_port_type(adapter->scsi_host)) { 2176ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann case FC_PORTTYPE_PTP: 21776f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> ZFCP_LOG_NORMAL("Point-to-Point fibrechannel " 21786f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "configuration detected at adapter %s\n" 21796f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "Peer WWNN 0x%016llx, " 21806f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "peer WWPN 0x%016llx, " 21816f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "peer d_id 0x%06x\n", 21826f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> zfcp_get_busid_by_adapter(adapter), 21836f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwnn, 21846f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwpn, 21856f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_d_id); 21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 218752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "top-p-to-p"); 21886f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> break; 2189ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann case FC_PORTTYPE_NLPORT: 21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel " 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "topology detected at adapter %s " 21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unsupported, shutting down adapter\n", 21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "top-al"); 21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 2198ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann case FC_PORTTYPE_NPORT: 2199aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin ZFCP_LOG_NORMAL("Switched fabric fibrechannel " 220052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "network detected at adapter %s.\n", 220152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The fibrechannel topology " 22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "reported by the exchange " 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "configuration command for " 22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the adapter %s is not " 22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "of a type known to the zfcp " 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "driver, shutting down adapter\n", 22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unknown-topo"); 22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2216aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin bottom = &qtcb->bottom.config; 22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " 22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "allowed by the adapter %s " 22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is lower than the minimum " 22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "required by the driver (%ld bytes).\n", 22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->max_qtcb_size, 22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct fsf_qtcb)); 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "qtcb-size"); 22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_event(fsf_req->adapter->erp_dbf, 0, 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &bottom->max_qtcb_size, sizeof (u32)); 22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, 22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &adapter->status); 22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: 22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "xchg-inco"); 22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) 22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 224152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, 224252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig &adapter->status); 2243aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 2244aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, 2245aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin &qtcb->header.fsf_status_qual.link_down_info); 22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); 22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_event(fsf_req->adapter->erp_dbf, 0, 225052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig &fsf_req->qtcb->header.fsf_status, sizeof(u32)); 22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data - request information about local port 2259aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin * @erp_action: ERP action for the adapter for which port data is requested 22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 226252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schilligzfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) 22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 226552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig struct zfcp_fsf_req *fsf_req; 226652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig struct zfcp_adapter *adapter = erp_action->adapter; 22672abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann unsigned long lock_flags; 226852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig int retval; 22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2270aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { 22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: exchange port data " 227252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "command not supported by adapter %s\n", 22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 227452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return -EOPNOTSUPP; 227552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig } 22761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 227952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_REQ_AUTO_CLEANUP, 228052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig adapter->pool.fsf_req_erp, 228152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig &lock_flags, &fsf_req); 228252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (retval) { 22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Out of resources. Could not create an " 228452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "exchange port data request for" 228552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "the adapter %s.\n", 22861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 22881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 22892448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann return retval; 2290aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin } 2291aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 229352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 229452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 229652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig erp_action->fsf_req = fsf_req; 229752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig fsf_req->erp_action = erp_action; 229852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_erp_start_timer(fsf_req); 22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23002abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 230152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 230252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an exchange port data " 230552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "command on the adapter %s\n", 23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 230852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig erp_action->fsf_req = NULL; 230952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig } 231052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig else 231152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_DEBUG("exchange port data request initiated " 231252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "(adapter %s)\n", 231352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 231452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return retval; 231552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig} 231652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 231752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 231852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig/** 231952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig * zfcp_fsf_exchange_port_data_sync - request information about local port 232052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig * and wait until information is ready 232152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig */ 232252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schilligint 232352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schilligzfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, 232452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig struct fsf_qtcb_bottom_port *data) 232552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{ 232652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig volatile struct qdio_buffer_element *sbale; 232752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig struct zfcp_fsf_req *fsf_req; 232852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig unsigned long lock_flags; 232952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig int retval; 233052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 233152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { 233252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_INFO("error: exchange port data " 233352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "command not supported by adapter %s\n", 233452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 233552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return -EOPNOTSUPP; 233652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig } 233752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 233852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig /* setup new FSF request */ 233952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 234052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 0, NULL, &lock_flags, &fsf_req); 234152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (retval) { 234252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_INFO("error: Out of resources. Could not create an " 234352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "exchange port data request for" 234452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "the adapter %s.\n", 234552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 23482448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann return retval; 23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 235152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (data) 235252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig fsf_req->data = (unsigned long) data; 235352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 235452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 235552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 235652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 235752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 235852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 235952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig retval = zfcp_fsf_req_send(fsf_req); 23602448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 236252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (retval) 236352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig ZFCP_LOG_INFO("error: Could not send an exchange port data " 236452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig "command on the adapter %s\n", 236552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_get_busid_by_adapter(adapter)); 236652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig else 23672448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann wait_event(fsf_req->completion_wq, 23682448c45965870ca9cfdb66388b4fcc93f1e12bb7Andreas Herrmann fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 236952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 237052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig zfcp_fsf_req_free(fsf_req); 237152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23752f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann/** 23762f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann * zfcp_fsf_exchange_port_evaluate 23772f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann * @fsf_req: fsf_req which belongs to xchg port data request 23782f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann * @xchg_ok: specifies if xchg port data was incomplete or complete (0/1) 23792f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann */ 23802f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmannstatic void 23812f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmannzfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) 23822f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann{ 23832f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct zfcp_adapter *adapter; 238452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig struct fsf_qtcb_bottom_port *bottom; 23852f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct Scsi_Host *shost; 23862f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann 23872f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann adapter = fsf_req->adapter; 238852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig bottom = &fsf_req->qtcb->bottom.port; 23892f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann shost = adapter->scsi_host; 23902f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann 239152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (fsf_req->data) 239252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig memcpy((struct fsf_qtcb_bottom_port*) fsf_req->data, bottom, 239352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig sizeof(struct fsf_qtcb_bottom_port)); 23942f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann 23952f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) 23962f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann fc_host_permanent_port_name(shost) = bottom->wwpn; 23972f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann else 23982f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann fc_host_permanent_port_name(shost) = fc_host_port_name(shost); 23992f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann fc_host_maxframe_size(shost) = bottom->maximum_frame_size; 24002f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann fc_host_supported_speeds(shost) = bottom->supported_speed; 24012f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann} 24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request 24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) 24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24102f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct zfcp_adapter *adapter; 24112f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann struct fsf_qtcb *qtcb; 24122f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann 24132f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann adapter = fsf_req->adapter; 24142f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann qtcb = fsf_req->qtcb; 24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2419aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin switch (qtcb->header.fsf_status) { 24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 24212f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann zfcp_fsf_exchange_port_evaluate(fsf_req, 1); 2422aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); 2423aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 2424aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: 24252f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann zfcp_fsf_exchange_port_evaluate(fsf_req, 0); 2426aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); 2427aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin zfcp_fsf_link_down_info_eval(adapter, 2428aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin &qtcb->header.fsf_status_qual.link_down_info); 24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2431aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng"); 2432aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin debug_event(adapter->erp_dbf, 0, 24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, sizeof(u32)); 24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_port 24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 244141fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * purpose: 24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 244441fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * NULL - request could not be initiated 24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_port(struct zfcp_erp_action *erp_action) 24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 24502abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_OPEN_PORT_WITH_DID, 24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 24592abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create open port request " 24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s.\n", 24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24682abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24722abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; 24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); 24742abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->port; 24752abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 24762abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24782abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 24792abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send open port request for " 24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s.\n", 24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 24852abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("open port request initiated " 24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_port_handler 25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Open Port command 25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 250541fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * returns: 25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) 25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_plogi *plogi; 25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2516059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_ALREADY_OPEN: 25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: remote port 0x%016Lx on adapter %s " 25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is already open.\n", 25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_popen"); 25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a bug, however operation should continue normally 25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if it is simply ignored 25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot open port 0x%016Lx " 25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: 25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: The FSF adapter is out of resources. " 25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The remote port 0x%016Lx on adapter %s " 25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "could not be opened. Disabling it.\n", 25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_max_ports"); 25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_failed(port); 25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 25731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_NO_RETRY_POSSIBLE: 25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("The remote port 0x%016Lx on " 25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s could not be opened. " 25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Disabling it.\n", 25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port)); 25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_no_retry"); 25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_failed(port); 25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 26031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save port handle assigned by FSF */ 26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle = header->port_handle; 26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("The remote port 0x%016Lx via adapter %s " 26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was opened, it's port handle is 0x%x\n", 26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port), 26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle); 26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark port as open */ 26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPEN | 26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 2621d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 2622d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann ZFCP_STATUS_COMMON_ACCESS_BOXED, 2623d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann &port->status); 26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check whether D_ID has changed during open */ 26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 26271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: This check is not airtight, as the FCP channel does 26281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not monitor closures of target port connections caused on 26291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the remote side. Thus, they might miss out on invalidating 26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locally cached WWPNs (and other N_Port parameters) of gone 26311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * target ports. So, our heroic attempt to make things safe 26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could be undermined by 'open port' response data tagged with 26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * obsolete WWPNs. Another reason to monitor potential 26341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connection closures ourself at least (by interpreting 26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * incoming ELS' and unsolicited status). It just crosses my 26361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mind that one should be able to cross-check by means of 26371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * another GID_PN straight after a port has been opened. 26381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alternately, an ADISC/PDISC ELS should suffice, as well. 26391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds plogi = (struct fsf_plogi *) fsf_req->qtcb->bottom.support.els; 26411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, &port->status)) 26421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 26431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->qtcb->bottom.support.els1_length < 264475bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner sizeof (struct fsf_plogi)) { 26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 26461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "warning: insufficient length of " 26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "PLOGI payload (%i)\n", 26481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.els1_length); 26491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 26501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_short_plogi:"); 26511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* skip sanity check and assume wwpn is ok */ 26521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 26531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (plogi->serv_param.wwpn != port->wwpn) { 26541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("warning: d_id of port " 26551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx changed during " 26561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "open\n", port->wwpn); 26571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event( 26581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 26591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_did_change:"); 26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask( 26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_PORT_DID_DID, 26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &port->status); 266375bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner } else { 26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwnn = plogi->serv_param.wwnn; 266575bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner zfcp_plogi_evaluate(port, plogi); 266675bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner } 26671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 26701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_OP_SUBTYPE: 26721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* should never occure, subtype not set in zfcp_fsf_open_port */ 26731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("unknown operation subtype (adapter: %s, " 26741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "op_subtype=0x%x)\n", 26751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), 26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.operation_subtype); 26771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 26781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 26791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 26831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 26841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 26861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 26871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 26881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &port->status); 26921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_port 26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 26981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: submit FSF command "close port" 26991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 27011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 27031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 27041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_port(struct zfcp_erp_action *erp_action) 27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 27072abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 27081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 27131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_PORT, 27141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 27162abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create a close port request " 27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s.\n", 27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 27221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27252abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 27271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); 27302abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->port; 27312abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 27322abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.port_handle = erp_action->port->handle; 27332abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 27342abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 27352abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 27362abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 27372abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 27381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 27391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send a close port request for " 27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s.\n", 27411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 27432abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 27461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("close port request initiated " 27491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 27511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 27561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_port_handler 27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close Port FSF command 27621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 27661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req) 27671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 27701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2771059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 27721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 27741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 27751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 27761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 27831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may happen " 27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "occasionally.\n", port->handle, 27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 27871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 27881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 27891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 27901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 27911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 27921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(port->adapter, 0); 27931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 27941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 27971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note: FSF has actually closed the port in this case. 27981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The status code is just daft. Fingers crossed for a change 27991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 28001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 28011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("remote port 0x016%Lx on adapter %s closed, " 28051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port handle 0x%x\n", port->wwpn, 28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->handle); 28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_modify_port_status(port, 28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_COMMON_OPEN, 28091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_CLEAR); 28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 28161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status); 28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, 28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 28221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &port->status); 28261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 28271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 28301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_physical_port 28311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: submit FSF command "close physical port" 28331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 28341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 28351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 28371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) 28391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 28412abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 28422abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann unsigned long lock_flags; 28432abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann int retval = 0; 28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_PHYSICAL_PORT, 28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 28502abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 28521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create close physical port " 28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request (adapter %s, port 0x%016Lx)\n", 28541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 28561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28602abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark port as being closed */ 28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, 28661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &erp_action->port->status); 28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save a pointer to this port */ 28682abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->port; 28692abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.port_handle = erp_action->port->handle; 28702abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 28712abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 28722abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 28732abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 28742abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send close physical port " 28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request (adapter %s, port 0x%016Lx)\n", 28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 28802abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 28811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("close physical port request initiated " 28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 28901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 28911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 28921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 28941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 28961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_physical_port_handler 28971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 28981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close Physical Port FSF command 28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 29021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) 29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 29071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 29081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 29091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 29101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 29131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x invalid" 29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx). " 29251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally.\n", 29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle, 29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), 29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn); 29291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 29301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 29311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 29321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 29341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 29351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(port->adapter, 0); 29361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot close " 29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "physical port 0x%016Lx on adapter %s\n", 29421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 29431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 29451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 29461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 29471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 29481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 29491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter " 29631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s needs to be reopened but it was attempted " 29641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to close it physically.\n", 29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port)); 29671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_pboxed"); 2968d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(port); 29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 29701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 29711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 29741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 29751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 29761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 29771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 29781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This will now be escalated by ERP */ 29791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 29801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 29821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 29841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 29851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 29881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 29891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 29921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 29941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof (u32)); 29961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 30011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Remote port 0x%016Lx via adapter %s " 30021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "physically closed, port handle 0x%x\n", 30031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 30041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->handle); 30051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* can't use generic zfcp_erp_modify_port_status because 30061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ZFCP_STATUS_COMMON_OPEN must not be reset for the port 30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 30091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(unit, &port->unit_list_head, list) 30101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 30111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 30161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 30171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 30181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 30191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 30201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 30251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, &port->status); 30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 30271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 30301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_unit 30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 30331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 30351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * assumptions: This routine does not check whether the associated 30371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remote port has already been opened. This should be 30381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done by calling routines. Otherwise some status 30391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may be presented by FSF 30401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 30411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 30421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) 30431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 30441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 30452abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 30461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 30471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 30481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 30501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 30511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_OPEN_LUN, 30521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 30531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 30542abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 30551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 30561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create open unit request for " 30571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s.\n", 30581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->port->wwpn, 30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30642abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 30661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 30671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30682abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.port_handle = erp_action->port->handle; 30692abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun; 3070aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE)) 30712abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->bottom.support.option = 307206506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann FSF_OPEN_LUN_SUPPRESS_BOXING; 30731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); 30742abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->unit; 30752abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 30762abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 30771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30782abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 30792abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(erp_action->fsf_req); 30801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 30811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an open unit request " 30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s, port 0x%016Lx for " 30831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx\n", 30841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 30851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 30861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun); 30872abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 30881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 30891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 30901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Open LUN request initiated (adapter %s, " 30931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 30941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 30951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, erp_action->unit->fcp_lun); 30961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 30971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 30981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 30991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 31001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_unit_handler 31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Open LUN command 31061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 310741fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * returns: 31081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 31091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 31101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) 31111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 31121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 31131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 31141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 31151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 31161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 31171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_queue_designator *queue_designator; 31181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 3119aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin int exclusive, readwrite; 31201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 31221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 31241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change unit status in our bookkeeping */ 31251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 31261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 31291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 31301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 31311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator = &header->fsf_status_qual.fsf_queue_designator; 31321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 3134b64ddf96456cde17be22bf74cafed381a29d58baHeiko Carstens ZFCP_STATUS_COMMON_ACCESS_BOXED | 31351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_UNIT_SHARED | 31361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_UNIT_READONLY, 31371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 31381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 31401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 31411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 31431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x " 31441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s invalid " 31451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally\n", 31461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 31471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 31481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 31491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 31501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 31511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 31521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_ph_nv"); 31531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 31541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_ALREADY_OPEN: 31581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Attempted to open unit 0x%016Lx on " 31591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port 0x%016Lx on adapter %s twice.\n", 31601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 31611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 31621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, 31631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_uopen"); 31641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 31681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot open unit 0x%016Lx on " 31691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port 0x%016Lx on adapter %s\n", 31701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 31711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 31721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 31731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 31741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 31751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 31761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 31771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 31781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 31791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 31801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 31811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 31821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 31861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 31871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); 31881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); 31891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 31931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 31941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 31951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 31961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); 3197d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 31981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 31991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_SHARING_VIOLATION: 32031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (header->fsf_status_qual.word[0] != 0) { 32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port " 32051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "with WWPN 0x%Lx " 32061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "connected to the adapter %s " 32071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is already in use in LPAR%d, CSS%d\n", 32081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 32091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 32111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator->hla, 32121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator->cssid); 32131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 32141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[4]; 32151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[5]; 32161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 32171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 32181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 32191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 32201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 32211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access to FCP-LUN 0x%Lx at the " 32221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port with WWPN 0x%Lx " 32231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "connected to the adapter %s " 32241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is denied (%s rule %d)\n", 32251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 32261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 32281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], 32291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule); 32301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 32341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 32351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 32361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 32371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, 32381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_l_sh_vio"); 32391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 32401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); 32411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); 32421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: 32461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: The adapter ran out of resources. " 32471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "There is no handle (temporary port identifier) " 32481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "available for unit 0x%016Lx on port 0x%016Lx " 32491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 32501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 32511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 32531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 32541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_max_units"); 32551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 32561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 32601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 32611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 32621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Re-establish link to port */ 32631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 32641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 326565a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 32661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 32691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 32701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 32711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 32721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 32751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 32761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 32771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 32781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, 32791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 32801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 32811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 32821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 32831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_INVALID_COMMAND_OPTION: 32871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 32881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Invalid option 0x%x has been specified " 32891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "in QTCB bottom sent to the adapter %s\n", 32901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option, 32911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 32921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 32941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 32971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save LUN handle assigned by FSF */ 32981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle = header->lun_handle; 32991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("unit 0x%016Lx on remote port 0x%016Lx on " 33001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s opened, port handle 0x%x\n", 33011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 33021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 33031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 33041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 33051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark unit as open */ 33061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 3307aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 3308aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) && 3309aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) && 3310aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin (adapter->ccw_device->id.dev_model != ZFCP_DEVICE_MODEL_PRIV)) { 3311aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin exclusive = (bottom->lun_access_info & 3312aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_UNIT_ACCESS_EXCLUSIVE); 3313aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin readwrite = (bottom->lun_access_info & 3314aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_UNIT_ACCESS_OUTBOUND_TRANSFER); 3315aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 33161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!exclusive) 33171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, 33181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 33191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!readwrite) { 33211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, 33221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 33231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("read-only access for unit " 33241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, wwpn=0x%016Lx, " 33251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fcp_lun=0x%016Lx)\n", 33261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 33271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 33281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 33291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exclusive && !readwrite) { 33321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("exclusive access of read-only " 33331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit not supported\n"); 33341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 33351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 33361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_shutdown(unit, 0); 33371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!exclusive && readwrite) { 33381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("shared access of read-write " 33391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit not supported\n"); 33401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 33411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 33421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_shutdown(unit, 0); 33431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 33471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 33481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 33501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 33511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 33521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 33531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_s_inval:"); 33541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 33551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 33561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 33571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 33601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status); 33611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 33621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 33631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 33651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_unit 33661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 33671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 33681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 33691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of fsf_req - request successfully initiated 337041fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * NULL - 33711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 33721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * assumptions: This routine does not check whether the associated 33731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remote port/lun has already been opened. This should be 33741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done by calling routines. Otherwise some status 33751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may be presented by FSF 33761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 33771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 33781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) 33791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 33801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 33812abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann struct zfcp_fsf_req *fsf_req; 33821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 33831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 33841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 33861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 33871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_LUN, 33881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 33891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 33902abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann &lock_flags, &fsf_req); 33911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 33921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create close unit request for " 33931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s.\n", 33941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 33951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 33961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 33971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 33981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34002abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 34011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 34021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 34031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34042abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.port_handle = erp_action->port->handle; 34052abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; 34061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); 34072abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->data = (unsigned long) erp_action->unit; 34082abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann fsf_req->erp_action = erp_action; 34092abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann erp_action->fsf_req = fsf_req; 34101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34112abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_erp_start_timer(fsf_req); 34122abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(erp_action->fsf_req); 34131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 34141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send a close unit request for " 34151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx onadapter %s.\n", 34161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 34171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 34181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 34192abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_req_free(fsf_req); 34201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 34211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 34221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Close LUN request initiated (adapter %s, " 34251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 34261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 34271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, erp_action->unit->fcp_lun); 34281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 34291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 34301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 34311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 34321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 34331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 34351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_unit_handler 34361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 34371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close LUN FSF command 34381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 34391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 34401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 34411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 34421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) 34431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 34441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 34451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 34461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3447059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 34481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 34501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change unit status in our bookkeeping */ 34511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 34521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 34551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 34561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 34581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 34591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may " 34601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "happen in rare circumstances\n", 34611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 34621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 34631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 34641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 34651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 34661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 34671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 34681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 34691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 34701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 34711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 34721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 34751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary LUN identifier 0x%x of unit " 34761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 34771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen occasionally.\n", 34781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 34791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 34801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 34811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 34821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Status qualifier data:\n"); 34831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 34841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 34851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 34861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 34871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv"); 34881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 34891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 34901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 34931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 34941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 34951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 34961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 34971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); 3498d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 34991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 35001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 35011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 35041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { 35051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 35061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* re-establish link to port */ 35071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 35081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 350965a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 35101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 35111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 35131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 35141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 35151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 35161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 35171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 35191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 35201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 35211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status_qual.word[0]); 35221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 35231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 35241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 35251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 35261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status_qual.word[0], 35271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 35281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 35301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 35331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("unit 0x%016Lx on port 0x%016Lx on adapter %s " 35341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "closed, port handle 0x%x\n", 35351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 35361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 35371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 35381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 35391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark unit as closed */ 35401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 35411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 35421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 35451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 35461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 35471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status); 35481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 35491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 35501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, 35511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 35521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 35531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 35541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 35561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &unit->status); 35571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 35581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 35591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 35611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) 35621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: adapter where scsi command is issued 35631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @unit: unit where command is sent to 35641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scsi_cmnd: scsi command to be sent 35651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @timer: timer to be started when request is initiated 35661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @req_flags: flags for fsf_request 35671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 35681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 35691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, 35701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit, 35711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_cmnd * scsi_cmnd, 35722abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann int use_timer, int req_flags) 35731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 35741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 35751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu; 35761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int sbtype; 35771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 35781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int real_bytes = 0; 35791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 35801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mask; 35811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 35831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, 35841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->pool.fsf_req_scsi, 35851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 35861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval < 0)) { 35871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: Could not create FCP command request " 35881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for unit 0x%016Lx on port 0x%016Lx on " 35891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 35901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 35911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 35921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 35931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req_create; 35941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 35951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3596059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_get(unit); 3597059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->unit = unit; 35981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3599059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann /* associate FSF request with SCSI request (for look up on abort) */ 36004eff4a36516d72e4f6ede901141214a7e05607e7Andreas Herrmann scsi_cmnd->host_scribble = (unsigned char *) fsf_req->req_id; 3601059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 3602059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann /* associate SCSI command with FSF request */ 3603059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) scsi_cmnd; 36041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handles of unit and its parent port in QTCB */ 36061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 36071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 36081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FSF does not define the structure of the FCP_CMND IU */ 36101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu = (struct fcp_cmnd_iu *) 36111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 36121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 36141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set depending on data direction: 36151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in SBALE (SB Type) 36161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in QTCB 36171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in FCP_CMND IU 36181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 36191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (scsi_cmnd->sc_data_direction) { 36201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_NONE: 36211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; 36221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 36231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(qdio): 36241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * what is the correct type for commands 36251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without 'real' data buffers? 36261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 36271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_READ; 36281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 36291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_FROM_DEVICE: 36301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ; 36311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_READ; 36321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->rddata = 1; 36331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 36341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_TO_DEVICE: 36351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE; 36361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_WRITE; 36371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->wddata = 1; 36381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 36391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_BIDIRECTIONAL: 36401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 36411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 36421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dummy, catch this condition earlier 36431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in zfcp_scsi_queuecommand 36441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 36451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_scsi_cmnd; 36461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 36471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FC service class in QTCB (3 per default) */ 364906506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; 36501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FCP_LUN in FCP_CMND IU in QTCB */ 36521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->fcp_lun = unit->fcp_lun; 36531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = ZFCP_STATUS_UNIT_READONLY | ZFCP_STATUS_UNIT_SHARED; 36551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set task attributes in FCP_CMND IU in QTCB */ 36571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely((scsi_cmnd->device->simple_tags) || 36581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (atomic_test_mask(mask, &unit->status)))) 36591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_attribute = SIMPLE_Q; 36601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 36611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_attribute = UNTAGGED; 36621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set additional length of FCP_CDB in FCP_CMND IU in QTCB, if needed */ 36641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH)) { 36651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length 36661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds = (scsi_cmnd->cmd_len - FCP_CDB_LENGTH) >> 2; 36671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("SCSI CDB length is 0x%x, " 36681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "additional FCP_CDB length is 0x%x " 36691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(shifted right 2 bits)\n", 36701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmnd->cmd_len, 36711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length); 36721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 36731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 36741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy SCSI CDB (including additional length, if any) to 36751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FCP_CDB in FCP_CMND IU in QTCB 36761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 36771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len); 36781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FCP CMND IU length in QTCB */ 36801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length = 36811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_cmnd_iu) + 36821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length + sizeof (fcp_dl_t); 36831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* generate SBALEs from data buffer */ 36851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds real_bytes = zfcp_qdio_sbals_from_scsicmnd(fsf_req, sbtype, scsi_cmnd); 36861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(real_bytes < 0)) { 36871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->sbal_number < ZFCP_MAX_SBALS_PER_REQ) { 36881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG( 36891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Data did not fit into available buffer(s), " 36901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "waiting for more...\n"); 36912282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt retval = -EIO; 36922282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt } else { 36932282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt ZFCP_LOG_NORMAL("error: No truncation implemented but " 36942282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt "required. Shutting down unit " 36952282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt "(adapter %s, port 0x%016Lx, " 36962282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt "unit 0x%016Lx)\n", 36972282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt zfcp_get_busid_by_unit(unit), 36982282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt unit->port->wwpn, 36992282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt unit->fcp_lun); 37002282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt zfcp_erp_unit_shutdown(unit, 0); 37012282f658914e316ca32fd120fded130d1c0e26e4Christof Schmitt retval = -EINVAL; 37021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_fit; 37041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set length of FCP data length in FCP_CMND IU in QTCB */ 37071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes); 37081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Sending SCSI command:\n"); 37101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 37111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) scsi_cmnd->cmnd, scsi_cmnd->cmd_len); 37121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37132abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann if (use_timer) 37142abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 37152abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 37162abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 37171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval < 0)) { 37181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send FCP command request " 37191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n", 37201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 37211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 37221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 37231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto send_failed; 37241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Send FCP Command initiated (adapter %s, " 37271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 37281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 37291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 37301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 37311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto success; 37321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_failed: 37341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds no_fit: 37351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_scsi_cmnd: 3736059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_put(unit); 37371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 37381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 37391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmnd->host_scribble = NULL; 37401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds success: 37411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req_create: 37421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 37431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 37441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 37451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct zfcp_fsf_req * 37471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, 37481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit, 37491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 tm_flags, int req_flags) 37501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 37511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 37521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 37531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu; 37541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 37551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 37561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 37581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, 37591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->pool.fsf_req_scsi, 37601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 37611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 37621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create FCP command (task " 37631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "management) request for adapter %s, port " 37641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " 0x%016Lx, unit 0x%016Lx.\n", 37651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 37661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, unit->fcp_lun); 37671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 37681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 37711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used to decide on proper handler in the return path, 37721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could be either zfcp_fsf_send_fcp_command_task_handler or 37731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_fcp_command_task_management_handler */ 37741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT; 37761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 37781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hold a pointer to the unit being target of this 37791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * task management request 37801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3781059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) unit; 37821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FSF related fields in QTCB */ 37841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 37851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 37861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; 378706506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; 37881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length = 37891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t); 37901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 37921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; 37931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 37941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FCP related fields in FCP_CMND IU in QTCB */ 37961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu = (struct fcp_cmnd_iu *) 37971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 37981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->fcp_lun = unit->fcp_lun; 37991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_management_flags = tm_flags; 38001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38012abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT); 38022abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 38031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 38041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an FCP-command (task " 38051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "management) on adapter %s, port 0x%016Lx for " 38061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit LUN 0x%016Lx\n", 38071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 38081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 38091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 38101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 38111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 38121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 38131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Send FCP Command (task management function) initiated " 38161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx, unit 0x%016Lx, " 38171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tm_flags=0x%x)\n", 38181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 38191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 38201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 38211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tm_flags); 38221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 38231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 38241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fsf_req; 38251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 38261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 38281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_handler 38291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 38301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Send FCP Command 38311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 383241fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * returns: 38331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 38341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 38351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) 38361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 38371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 38381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 38391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 38401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 38411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 38431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) 3845059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 38461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3847059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = fsf_req->unit; 38481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 38501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* go directly to calls of special handlers */ 38511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 38521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 38551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 38561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 38581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 38591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid\n", 38601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 38611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 38621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 38631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 38641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 38651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 38661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 38671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 38681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 38721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary LUN identifier 0x%x for unit " 38731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 38741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen occasionally.\n", 38751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 38761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 38771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 38781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 38791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Status qualifier data:\n"); 38801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 38811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 38821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 38831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 38841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_uhand_nv"); 38851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 38861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_HANDLE_MISMATCH: 38901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The port handle 0x%x has changed " 38911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unexpectedly. (adapter %s, port 0x%016Lx, " 38921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx)\n", 38931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 38941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 38951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 38961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 38971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("status qualifier:\n"); 38981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 38991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 39001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 39011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 39021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_hand_mis"); 39031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 39041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 39051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 390806506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_LOG_INFO("error: adapter %s does not support fc " 390906506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann "class %d.\n", 391006506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann zfcp_get_busid_by_unit(unit), 391106506d00ec1a0d7d3b1dff59185af355ce29ac0aAndreas Herrmann ZFCP_FC_SERVICE_CLASS_DEFAULT); 39121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 39131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 39141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_class_nsup"); 39151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 39161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 39171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCPLUN_NOT_VALID: 39201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: unit 0x%016Lx on port 0x%016Lx on " 39211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s does not have correct unit " 39221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "handle 0x%x\n", 39231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 39241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 39251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 39261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 39271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 39281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 39291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 39301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 39311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 39321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_fcp_lun_nv"); 39331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 39341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 39351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 39381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot send FCP command to " 39391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on " 39401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", unit->fcp_lun, unit->port->wwpn, 39411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 39421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 39431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 39441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 39451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 39461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 39471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 39481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 39491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 39501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 39511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 39521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 39561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 39571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 39581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_DIRECTION_INDICATOR_NOT_VALID: 39611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Invalid data direction given for unit " 39621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s " 39631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info %d)\n", 39641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 39651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 39661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 39671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction); 39681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 39691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 39701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_dir_ind_nv"); 39711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 39721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 39731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CMND_LENGTH_NOT_VALID: 39761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 39771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: An invalid control-data-block length field " 39781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was found in a command for unit 0x%016Lx on port " 39791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s " "(debug info %d)\n", 39801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 39811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 39821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length); 39831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 39841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 39851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_cmd_len_nv"); 39861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 39871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 39881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 39911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 39921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 39931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 39941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); 3995d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 39961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 39971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 39981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_BOXED: 40011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("unit needs to be reopened (adapter %s, " 40021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n", 40031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 40041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, unit->fcp_lun); 40051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); 4006d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_unit_boxed(unit); 40071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 40081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 40091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 40121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 40131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 40141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* re-establish link to port */ 40151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 40161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 401765a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 40181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 40201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME(hw) need proper specs for proper action */ 40211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* let scsi stack deal with retries and escalation */ 40221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 40231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 40241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 40261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 4027516a4201bacfd61ea957039d6f47276ee9c32a0dAndreas Herrmann ("Unknown status qualifier 0x%x arrived.\n", 40281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 40291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 40301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 40311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 40321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 40331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(u32)); 40341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4036516a4201bacfd61ea957039d6f47276ee9c32a0dAndreas Herrmann fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 40371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 40401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_RSP_AVAILABLE: 40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 40461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 40471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 40481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof(u32)); 40491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 40531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) { 40541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 40551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_fcp_command_task_management_handler(fsf_req); 40561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 40571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req); 4058059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->unit = NULL; 4059059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_put(unit); 40601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 40621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 40631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 40651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_task_handler 40661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 40671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FCP_RSP IU 40681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 406941fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * returns: 40701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 40711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 40721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) 40731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 40741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 40751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_cmnd *scpnt; 40761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) 40771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_rsp); 40781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu = (struct fcp_cmnd_iu *) 40791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 40801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 sns_len; 40811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); 40821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 4083059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit = fsf_req->unit; 40841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_lock_irqsave(&fsf_req->adapter->abort_lock, flags); 4086059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann scpnt = (struct scsi_cmnd *) fsf_req->data; 40871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(!scpnt)) { 40881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG 40891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("Command with fsf_req %p is not associated to " 40901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "a scsi command anymore. Aborted?\n", fsf_req); 40911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 40921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTED)) { 40941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME: (design) mid-layer should handle DID_ABORT like 40951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DID_SOFT_ERROR by retrying the request for devices 40961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that allow retries. 40971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 40981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Setting DID_SOFT_ERROR and SUGGEST_RETRY\n"); 40991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_SOFT_ERROR); 41001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_driver_byte(&scpnt->result, SUGGEST_RETRY); 41011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 41021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 41051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Setting DID_ERROR\n"); 41061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 41071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 41081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set message byte of result in SCSI command */ 41111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result |= COMMAND_COMPLETE << 8; 41121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 41141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy SCSI status code of FCP_STATUS of FCP_RSP IU to status byte 41151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of result in SCSI command 41161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result |= fcp_rsp_iu->scsi_status; 41181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->scsi_status)) { 41191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* DEBUG */ 41201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status for SCSI Command:\n"); 41211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 41221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->cmnd, scpnt->cmd_len); 41231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("SCSI status code 0x%x\n", 41241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->scsi_status); 41251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 41261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) fcp_rsp_iu, sizeof (struct fcp_rsp_iu)); 41271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 41281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), 41291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_sns_len); 41301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check FCP_RSP_INFO */ 41331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) { 41341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("rsp_len is valid\n"); 41351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fcp_rsp_info[3]) { 41361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_GOOD: 41371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ok, continue */ 41381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("no failure or Task Management " 41391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Function complete\n"); 41401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_OK); 41411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 41421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_LENGTH_MISMATCH: 41431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* hardware bug */ 41441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: FCP response code indictates " 41451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that the fibrechannel protocol data " 41461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "length differs from the burst length. " 41471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on unit 0x%016Lx " 41481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on port 0x%016Lx on adapter %s", 41491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 41511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 41521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 41531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 41541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 41551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 41561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 41571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 41581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_FIELD_INVALID: 41591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* driver or hardware bug */ 41601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: FCP response code indictates " 41611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that the fibrechannel protocol data " 41621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fields were incorrectly set up. " 41631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on the unit " 41641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on " 41651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s", 41661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 41681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 41691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 41701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 41711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 41721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 41731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 41741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 41751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_RO_MISMATCH: 41761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* hardware bug */ 41771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The FCP response code indicates " 41781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that conflicting values for the " 41791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fibrechannel payload offset from the " 41801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "header were found. " 41811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on unit 0x%016Lx " 41821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on port 0x%016Lx on adapter %s.\n", 41831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 41851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 41861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 41871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 41881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 41891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 41901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 41911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 41921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 41931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An invalid FCP response " 41941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "code was detected for a command. " 41951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on the unit " 41961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on " 41971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s (debug info 0x%x)\n", 41981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 42001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 42011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_info[3]); 42021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 42031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 42041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 42051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 42061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 42076f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> goto skip_fsfstatus; 42081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for sense data */ 42121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) { 42131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = FSF_FCP_RSP_SIZE - 42141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_rsp_iu) + fcp_rsp_iu->fcp_rsp_len; 42151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("room for %i bytes sense data in QTCB\n", 42161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len); 42171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE); 42181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("room for %i bytes sense data in SCSI command\n", 42191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_SENSE_BUFFERSIZE); 42201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len); 42211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n", 42221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result); 42231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 42241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) &scpnt->cmnd, scpnt->cmd_len); 42251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n", 42271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_sns_len); 42281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&scpnt->sense_buffer, 42291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len); 42301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 42311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) &scpnt->sense_buffer, sns_len); 42321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for overrun */ 42351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_over)) { 42361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("A data overrun was detected for a command. " 42371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s. " 42381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The response data length is " 42391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d, the original length was %d.\n", 42401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 42411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 42421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 42431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_resid, 42441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (int) zfcp_get_fcp_dl(fcp_cmnd_iu)); 42451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for underrun */ 42481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) { 42491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("A data underrun was detected for a command. " 42501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s. " 42511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The response data length is " 42521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d, the original length was %d.\n", 42531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 42541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 42551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 42561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_resid, 42571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (int) zfcp_get_fcp_dl(fcp_cmnd_iu)); 42581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42597936a892e72498a05b9a7fb1fec6506d65c8e435FUJITA Tomonori scsi_set_resid(scpnt, fcp_rsp_iu->fcp_resid); 42607936a892e72498a05b9a7fb1fec6506d65c8e435FUJITA Tomonori if (scsi_bufflen(scpnt) - scsi_get_resid(scpnt) < 42617936a892e72498a05b9a7fb1fec6506d65c8e435FUJITA Tomonori scpnt->underflow) 42626f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> set_host_byte(&scpnt->result, DID_ERROR); 42631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 42661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); 42671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42688a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (scpnt->result != 0) 4269ed829ad607a9c334cea490d3a8c0f874153fb42dMaxim Shchetynin zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req); 42708a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin else if (scpnt->retries > 0) 4271ed829ad607a9c334cea490d3a8c0f874153fb42dMaxim Shchetynin zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req); 42728a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin else 4273ed829ad607a9c334cea490d3a8c0f874153fb42dMaxim Shchetynin zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req); 42741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* cleanup pointer (need this especially for abort) */ 42761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->host_scribble = NULL; 42771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* always call back */ 42791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (scpnt->scsi_done) (scpnt); 42801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 42821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We must hold this lock until scsi_done has been called. 42831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise we may call scsi_done after abort regarding this 42841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command has completed. 42851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: scsi_done must not block! 42861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 42871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 42881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_unlock_irqrestore(&fsf_req->adapter->abort_lock, flags); 42891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 42901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 42911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 42931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_task_management_handler 42941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 42951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FCP_RSP IU 42961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 429741fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig * returns: 42981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 42991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 43001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req) 43011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 43021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 43031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) 43041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_rsp); 43051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); 4306059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data; 43071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 43091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 43101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 43111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check FCP_RSP_INFO */ 43141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fcp_rsp_info[3]) { 43151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_GOOD: 43161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ok, continue */ 43171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("no failure or Task Management " 43181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Function complete\n"); 43191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_TASKMAN_UNSUPP: 43211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: A reuested task management function " 43221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is not supported on the target device " 43231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s\n ", 43241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 43251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 43261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 43271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP; 43281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_TASKMAN_FAILED: 43301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: A reuested task management function " 43311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "failed to complete successfully. " 43321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s.\n", 43331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 43341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 43351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 43361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 43371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 43391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An invalid FCP response " 43401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "code was detected for a command. " 43411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s " 43421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 43431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 43441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 43451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 43461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_info[3]); 43471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 43481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 43511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 43521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 43531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 43561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_control_file 43571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 43581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Initiator of the control file upload/download FSF requests 43591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 43601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - FSF request is successfuly created and queued 43611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EOPNOTSUPP - The FCP adapter does not have Control File support 43621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - Invalid direction specified 43631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENOMEM - Insufficient memory 43641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EPERM - Cannot create FSF request or place it in QDIO queue 43651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 43661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 43671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_control_file(struct zfcp_adapter *adapter, 43681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req **fsf_req_ptr, 43691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 fsf_command, 43701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 option, 43711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_sg_list *sg_list) 43721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 43731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 43741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 43751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 43761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 43771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int req_flags = 0; 43781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int direction; 43791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 43801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4381aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) { 43821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", 43831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EOPNOTSUPP; 43851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 43861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_command) { 43891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_DOWNLOAD_CONTROL_FILE: 43911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds direction = SBAL_FLAGS0_TYPE_WRITE; 43921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((option != FSF_CFDC_OPTION_FULL_ACCESS) && 43931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (option != FSF_CFDC_OPTION_RESTRICTED_ACCESS)) 43941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_flags = ZFCP_WAIT_FOR_SBAL; 43951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_UPLOAD_CONTROL_FILE: 43981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds direction = SBAL_FLAGS0_TYPE_READ; 43991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 44021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Invalid FSF command code 0x%08x\n", fsf_command); 44031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 44041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 44051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags, 44081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, &lock_flags, &fsf_req); 44091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 44101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create FSF request for the " 44111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 44121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 44141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto unlock_queue_lock; 44151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 44181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= direction; 44191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 44211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; 44221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option = option; 44231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sg_list->count > 0) { 44251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 44261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, direction, 44281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sg_list->sg, sg_list->count, 44291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_REQ); 44301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes != ZFCP_CFDC_MAX_CONTROL_FILE_SIZE) { 44311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 44321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "error: Could not create sufficient number of " 44331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "SBALS for an FSF request to the adapter %s\n", 44341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -ENOMEM; 44361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto free_fsf_req; 44371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 44391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 44401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44412abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 44422abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann retval = zfcp_fsf_req_send(fsf_req); 44431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 44441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("initiation of cfdc up/download failed" 44451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s)\n", 44461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 44481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto free_fsf_req; 44491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 44511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Control file %s FSF request has been sent to the " 44531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 44541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ? 44551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "download" : "upload", 44561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_event(fsf_req->completion_wq, 44591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 44601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fsf_req_ptr = fsf_req; 44622abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann goto out; 44631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_fsf_req: 44651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 44661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_queue_lock: 44671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 44681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 44691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 44701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 44711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 44741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_control_file_handler 44751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 44761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Handler of the control file upload/download FSF requests 44771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 44781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - FSF request successfuly processed 44791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EAGAIN - Operation has to be repeated because of a temporary problem 44801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EACCES - There is no permission to execute an operation 44811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EPERM - The control file is not in a right format 44821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO - There is a problem with the FCP adapter 44831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - Invalid operation 44841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EFAULT - User space memory I/O operation fault 44851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 44861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 44871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req) 44881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 44891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 44901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header = &fsf_req->qtcb->header; 44911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom = &fsf_req->qtcb->bottom.support; 44921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 44931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 44951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 44961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 44971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 45001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 45021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The FSF request has been successfully completed " 45041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s\n", 45051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_OPERATION_PARTIALLY_SUCCESSFUL: 45091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) { 45101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 45111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45126f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> case FSF_SQ_CFDC_HARDENED_ON_SE: 45136f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> ZFCP_LOG_NORMAL( 45146f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "CFDC on the adapter %s has being " 45156f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "hardened on primary and secondary SE\n", 45166f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> zfcp_get_busid_by_adapter(adapter)); 45176f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> break; 45186f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> 45191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE: 45201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC of the adapter %s could not " 45221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be saved on the SE\n", 45231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2: 45271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC of the adapter %s could not " 45291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be copied to the secondary SE\n", 45301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 45341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC could not be hardened " 45361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s\n", 45371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EAGAIN; 45421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_AUTHORIZATION_FAILURE: 45451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Adapter %s does not accept privileged commands\n", 45471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EACCES; 45501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CFDC_ERROR_DETECTED: 45531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Error at position %d in the CFDC, " 45551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC is discarded by the adapter %s\n", 45561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0], 45571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 45601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONTROL_FILE_UPDATE_ERROR: 45631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Adapter %s cannot harden the control file, " 45651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "file is discarded\n", 45661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 45691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONTROL_FILE_TOO_LARGE: 45721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Control file is too large, file is discarded " 45741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "by the adapter %s\n", 45751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 45761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 45781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_CONFLICT_DETECTED: 45811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) 45821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC has been discarded by the adapter %s, " 45841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "because activation would impact " 45851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d active connection(s)\n", 45861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 45871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 45881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 45891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 45901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 45911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONFLICTS_OVERRULED: 45931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) 45941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 45951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC has been activated on the adapter %s, " 45961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "but activation has impacted " 45971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d active connection(s)\n", 45981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 45991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 46001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 46011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 46021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 46031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_OP_SUBTYPE: 46051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("unknown operation subtype (adapter: %s, " 46061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "op_subtype=0x%x)\n", 46071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 46081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->operation_subtype); 46091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 46101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 46111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 46121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_INVALID_COMMAND_OPTION: 46141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 46151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Invalid option 0x%x has been specified " 46161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "in QTCB bottom sent to the adapter %s\n", 46171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option, 46181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 46191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 46201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 46211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 46221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 46241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 46251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bug: An unknown/unexpected FSF status 0x%08x " 46261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was presented on the adapter %s\n", 46271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status, 46281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 46291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval"); 46301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 46311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof(u32)); 46321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 46331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 46341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 46351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 46361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 46381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 46391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 46401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 46421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_sbal_check(unsigned long *flags, 46431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *queue, int needed) 46441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 46451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_lock_irqsave(&queue->queue_lock, *flags); 46461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(atomic_read(&queue->free_count) >= needed)) 46471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 46481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&queue->queue_lock, *flags); 46491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 46501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 46511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 46531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set qtcb pointer in fsf_req and initialize QTCB 46541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 46554d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic void 46568a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetyninzfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) 46571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 46581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->qtcb != NULL)) { 4659fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->qtcb->prefix.req_seq_no = 4660fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->adapter->fsf_req_seq_no; 4661fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->qtcb->prefix.req_id = fsf_req->req_id; 46621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; 4663fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->qtcb->prefix.qtcb_type = 4664fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_qtcb_type[fsf_req->fsf_command]; 46651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; 4666fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske fsf_req->qtcb->header.req_handle = fsf_req->req_id; 46678a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; 46681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 46691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 46701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 46721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_req_sbal_get - try to get one SBAL in the request queue 46731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: adapter for which request queue is examined 46741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @req_flags: flags indicating whether to wait for needed SBAL or not 46751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @lock_flags: lock_flags if queue_lock is taken 46761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return: 0 on success, otherwise -EIO, or -ERESTARTSYS 46771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Locks: lock adapter->request_queue->queue_lock on success 46781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 46791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 46801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags, 46811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *lock_flags) 46821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 46831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long ret; 46841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue = &adapter->request_queue; 46851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) { 46871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = wait_event_interruptible_timeout(adapter->request_wq, 46881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1), 46891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_SBAL_TIMEOUT); 46901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 46911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 46921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) 46931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 46941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1)) 46951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 46961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 46981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 46991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 47011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_create 47021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 47031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: create an FSF request at the specified adapter and 47041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * setup common fields 47051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 47061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: -ENOMEM if there was insufficient memory for a request 47071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO if no qdio buffers could be allocate to the request 47081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL/-EPERM on bug conditions in req_dequeue 47091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 in success 47101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 47111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * note: The created request is returned by reference. 47121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 47131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: lock of concerned request queue must not be held, 47141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but is held on completion (write, irqsave) 47151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 47161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 47171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, 47181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_t *pool, unsigned long *lock_flags, 47191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req **fsf_req_p) 47201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 47211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 47221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 47231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 47241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue = &adapter->request_queue; 47251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate new FSF request */ 47271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = zfcp_fsf_req_alloc(pool, req_flags); 47281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(NULL == fsf_req)) { 47291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: Could not put an FSF request into" 47301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the outbound (send) queue.\n"); 47311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 47321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_fsf_req; 47331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 47341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47358a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->adapter = adapter; 47368a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->fsf_command = fsf_cmd; 4737fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske INIT_LIST_HEAD(&fsf_req->list); 47382abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann init_timer(&fsf_req->timer); 47391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 474041fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig /* initialize waitqueue which may be used to wait on 47411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this request completion */ 47421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&fsf_req->completion_wq); 47431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_sbal_get(adapter, req_flags, lock_flags); 4745801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt if (ret < 0) 47461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_sbals; 4747801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt 4748801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt /* this is serialized (we are holding req_queue-lock of adapter) */ 4749801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt if (adapter->req_no == 0) 4750801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt adapter->req_no++; 4751801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt fsf_req->req_id = adapter->req_no++; 4752801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt 4753801e0ced1891a2b8cad1a435c45234a719b3b6bfChristof Schmitt zfcp_fsf_req_qtcb_init(fsf_req); 47541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 47561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We hold queue_lock here. Check if QDIOUP is set and let request fail 47571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if it is not set (see also *_open_qdio and *_close_qdio). 47581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 47591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) { 47611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&req_queue->queue_lock, *lock_flags); 47621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EIO; 47631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_sbals; 47641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 47651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47668a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (fsf_req->qtcb) { 47678a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->seq_no = adapter->fsf_req_seq_no; 47688a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; 47698a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin } 47701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_number = 1; 47711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_first = req_queue->free_index; 47721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_curr = req_queue->free_index; 47731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = 1; 47741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP)) { 47761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 47771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 47781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 47801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup common SBALE fields */ 4782fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske sbale[0].addr = (void *) fsf_req->req_id; 47831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_COMMAND; 47841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->qtcb != NULL)) { 47851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].addr = (void *) fsf_req->qtcb; 47861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].length = sizeof(struct fsf_qtcb); 47871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 47881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("got %i free BUFFERs starting at index %i\n", 47901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_number, fsf_req->sbal_first); 47911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto success; 47931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_sbals: 47951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* dequeue new FSF request previously enqueued */ 47961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 47971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 47981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_fsf_req: 48001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_lock_irqsave(&req_queue->queue_lock, *lock_flags); 48011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds success: 48021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fsf_req_p = fsf_req; 48031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 48041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 48051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 48071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_send 48081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 48091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: start transfer of FSF request via QDIO 48101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 48111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - request transfer succesfully started 48121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * !0 - start of request transfer failed 48131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 48142abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmannstatic int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req) 48151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 48161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 48171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue; 48181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 48198a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin int inc_seq_no; 48201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int new_distance_from_int; 4821fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske u64 dbg_tmp[2]; 48221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 48231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 48251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue = &adapter->request_queue, 48261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME(debug): remove it later */ 48291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_first, 0); 48301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("SBALE0 flags=0x%x\n", sbale[0].flags); 48311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("HEX DUMP OF SBALE1 PAYLOAD:\n"); 48321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, 48331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].length); 48341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4835fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske /* put allocated FSF request into hash table */ 4836fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_lock(&adapter->req_list_lock); 4837fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske zfcp_reqlist_add(adapter, fsf_req); 4838fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_unlock(&adapter->req_list_lock); 48391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48408a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin inc_seq_no = (fsf_req->qtcb != NULL); 48418a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 48421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("request queue of adapter %s: " 48431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "next free SBAL is %i, %i free SBALs\n", 48441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 48451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index, 48461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&req_queue->free_count)); 48471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("calling do_QDIO adapter %s, flags=0x%x, queue_no=%i, " 48491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "index_in_queue=%i, count=%i, buffers=%p\n", 48501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 48511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QDIO_FLAG_SYNC_OUTPUT, 48521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, fsf_req->sbal_first, fsf_req->sbal_number, 48531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &req_queue->buffer[fsf_req->sbal_first]); 48541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 48561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adjust the number of free SBALs in request queue as well as 48571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * position of first one 48581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 48591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_sub(fsf_req->sbal_number, &req_queue->free_count); 48601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("free_count=%d\n", atomic_read(&req_queue->free_count)); 48611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index += fsf_req->sbal_number; /* increase */ 48621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap if needed */ 48631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req); 48641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48658a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->issued = get_clock(); 48668a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 48671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = do_QDIO(adapter->ccw_device, 48681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QDIO_FLAG_SYNC_OUTPUT, 48691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); 48701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske dbg_tmp[0] = (unsigned long) sbale[0].addr; 4872fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske dbg_tmp[1] = (u64) retval; 4873fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); 4874fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske 48751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval)) { 48761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Queues are down..... */ 48771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 48782abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann del_timer(&fsf_req->timer); 4879fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_lock(&adapter->req_list_lock); 4880ca2d02c2f9ea476062ae181eec60b8bcd97857d6Heiko Carstens zfcp_reqlist_remove(adapter, fsf_req); 4881fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske spin_unlock(&adapter->req_list_lock); 4882fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske /* undo changes in request queue made for this request */ 48831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_qdio_zero_sbals(req_queue->buffer, 48841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_first, fsf_req->sbal_number); 48851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_add(fsf_req->sbal_number, &req_queue->free_count); 4886fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske req_queue->free_index -= fsf_req->sbal_number; 48871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q; 48881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ 4889fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske zfcp_erp_adapter_reopen(adapter, 0); 48901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 48911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->distance_from_int = new_distance_from_int; 48921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 48931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * increase FSF sequence counter - 48941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this must only be done for request successfully enqueued to 48951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * QDIO this rejected requests may be cleaned up by calling 48961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routines resulting in missing sequence counter values 48971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * otherwise, 48981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 48998a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 49001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't increase for unsolicited status */ 49018a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (inc_seq_no) 49021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fsf_req_seq_no++; 49038a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 49041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* count FSF requests pending */ 4905fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3Volker Sameske atomic_inc(&adapter->reqs_active); 49061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 49071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 49081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 49091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef ZFCP_LOG_AREA 4911