zfcp_fsf.c revision 8a36e4532ea10471f0a8605207d071361d7be2c3
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/s390/scsi/zfcp_fsf.c 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FCP adapter driver for IBM eServer zSeries 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright IBM Corp. 2002, 2004 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author(s): Martin Peschke <mpeschke@de.ibm.com> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Raimund Schroeder <raimund.schroeder@de.ibm.com> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Aron Zeh 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wolfgang Taphorn 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stefan Bader <stefan.bader@de.ibm.com> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Heiko Carstens <heiko.carstens@de.ibm.com> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Andreas Herrmann <aherrman@de.ibm.com> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Volker Sameske <sameske@de.ibm.com> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * any later version. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ZFCP_FSF_C_REVISION "$Revision: 1.92 $" 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "zfcp_ext.h" 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *); 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_open_port_handler(struct zfcp_fsf_req *); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_close_port_handler(struct zfcp_fsf_req *); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *); 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_fcp_command_task_management_handler( 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *); 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int zfcp_fsf_req_sbal_check( 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *, struct zfcp_qdio_queue *, int); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int zfcp_use_one_sbal( 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scatterlist *, int, struct scatterlist *, int); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct zfcp_fsf_req *zfcp_fsf_req_alloc(mempool_t *, int); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* association between FSF command and FSF QTCB type */ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 fsf_qtcb_type[] = { 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_FCP_CMND] = FSF_IO_COMMAND, 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_ABORT_FCP_CMND] = FSF_SUPPORT_COMMAND, 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_OPEN_PORT_WITH_DID] = FSF_SUPPORT_COMMAND, 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_OPEN_LUN] = FSF_SUPPORT_COMMAND, 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_LUN] = FSF_SUPPORT_COMMAND, 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_PORT] = FSF_SUPPORT_COMMAND, 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_PHYSICAL_PORT] = FSF_SUPPORT_COMMAND, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_SEND_ELS] = FSF_SUPPORT_COMMAND, 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_SEND_GENERIC] = FSF_SUPPORT_COMMAND, 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND, 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_EXCHANGE_PORT_DATA] = FSF_PORT_COMMAND, 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND, 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char zfcp_act_subtable_type[5][8] = { 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unknown", "OS", "WWPN", "DID", "LUN" 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************/ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************** FSF related Functions *************************/ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************/ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_alloc 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Obtains an fsf_req and potentially a qtcb (for all but 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsolicited requests) via helper functions 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Does some initial fsf request set-up. 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: pointer to allocated fsf_req if successfull 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL otherwise 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: none 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct zfcp_fsf_req * 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_alloc(mempool_t *pool, int req_flags) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t size; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *ptr; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req_flags & ZFCP_REQ_NO_QTCB) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = sizeof(struct zfcp_fsf_req); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = sizeof(struct zfcp_fsf_req_pool_element); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(pool != NULL)) 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = mempool_alloc(pool, GFP_ATOMIC); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = kmalloc(size, GFP_ATOMIC); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(NULL == ptr)) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(ptr, 0, size); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req_flags & ZFCP_REQ_NO_QTCB) { 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = (struct zfcp_fsf_req *) ptr; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = &((struct zfcp_fsf_req_pool_element *) ptr)->fsf_req; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb = 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &((struct zfcp_fsf_req_pool_element *) ptr)->qtcb; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->pool = pool; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fsf_req; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_free 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Frees the memory of an fsf_req (and potentially a qtcb) or 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns it into the pool via helper functions. 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: sod all 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: none 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1511db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmannvoid 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->pool != NULL)) 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(fsf_req, fsf_req->pool); 1561db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann else 1571db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann kfree(fsf_req); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * note: qdio queues shall be down (no ongoing inbound processing) 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req, *tmp; 1731db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann unsigned long flags; 1741db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann LIST_HEAD(remove_queue); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); 1771db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann list_splice_init(&adapter->fsf_req_list_head, &remove_queue); 1781db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann atomic_set(&adapter->fsf_reqs_active, 0); 1791db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) { 1821db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann list_del(&fsf_req->list); 1831db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann zfcp_fsf_req_dismiss(fsf_req); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann return 0; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_dismiss(struct zfcp_fsf_req *fsf_req) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_complete(fsf_req); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_complete 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Updates active counts and timers for openfcp-reqs 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * May cleanup request after req_eval returns 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - success 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * !0 - failure 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * context: 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req) 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cleanup; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) { 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Status read response received\n"); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: all cleanup handling is done in the callchain of 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the function call-chain below. 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_status_read_handler(fsf_req); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_protstatus_eval(fsf_req); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fsf_req may be deleted due to waking up functions, so 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cleanup is saved here and used later 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cleanup = 1; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cleanup = 0; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_COMPLETED; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* cleanup request if requested by initiator */ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(cleanup)) { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("removing FSF request %p\n", fsf_req); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lock must not be held here since it will be 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * grabed by the called routine, too 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2491db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann zfcp_fsf_req_free(fsf_req); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* notify initiator waiting for the requests completion */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("waking initiator of FSF request %p\n",fsf_req); 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: Race! We must not access fsf_req here as it might have been 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cleaned up already due to the set ZFCP_STATUS_FSFREQ_COMPLETED 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * flag. It's an improbable case. But, we have the same paranoia for 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the cleanup flag already. 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Might better be handled using complete()? 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (setting the flag and doing wakeup ought to be atomic 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with regard to checking the flag as long as waitqueue is 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * part of the to be released structure) 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up(&fsf_req->completion_wq); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_protstatus_eval 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates the QTCB of the finished FSF request 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and initiates appropriate actions 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (usually calling FSF command specific handlers) 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * context: 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 2888a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin struct fsf_qtcb *qtcb = fsf_req->qtcb; 2898a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin union fsf_prot_status_qual *prot_status_qual = 2908a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin &qtcb->prefix.prot_status_qual; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2928a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_hba_dbf_event_fsf_response(fsf_req); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("fsf_req 0x%lx has been dismissed\n", 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long) fsf_req); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_protstatus; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* log additional information provided by FSF (if any) */ 3038a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (unlikely(qtcb->header.log_length)) { 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do not trust them ;-) */ 3058a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) { 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: ULP (FSF logging) log data starts " 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "beyond end of packet header. Ignored. " 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(start=%i, size=%li)\n", 3108a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->header.log_start, 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct fsf_qtcb)); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto forget_log; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3148a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if ((size_t) (qtcb->header.log_start + qtcb->header.log_length) 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds > sizeof(struct fsf_qtcb)) { 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends " 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "beyond end of packet header. Ignored. " 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(start=%i, length=%i, size=%li)\n", 3198a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->header.log_start, 3208a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->header.log_length, 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct fsf_qtcb)); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto forget_log; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("ULP log data: \n"); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 3268a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin (char *) qtcb + qtcb->header.log_start, 3278a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->header.log_length); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds forget_log: 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF Protocol Status */ 3328a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin switch (qtcb->prefix.prot_status) { 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_GOOD: 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_FSF_STATUS_PRESENTED: 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_QTCB_VERSION_ERROR: 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: The adapter %s contains " 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "microcode of version 0x%x, the device driver " 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "only supports 0x%x. Aborting.\n", 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 3438a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin prot_status_qual->version_error.fsf_version, 3448a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_QTCB_VERSION); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_SEQ_NUMB_ERROR: 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Sequence number mismatch between " 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "driver (0x%x) and adapter %s (0x%x). " 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Restarting all operations on this adapter.\n", 3538a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->prefix.req_seq_no, 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 3558a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin prot_status_qual->sequence_error.exp_req_seq_no); 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_UNSUPP_QTCB_TYPE: 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: Packet header type used by the " 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "device driver is incompatible with " 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that used on adapter %s. " 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this adapter.\n", 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_HOST_CONNECTION_INITIALIZING: 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(adapter->status)); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_DUPLICATE_REQUEST_ID: 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->qtcb) { 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx " 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to the adapter %s is ambiguous. " 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this " 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter.\n", 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *(unsigned long long *) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (&fsf_req->qtcb->bottom.support. 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_handle), 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The request identifier %p " 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to the adapter %s is ambiguous. " 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this " 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter. " 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(bug: got this for an unsolicited " 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "status read request)\n", 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req, 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_LINK_DOWN: 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 'test and set' is not atomic here - 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's ok as long as calls to our response queue handler 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (and thus execution of this code here) are serialized 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by the qdio module 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &adapter->status)) { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->prefix.prot_status_qual. 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locallink_error.code) { 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PSQ_LINK_NOLIGHT: 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("The local link to adapter %s " 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is down (no light detected).\n", 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter( 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter)); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PSQ_LINK_WRAPPLUG: 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("The local link to adapter %s " 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is down (wrap plug detected).\n", 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter( 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter)); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PSQ_LINK_NOFCP: 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("The local link to adapter %s " 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is down (adjacent node on " 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "link does not support FCP).\n", 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter( 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter)); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("The local link to adapter %s " 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is down " 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(warning: unknown reason " 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "code).\n", 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter( 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter)); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Due to the 'erp failed' flag the adapter won't 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * be recovered but will be just set to 'blocked' 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state. All subordinary devices will have state 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 'blocked' and 'erp failed', too. 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thus the adapter is still able to provide 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 'link up' status without being flooded with 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * requests. 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (note: even 'close port' is not permitted) 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Stopping all operations for adapter " 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s.\n", 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_COMMON_ERP_FAILED, 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &adapter->status); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_REEST_QUEUE: 4638a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("The local link to adapter with " 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s was re-plugged. " 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Re-starting operations on this adapter.\n", 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* All ports should be marked as ready to run again */ 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_modify_adapter_status(adapter, 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_COMMON_RUNNING, 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_SET); 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_COMMON_ERP_FAILED); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PROT_ERROR_STATE: 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: The adapter %s " 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "has entered the error state. " 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Restarting all operations on this " 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter.\n", 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Transfer protocol status information " 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "provided by the adapter %s " 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is not compatible with the device driver. " 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this adapter. " 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x).\n", 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 4958a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin qtcb->prefix.prot_status); 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_protstatus: 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always call specific handlers to give them a chance to do 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * something meaningful even in error cases 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_fsfstatus_eval(fsf_req); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_fsfstatus_eval 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FSF status of completed FSF request 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and acts accordingly 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF Status */ 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_COMMAND: 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Command issued by the device driver is " 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "not known by the adapter %s " 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this adapter. " 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x).\n", 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(fsf_req->adapter), 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_command); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_RSP_AVAILABLE: 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("FCP Sense data will be presented to the " 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "SCSI stack.\n"); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_fsfstatus_qual_eval(fsf_req); 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always call specific handlers to give them a chance to do 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * something meaningful even in error cases 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_dispatch(fsf_req); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_fsfstatus_qual_eval 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FSF status-qualifier of completed FSF request 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and acts accordingly 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_FCP_RSP_AVAILABLE: 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_RETRY_IF_POSSIBLE: 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The SCSI-stack may now issue retries or escalate */ 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_COMMAND_ABORTED: 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Carry the aborted state on to upper layer */ 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTED; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_NO_RECOM: 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: No recommendation could be given for a" 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "problem on the adapter %s " 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Stopping all operations on this adapter. ", 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(fsf_req->adapter)); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_PROGRAMMING_ERROR: 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer " 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s)\n", 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(fsf_req->adapter)); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_NO_RETRY_POSSIBLE: 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dealt with in the respective functions */ 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Additional status info could " 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "not be interpreted properly.\n"); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_dispatch 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: calls the appropriate command specific handler 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_erp_action *erp_action = fsf_req->erp_action; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->fsf_command) { 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_FCP_CMND: 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_fcp_command_handler(fsf_req); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_ABORT_FCP_CMND: 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_abort_fcp_command_handler(fsf_req); 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_SEND_GENERIC: 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_ct_handler(fsf_req); 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_OPEN_PORT_WITH_DID: 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_open_port_handler(fsf_req); 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_OPEN_LUN: 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_open_unit_handler(fsf_req); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_CLOSE_LUN: 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_close_unit_handler(fsf_req); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_CLOSE_PORT: 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_close_port_handler(fsf_req); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_CLOSE_PHYSICAL_PORT: 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_close_physical_port_handler(fsf_req); 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_EXCHANGE_CONFIG_DATA: 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_exchange_config_data_handler(fsf_req); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_EXCHANGE_PORT_DATA: 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_exchange_port_data_handler(fsf_req); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_SEND_ELS: 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_els_handler(fsf_req); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_DOWNLOAD_CONTROL_FILE: 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_control_file_handler(fsf_req); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_UPLOAD_CONTROL_FILE: 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_control_file_handler(fsf_req); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Command issued by the device driver is " 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "not supported by the adapter %s\n", 6898a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_get_busid_by_adapter(adapter)); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->fsf_command != fsf_req->qtcb->header.fsf_command) 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Command issued by the device driver differs " 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "from the command returned by the adapter %s " 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x, 0x%x).\n", 6958a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_get_busid_by_adapter(adapter), 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->fsf_command, 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_command); 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!erp_action) 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_async_handler(erp_action, 0); 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_status_read 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: initiates a Status Read command at the specified adapter 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_status_read_buffer *status_buffer; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS, 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_flags | ZFCP_REQ_NO_QTCB, 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->pool.fsf_req_status_read, 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create unsolicited status " 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "buffer for adapter %s.\n", 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req_create; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_STATUS; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = 2; 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer = 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_alloc(adapter->pool.data_status_read, GFP_ATOMIC); 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!status_buffer) { 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: could not get some buffer\n"); 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_buf; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer)); 748059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) status_buffer; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* insert pointer to respective buffer */ 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_curr(fsf_req); 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale->addr = (void *) status_buffer; 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale->length = sizeof(struct fsf_status_read_buffer); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(fsf_req, NULL); 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: Could not set-up unsolicited status " 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "environment.\n"); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req_send; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Status Read request initiated (adapter%s)\n", 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req_send: 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(status_buffer, adapter->pool.data_status_read); 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_buf: 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req_create: 7738a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req) 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_status_read_buffer *status_buffer; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 787059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_lock_irqsave(&zfcp_data.config_lock, flags); 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(port, &adapter->port_list_head, list) 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port->d_id == (status_buffer->d_id & ZFCP_DID_MASK)) 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_unlock_irqrestore(&zfcp_data.config_lock, flags); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!port || (port->d_id != (status_buffer->d_id & ZFCP_DID_MASK))) { 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Reopen port indication received for" 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nonexisting port with d_id 0x%08x on " 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s. Ignored.\n", 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer->d_id & ZFCP_DID_MASK, 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (status_buffer->status_subtype) { 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT: 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 3, "unsol_pc_phys:"); 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(port, 0); 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SUB_ERROR_PORT: 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "unsol_pc_err:"); 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_shutdown(port, 0); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "unsol_unk_sub:"); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &status_buffer->status_subtype, sizeof (u32)); 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Undefined status subtype received " 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for a reopen indication on port with " 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "d_id 0x%08x on the adapter %s. " 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Ignored. (debug info 0x%x)\n", 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer->d_id, 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer->status_subtype); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_status_read_handler 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Open Port command 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_status_read_buffer *status_buffer = 846059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann (struct fsf_status_read_buffer *) fsf_req->data; 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { 8498a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer); 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(status_buffer, adapter->pool.data_status_read); 8511db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann zfcp_fsf_req_free(fsf_req); 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8558a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_hba_dbf_event_fsf_unsol("read", adapter, status_buffer); 8568a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (status_buffer->status_type) { 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_PORT_CLOSED: 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_status_read_port_closed(fsf_req); 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_INCOMING_ELS: 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_incoming_els(fsf_req); 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SENSE_DATA_AVAIL: 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n", 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Bit error threshold data received:\n"); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) status_buffer, 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fsf_status_read_buffer)); 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_LINK_DOWN: 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:"); 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Local link to adapter %s is down\n", 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &adapter->status); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_failed(adapter); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_LINK_UP: 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "unsol_link_up:"); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Local link to adapter %s was replugged. " 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Restarting operations on this adapter\n", 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* All ports should be marked as ready to run again */ 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_modify_adapter_status(adapter, 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_COMMON_RUNNING, 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_SET); 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_COMMON_ERP_FAILED); 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_CFDC_UPDATED: 9038a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_access_changed(adapter); 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_CFDC_HARDENED: 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (status_buffer->status_subtype) { 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE: 9118a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("CFDC of adapter %s saved on SE\n", 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2: 9158a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("CFDC of adapter %s has been copied " 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to the secondary SE\n", 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9208a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("CFDC of adapter %s has been hardened\n", 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9268a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown " 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "type was received (debug info 0x%x)\n", 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer->status_type); 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Dump of status_read_buffer %p:\n", 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status_buffer); 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) status_buffer, 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fsf_status_read_buffer)); 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(status_buffer, adapter->pool.data_status_read); 9371db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann zfcp_fsf_req_free(fsf_req); 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * recycle buffer and start new request repeat until outbound 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * queue is empty or adapter shutdown is requested 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(qdio): 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we may wait in the req_create for 5s during shutdown, so 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qdio_cleanup will have to wait at least that long before returning 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with failure to allow us a proper cleanup under all circumstances 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocation failure possible? (Is this code needed?) 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_status_read(adapter, 0); 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Failed to create unsolicited status read " 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request for the adapter %s.\n", 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* temporary fix to avoid status read buffer shortage */ 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->status_read_failed++; 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ZFCP_STATUS_READS_RECOM - adapter->status_read_failed) 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds < ZFCP_STATUS_READ_FAILED_THRESHOLD) { 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("restart adapter %s due to status read " 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "buffer shortage\n", 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_abort_fcp_command 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: tells FSF to abort a running SCSI command 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(design): should be watched by a timeout !!! 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(design) shouldn't this be modified to return an int 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * also...don't know how though 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct zfcp_fsf_req * 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_abort_fcp_command(unsigned long old_req_id, 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter, 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit, int req_flags) 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_flags, adapter->pool.fsf_req_abort, 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Failed to create an abort command " 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request for lun 0x%016Lx on port 0x%016Lx " 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s.\n", 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) unit; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handles of unit and its parent port in QTCB */ 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handle of request which should be aborted */ 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id; 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_start_scsi_er_timer(adapter); 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(fsf_req, NULL); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&adapter->scsi_er_timer); 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Failed to send abort command request " 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n", 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, unit->fcp_lun); 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Abort FCP Command request initiated " 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter%s, port d_id=0x%08x, " 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit x%016Lx, old_req_id=0x%lx)\n", 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->d_id, 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, old_req_id); 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fsf_req; 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_abort_fcp_command_handler 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Abort FCP Command request 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 1057059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit; 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char status_qual = 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->qtcb->header.fsf_status_qual.word[0]; 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&new_fsf_req->adapter->scsi_er_timer); 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */ 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1068059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) new_fsf_req->data; 1069059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (new_fsf_req->qtcb->header.fsf_status) { 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status_qual >> 4 != status_qual % 0xf) { 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv0"); 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * In this case a command that was sent prior to a port 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reopen was aborted (handles are different). This is 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fine. 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for " 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s invalid. " 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally.\n", 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &new_fsf_req->qtcb->header. 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual, 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Let's hope this sorts out the mess */ 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv1"); 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status_qual >> 4 != status_qual % 0xf) { 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2 */ 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv0"); 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * In this case a command that was sent prior to a unit 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reopen was aborted (handles are different). 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is fine. 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("Warning: Temporary LUN identifier 0x%x of LUN " 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen in rare cases. " 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Trying to re-establish link.\n", 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Status qualifier data:\n"); 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &new_fsf_req->qtcb->header. 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual, 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Let's hope this sorts out the mess */ 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv1"); 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_COMMAND_DOES_NOT_EXIST: 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 3, 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_no_exist"); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to " 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be reopened\n", unit->port->wwpn, 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 2, 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_pboxed"); 1148d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_BOXED: 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s needs " 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to be reopened\n", 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); 1160d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_unit_boxed(unit); 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) { 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 117065a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SCSI stack will escalate */ 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 1, 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->qtcb->header.fsf_status_qual.word[0]); 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 0, 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(new_fsf_req->adapter->erp_dbf, 0, 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &new_fsf_req->qtcb->header. 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_status_qual.word[0], sizeof (u32)); 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED; 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fsf_req->qtcb->header.fsf_status); 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(new_fsf_req->adapter->erp_dbf, 0, 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_inval:"); 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(new_fsf_req->adapter->erp_dbf, 0, 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &new_fsf_req->qtcb->header.fsf_status, 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_use_one_sbal - checks whether req buffer and resp bother each fit into 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one SBALE 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Two scatter-gather lists are passed, one for the reqeust and one for the 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response. 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_use_one_sbal(struct scatterlist *req, int req_count, 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scatterlist *resp, int resp_count) 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((req_count == 1) && 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (resp_count == 1) && 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (((unsigned long) zfcp_sg_to_address(&req[0]) & 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAGE_MASK) == 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((unsigned long) (zfcp_sg_to_address(&req[0]) + 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req[0].length - 1) & PAGE_MASK)) && 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (((unsigned long) zfcp_sg_to_address(&resp[0]) & 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAGE_MASK) == 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((unsigned long) (zfcp_sg_to_address(&resp[0]) + 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resp[0].length - 1) & PAGE_MASK))); 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS) 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ct: pointer to struct zfcp_send_ct which conatins all needed data for 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the request 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: pointer to memory pool, if non-null this pool is used to allocate 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a struct zfcp_fsf_req 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @erp_action: pointer to erp_action, if non-null the Generic Service request 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is sent within error recovery 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_erp_action *erp_action) 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = ct->port; 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = port->adapter; 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC, 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool, &lock_flags, &fsf_req); 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create CT request (FC-GS) for " 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter: %s\n", 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req; 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (erp_action != NULL) { 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = fsf_req; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->erp_action = erp_action; 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_use_one_sbal(ct->req, ct->req_count, 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->resp, ct->resp_count)){ 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* both request buffer and response buffer 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fit into one sbale each */ 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].addr = zfcp_sg_to_address(&ct->req[0]); 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].length = ct->req[0].length; 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].length = ct->resp[0].length; 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (adapter->supported_features & 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_FEATURE_ELS_CT_CHAINED_SBALS) { 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try to use chained SBALs */ 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->req, ct->req_count, 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_CT_REQ); 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of CT request failed " 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.req_buf_length = bytes; 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ct->resp, ct->resp_count, 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_CT_REQ); 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of CT request failed " 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.resp_buf_length = bytes; 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reject send generic request */ 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "error: microcode does not support chained SBALs," 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CT request too big (adapter %s)\n", 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EOPNOTSUPP; 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* settings in QTCB */ 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = port->handle; 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.timeout = ct->timeout; 1334059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) ct; 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13368a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_ct_request(fsf_req); 13378a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_send(fsf_req, ct->timer); 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: initiation of CT request failed " 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), port->wwpn); 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("CT request initiated (adapter %s, port 0x%016Lx)\n", 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), port->wwpn); 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_send: 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (erp_action != NULL) { 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req: 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_ct_handler - handler for Generic Service requests 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1367059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Data specific for the Generic Service request is passed using 1368059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * fsf_req->data. There we find the pointer to struct zfcp_send_ct. 1369059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Usually a specific handler for the CT request is called which is 1370059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * found in this structure. 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_send_ct *send_ct; 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 1384059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann send_ct = (struct zfcp_send_ct *) fsf_req->data; 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = send_ct->port; 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 13968a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_ct_response(fsf_req); 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (adapter->fc_service_class <= 3) { 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: adapter %s does not support fc " 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "class %d.\n", 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_service_class); 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: The fibre channel class at the " 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s is invalid. " 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info %d)\n", 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_service_class); 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]){ 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reopening link to port */ 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_test_link(port); 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x " 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "arrived.\n", 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("access denied, cannot send generic service " 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "command (adapter %s, port d_id=0x%08x)\n", 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GENERIC_COMMAND_REJECTED: 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("generic service command rejected " 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port d_id=0x%08x)\n", 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej"); 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Temporary port identifier 0x%x for port " 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may " 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "happen occasionally.\n", port->handle, 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("status qualifier:\n"); 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv"); 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(adapter, 0); 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("port needs to be reopened " 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port d_id=0x%08x)\n", 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->d_id); 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); 1493d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(port); 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* following states should never occure, all cases avoided 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in zfcp_fsf_send_ct - but who knows ... */ 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PAYLOAD_SIZE_MISMATCH: 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("payload size mismatch (adapter: %s, " 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "req_buf_length=%d, resp_buf_length=%d)\n", 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_REQUEST_SIZE_TOO_LARGE: 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("request size too large (adapter: %s, " 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "req_buf_length=%d)\n", 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length); 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_RESPONSE_SIZE_TOO_LARGE: 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("response size too large (adapter: %s, " 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SBAL_MISMATCH: 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, " 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", header->fsf_status); 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:"); 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof (u32)); 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_ct->status = retval; 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (send_ct->handler != NULL) 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_ct->handler(send_ct->handler_data); 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_els - initiate an ELS command (FC-FS) 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @els: pointer to struct zfcp_send_els which contains all needed data for 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the command. 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_els(struct zfcp_send_els *els) 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fc_id_t d_id; 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d_id = els->d_id; 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = els->adapter; 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_REQ_AUTO_CLEANUP, 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, &lock_flags, &fsf_req); 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of ELS request failed " 15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port d_id: 0x%08x)\n", 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req; 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_use_one_sbal(els->req, els->req_count, 15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds els->resp, els->resp_count)){ 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* both request buffer and response buffer 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fit into one sbale each */ 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; 15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].addr = zfcp_sg_to_address(&els->req[0]); 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[2].length = els->req[0].length; 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].length = els->resp[0].length; 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (adapter->supported_features & 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_FEATURE_ELS_CT_CHAINED_SBALS) { 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try to use chained SBALs */ 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds els->req, els->req_count, 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_ELS_REQ); 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of ELS request failed " 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port d_id: 0x%08x)\n", 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) { 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.req_buf_length = bytes; 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SBAL_FLAGS0_TYPE_WRITE_READ, 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds els->resp, els->resp_count, 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_ELS_REQ); 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes <= 0) { 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: creation of ELS request failed " 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port d_id: 0x%08x)\n", 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes == 0) { 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = bytes; 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.resp_buf_length = bytes; 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reject request */ 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: microcode does not support chained SBALs" 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ", ELS request too big (adapter %s, " 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port d_id: 0x%08x)\n", 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EOPNOTSUPP; 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* settings in QTCB */ 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.d_id = d_id; 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; 1637059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) els; 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16418a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_els_request(fsf_req); 16428a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_send(fsf_req, els->timer); 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: initiation of ELS request failed " 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port d_id: 0x%08x)\n", 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port d_id: " 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_send: 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req: 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_els_handler - handler for ELS commands 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1671059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Data specific for the ELS command is passed using 1672059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * fsf_req->data. There we find the pointer to struct zfcp_send_els. 1673059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * Usually a specific handler for the ELS command is called which is 1674059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann * found in this structure. 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 168064b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann fc_id_t d_id; 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_send_els *send_els; 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1687059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann send_els = (struct zfcp_send_els *) fsf_req->data; 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = send_els->adapter; 168964b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann port = send_els->port; 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d_id = send_els->d_id; 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 17008a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_san_dbf_event_els_response(fsf_req); 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (adapter->fc_service_class <= 3) { 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: adapter %s does " 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "not support fibrechannel class %d.\n", 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_service_class); 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: The fibrechannel class at " 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s is invalid. " 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info %d)\n", 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_service_class); 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]){ 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); 172764b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann if (port && (send_els->ls_code != ZFCP_LS_ADISC)) 172864b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann zfcp_test_link(port); 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_handle_els_rjt(header->fsf_status_qual.word[1], 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (struct zfcp_ls_rjt_par *) 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[2]); 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_RETRY_IF_POSSIBLE: 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry"); 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x\n", 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char*)header->fsf_status_qual.word, 16); 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ELS_COMMAND_REJECTED: 17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("ELS has been rejected because command filter " 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "prohibited sending " 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, port d_id: 0x%08x)\n", 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PAYLOAD_SIZE_MISMATCH: 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ELS request size and ELS response size must be either " 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "both 0, or both greater than 0 " 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, req_buf_length=%d resp_buf_length=%d)\n", 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_REQUEST_SIZE_TOO_LARGE: 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Length of the ELS request buffer, " 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "specified in QTCB bottom, " 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "exceeds the size of the buffers " 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that have been allocated for ELS request data " 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, req_buf_length=%d)\n", 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length); 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_RESPONSE_SIZE_TOO_LARGE: 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Length of the ELS response buffer, " 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "specified in QTCB bottom, " 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "exceeds the size of the buffers " 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that have been allocated for ELS response data " 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, resp_buf_length=%d)\n", 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->resp_buf_length); 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SBAL_MISMATCH: 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* should never occure, avoided in zfcp_fsf_send_els */ 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, " 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "resp_buf_length=%d)\n", 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->req_buf_length, bottom->resp_buf_length); 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("access denied, cannot send ELS command " 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port d_id=0x%08x)\n", 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), d_id); 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port != NULL) 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bug: An unknown FSF Status was presented " 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter: %s, fsf_status=0x%08x)\n", 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval"); 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof(u32)); 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_els->status = retval; 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (send_els->handler != 0) 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_els->handler(send_els->handler_data); 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_EXCHANGE_CONFIG_DATA, 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_REQ_AUTO_CLEANUP, 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &(erp_action->fsf_req)); 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create exchange configuration " 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "data request for adapter %s.\n", 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->sbal_curr, 0); 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->erp_action = erp_action; 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->bottom.config.feature_selection = 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING); 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("error: Could not send exchange configuration data " 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "command on the adapter %s\n", 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(erp_action->fsf_req); 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("exchange configuration data request initiated " 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s)\n", 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_config_evaluate 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: fsf_req which belongs to xchg config data request 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @xchg_ok: specifies if xchg config data was incomplete or complete (0/1) 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: -EIO on error, 0 otherwise 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_config *bottom; 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.config; 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", 19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->low_qtcb_version, bottom->high_qtcb_version); 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fsf_lic_version = bottom->lic_version; 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->supported_features = bottom->supported_features; 19226f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwpn = 0; 19236f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwnn = 0; 19246f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_d_id = 0; 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (xchg_ok) { 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->wwnn = bottom->nport_serv_param.wwnn; 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->wwpn = bottom->nport_serv_param.wwpn; 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->s_id = bottom->s_id & ZFCP_DID_MASK; 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_topology = bottom->fc_topology; 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_link_speed = bottom->fc_link_speed; 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hydra_version = bottom->adapter_type; 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->wwnn = 0; 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->wwpn = 0; 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->s_id = 0; 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_topology = 0; 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_link_speed = 0; 19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hydra_version = 0; 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19426f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> if (adapter->fc_topology == FSF_TOPO_P2P) { 19436f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; 19446f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwpn = bottom->plogi_payload.wwpn; 19456f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwnn = bottom->plogi_payload.wwnn; 19466f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> } 19476f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){ 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hardware_version = bottom->hardware_version; 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(adapter->serial_number, bottom->serial_number, 17); 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EBCASC(adapter->serial_number, sizeof(adapter->serial_number)); 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19546f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n" 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "WWNN 0x%016Lx, " 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "WWPN 0x%016Lx, " 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "S_ID 0x%08x,\n" 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter version 0x%x, " 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "LIC version 0x%x, " 19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "FC link speed %d Gb/s\n", 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->wwnn, 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->wwpn, 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned int) adapter->s_id, 19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hydra_version, 19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fsf_lic_version, 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fc_link_speed); 19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) { 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: the adapter %s " 19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "only supports newer control block " 19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "versions in comparison to this device " 19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "driver (try updated device driver)\n", 19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "low_qtcb_ver"); 19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ZFCP_QTCB_VERSION > bottom->high_qtcb_version) { 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: the adapter %s " 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "only supports older control block " 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "versions than this device driver uses" 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(consider a microcode upgrade)\n", 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "high_qtcb_ver"); 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19883859f6a248cbdfbe7b41663f3a2b51f48e30b281Andreas Herrmann zfcp_set_fc_host_attrs(adapter); 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_exchange_config_data_handler 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Exchange Configuration Data command 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_config *bottom; 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) 20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (adapter->fc_topology) { 20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_TOPO_P2P: 20166f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> ZFCP_LOG_NORMAL("Point-to-Point fibrechannel " 20176f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "configuration detected at adapter %s\n" 20186f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "Peer WWNN 0x%016llx, " 20196f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "peer WWPN 0x%016llx, " 20206f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "peer d_id 0x%06x\n", 20216f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> zfcp_get_busid_by_adapter(adapter), 20226f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwnn, 20236f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_wwpn, 20246f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->peer_d_id); 20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "top-p-to-p"); 20276f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> break; 20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_TOPO_AL: 20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel " 20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "topology detected at adapter %s " 20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unsupported, shutting down adapter\n", 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "top-al"); 20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_TOPO_FABRIC: 20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Switched fabric fibrechannel " 20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "network detected at adapter %s.\n", 20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The fibrechannel topology " 20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "reported by the exchange " 20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "configuration command for " 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the adapter %s is not " 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "of a type known to the zfcp " 20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "driver, shutting down adapter\n", 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20506f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> adapter->fc_topology = FSF_TOPO_ERROR; 20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unknown-topo"); 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.config; 20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "allowed by the adapter %s " 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is lower than the minimum " 20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "required by the driver (%ld bytes).\n", 20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->max_qtcb_size, 20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct fsf_qtcb)); 20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "qtcb-size"); 20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_event(fsf_req->adapter->erp_dbf, 0, 20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &bottom->max_qtcb_size, sizeof (u32)); 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, 20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &adapter->status); 20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "xchg-inco"); 20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Local link to adapter %s is down\n", 20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | 20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, 20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &adapter->status); 20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_failed(adapter); 20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_event(fsf_req->adapter->erp_dbf, 0, 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, sizeof (u32)); 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(adapter, 0); 20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data - request information about local port 21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: for which port data is requested 21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @data: response to exchange port data request 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_port *data) 21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct timer_list *timer; 21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){ 21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: exchange port data " 21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "command not supported by adapter %s\n", 21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); 21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!timer) 21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, 0, &lock_flags, &fsf_req); 21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Out of resources. Could not create an " 21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "exchange port data request for" 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the adapter %s.\n", 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2137059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) data; 2138059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(timer); 21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer->function = zfcp_fsf_request_timeout_handler; 21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer->data = (unsigned long) adapter; 21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; 21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(fsf_req, timer); 21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an exchange port data " 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "command on the adapter %s\n", 21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n", 21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, 21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_event(fsf_req->completion_wq, 21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer_sync(timer); 21681db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann zfcp_fsf_req_free(fsf_req); 21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(timer); 21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request 21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fsf_req: pointer to struct zfcp_fsf_req 21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) 21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_port *bottom; 2183059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct fsf_qtcb_bottom_port *data; 2184059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 2185059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann data = (struct fsf_qtcb_bottom_port*) fsf_req->data; 21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) 21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.port; 21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(data, bottom, sizeof(*data)); 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng"); 21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_event(fsf_req->adapter->erp_dbf, 0, 21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, sizeof(u32)); 22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_port 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_port(struct zfcp_erp_action *erp_action) 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_OPEN_PORT_WITH_DID, 22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &(erp_action->fsf_req)); 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create open port request " 22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s.\n", 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, 22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->sbal_curr, 0); 22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; 22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); 2240059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann erp_action->fsf_req->data = (unsigned long) erp_action->port; 22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->erp_action = erp_action; 22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); 22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send open port request for " 22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s.\n", 22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(erp_action->fsf_req); 22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("open port request initiated " 22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_port_handler 22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Open Port command 22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 22721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) 22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 22761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 22771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_plogi *plogi; 22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 22801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 22861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_ALREADY_OPEN: 22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: remote port 0x%016Lx on adapter %s " 22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is already open.\n", 22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_popen"); 22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a bug, however operation should continue normally 23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if it is simply ignored 23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot open port 0x%016Lx " 23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 23091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 23111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 23161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 23221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 23231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 23241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: 23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: The FSF adapter is out of resources. " 23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The remote port 0x%016Lx on adapter %s " 23291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "could not be opened. Disabling it.\n", 23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_max_ports"); 23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_failed(port); 23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 23401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 23481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_NO_RETRY_POSSIBLE: 23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("The remote port 0x%016Lx on " 23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s could not be opened. " 23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Disabling it.\n", 23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port)); 23571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_no_retry"); 23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_failed(port); 23601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 23631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 23661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 23671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 23691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 23701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 23771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save port handle assigned by FSF */ 23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle = header->port_handle; 23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("The remote port 0x%016Lx via adapter %s " 23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was opened, it's port handle is 0x%x\n", 23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port), 23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle); 23831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark port as open */ 23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPEN | 23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 2386d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 2387d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann ZFCP_STATUS_COMMON_ACCESS_BOXED, 2388d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann &port->status); 23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check whether D_ID has changed during open */ 23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: This check is not airtight, as the FCP channel does 23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not monitor closures of target port connections caused on 23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the remote side. Thus, they might miss out on invalidating 23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locally cached WWPNs (and other N_Port parameters) of gone 23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * target ports. So, our heroic attempt to make things safe 23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could be undermined by 'open port' response data tagged with 23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * obsolete WWPNs. Another reason to monitor potential 23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connection closures ourself at least (by interpreting 24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * incoming ELS' and unsolicited status). It just crosses my 24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mind that one should be able to cross-check by means of 24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * another GID_PN straight after a port has been opened. 24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alternately, an ADISC/PDISC ELS should suffice, as well. 24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds plogi = (struct fsf_plogi *) fsf_req->qtcb->bottom.support.els; 24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, &port->status)) 24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->qtcb->bottom.support.els1_length < 24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((((unsigned long) &plogi->serv_param.wwpn) - 24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((unsigned long) plogi)) + sizeof (u64))) { 24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "warning: insufficient length of " 24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "PLOGI payload (%i)\n", 24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.els1_length); 24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_short_plogi:"); 24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* skip sanity check and assume wwpn is ok */ 24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (plogi->serv_param.wwpn != port->wwpn) { 24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("warning: d_id of port " 24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx changed during " 24221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "open\n", port->wwpn); 24231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event( 24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_did_change:"); 24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask( 24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_PORT_DID_DID, 24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &port->status); 24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwnn = plogi->serv_param.wwnn; 24311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_OP_SUBTYPE: 24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* should never occure, subtype not set in zfcp_fsf_open_port */ 24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("unknown operation subtype (adapter: %s, " 24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "op_subtype=0x%x)\n", 24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), 24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.support.operation_subtype); 24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &port->status); 24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_port 24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: submit FSF command "close port" 24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_port(struct zfcp_erp_action *erp_action) 24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_PORT, 24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &(erp_action->fsf_req)); 24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create a close port request " 24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s.\n", 24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, 24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->sbal_curr, 0); 24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); 2494059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann erp_action->fsf_req->data = (unsigned long) erp_action->port; 24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->erp_action = erp_action; 24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->header.port_handle = 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->handle; 24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); 25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send a close port request for " 25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx on adapter %s.\n", 25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(erp_action->fsf_req); 25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("close port request initiated " 25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_port_handler 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close Port FSF command 25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req) 25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2534059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may happen " 25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "occasionally.\n", port->handle, 25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(port->adapter, 0); 25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note: FSF has actually closed the port in this case. 25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The status code is just daft. Fingers crossed for a change 25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("remote port 0x016%Lx on adapter %s closed, " 25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port handle 0x%x\n", port->wwpn, 25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->handle); 25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_modify_port_status(port, 25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_COMMON_OPEN, 25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_CLEAR); 25731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status); 25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, 25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &port->status); 25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_physical_port 25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: submit FSF command "close physical port" 25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of initiated FSF request 25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - request could not be initiated 25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) 26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_PHYSICAL_PORT, 26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &erp_action->fsf_req); 26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create close physical port " 26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request (adapter %s, port 0x%016Lx)\n", 26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, 26231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->sbal_curr, 0); 26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark port as being closed */ 26281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, 26291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &erp_action->port->status); 26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save a pointer to this port */ 2631059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann erp_action->fsf_req->data = (unsigned long) erp_action->port; 26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* port to be closeed */ 26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->header.port_handle = 26341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->handle; 26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->erp_action = erp_action; 26361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 26381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); 26391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 26401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send close physical port " 26411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "request (adapter %s, port 0x%016Lx)\n", 26421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 26431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 26441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(erp_action->fsf_req); 26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 26461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("close physical port request initiated " 26501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx)\n", 26511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 26521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn); 26531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 26541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 26551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 26561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 26571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_physical_port_handler 26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close Physical Port FSF command 26631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 26651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 26671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) 26681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 26701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_port *port; 26711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 26721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 26731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 26741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2675059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann port = (struct zfcp_port *) fsf_req->data; 26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 26771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 26791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change port status in our bookkeeping */ 26801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 26841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 26871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x invalid" 26881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx). " 26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally.\n", 26901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle, 26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), 26921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn); 26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 26941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 26981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 26991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(port->adapter, 0); 27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 27011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 27041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot close " 27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "physical port 0x%016Lx on adapter %s\n", 27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, zfcp_get_busid_by_port(port)); 27071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 27081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 27111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 27131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 27141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 27161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_access_denied(port); 27221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter " 27271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s needs to be reopened but it was attempted " 27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to close it physically.\n", 27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port)); 27311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_pboxed"); 2732d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(port); 27331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 27341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 27351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 27381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 27391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 27411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This will now be escalated by ERP */ 27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 27461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 27471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 27481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 27491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 27561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 27581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof (u32)); 27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Remote port 0x%016Lx via adapter %s " 27661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "physically closed, port handle 0x%x\n", 27671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wwpn, 27681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_port(port), port->handle); 27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* can't use generic zfcp_erp_modify_port_status because 27701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ZFCP_STATUS_COMMON_OPEN must not be reset for the port 27711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 27721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(unit, &port->unit_list_head, list) 27741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 27751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 27761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 27811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 27831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 27891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, &port->status); 27901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 27911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 27941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_unit 27951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 27971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 27991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 28001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * assumptions: This routine does not check whether the associated 28011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remote port has already been opened. This should be 28021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done by calling routines. Otherwise some status 28031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may be presented by FSF 28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 28051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) 28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 28091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 28131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_OPEN_LUN, 28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 28161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &(erp_action->fsf_req)); 28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create open unit request for " 28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s.\n", 28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 28221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->port->wwpn, 28231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, 28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->sbal_curr, 0); 28291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 28301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 28311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->header.port_handle = 28331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->handle; 28341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->bottom.support.fcp_lun = 28351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun; 28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->bottom.support.option = 28371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_OPEN_LUN_SUPPRESS_BOXING; 28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); 2839059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann erp_action->fsf_req->data = (unsigned long) erp_action->unit; 28401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->erp_action = erp_action; 28411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 28431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); 28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an open unit request " 28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s, port 0x%016Lx for " 28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx\n", 28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun); 28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(erp_action->fsf_req); 28521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 28541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Open LUN request initiated (adapter %s, " 28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, erp_action->unit->fcp_lun); 28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_open_unit_handler 28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 28691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Open LUN command 28701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 28711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 28731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 28741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) 28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 28801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 28811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_queue_designator *queue_designator; 28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 allowed, exclusive, readwrite; 28841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2885059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change unit status in our bookkeeping */ 28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 28901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 28941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 28951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator = &header->fsf_status_qual.fsf_queue_designator; 28961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds allowed = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED; 28981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE; 28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER; 29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 29021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_UNIT_SHARED | 29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_UNIT_READONLY, 29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 29071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 29081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 29101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x " 29111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for port 0x%016Lx on adapter %s invalid " 29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This may happen occasionally\n", 29131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_ph_nv"); 29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_ALREADY_OPEN: 29251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: Attempted to open unit 0x%016Lx on " 29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port 0x%016Lx on adapter %s twice.\n", 29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 29291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(adapter->erp_dbf, 0, 29301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_uopen"); 29311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 29321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 29351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot open unit 0x%016Lx on " 29361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port 0x%016Lx on adapter %s\n", 29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 29421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 29431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 29451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 29461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 29471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 29481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 29491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); 29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); 29561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 29631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); 2964d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 29671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_SHARING_VIOLATION: 29701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (header->fsf_status_qual.word[0] != 0) { 29711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port " 29721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "with WWPN 0x%Lx " 29731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "connected to the adapter %s " 29741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is already in use in LPAR%d, CSS%d\n", 29751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 29761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 29771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 29781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator->hla, 29791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue_designator->cssid); 29801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[4]; 29821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[5]; 29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 29841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 29851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 29871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 29881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access to FCP-LUN 0x%Lx at the " 29891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "remote port with WWPN 0x%Lx " 29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "connected to the adapter %s " 29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is denied (%s rule %d)\n", 29921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 29941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], 29961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule); 29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 29981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 30011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 30021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 30031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 30041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 2, 30051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_l_sh_vio"); 30061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); 30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); 30091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: 30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: The adapter ran out of resources. " 30141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "There is no handle (temporary port identifier) " 30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "available for unit 0x%016Lx on port 0x%016Lx " 30161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s\n", 30171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 30181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 30191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 30201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_max_units"); 30221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 30271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 30291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Re-establish link to port */ 30301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 303265a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 30331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 30361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 30371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 1, 30381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 30391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 30421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 30431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 30441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 30451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, 30461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 30471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 30481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 30501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_INVALID_COMMAND_OPTION: 30541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 30551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Invalid option 0x%x has been specified " 30561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "in QTCB bottom sent to the adapter %s\n", 30571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option, 30581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 30641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save LUN handle assigned by FSF */ 30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle = header->lun_handle; 30661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("unit 0x%016Lx on remote port 0x%016Lx on " 30671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s opened, port handle 0x%x\n", 30681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 30691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 30701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 30711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 30721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark unit as open */ 30731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 3074d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 3075d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann ZFCP_STATUS_COMMON_ACCESS_BOXED, 3076d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann &unit->status); 30771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){ 30781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!exclusive) 30791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, 30801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 30811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!readwrite) { 30831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, 30841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &unit->status); 30851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("read-only access for unit " 30861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, wwpn=0x%016Lx, " 30871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fcp_lun=0x%016Lx)\n", 30881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 30891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 30901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 30911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exclusive && !readwrite) { 30941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("exclusive access of read-only " 30951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit not supported\n"); 30961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 30971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 30981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_shutdown(unit, 0); 30991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!exclusive && readwrite) { 31001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("shared access of read-write " 31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit not supported\n"); 31021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_failed(unit); 31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_shutdown(unit, 0); 31051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 31091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 31121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 31131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 31141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status); 31151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(adapter->erp_dbf, 0, "fsf_s_inval:"); 31161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(adapter->erp_dbf, 0, 31171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof (u32)); 31181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 31191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 31221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status); 31231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 31241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 31251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_unit 31281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 31301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: address of fsf_req - request successfully initiated 31321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NULL - 31331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * assumptions: This routine does not check whether the associated 31351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remote port/lun has already been opened. This should be 31361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done by calling routines. Otherwise some status 31371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may be presented by FSF 31381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 31391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 31401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) 31411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 31421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 31431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 31441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 31451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 31471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(erp_action->adapter, 31481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FSF_QTCB_CLOSE_LUN, 31491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, 31501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->adapter->pool.fsf_req_erp, 31511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &(erp_action->fsf_req)); 31521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 31531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create close unit request for " 31541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on adapter %s.\n", 31551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 31561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 31571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 31581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 31591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, 31621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->sbal_curr, 0); 31631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; 31641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 31651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->header.port_handle = 31671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->handle; 31681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; 31691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); 3170059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann erp_action->fsf_req->data = (unsigned long) erp_action->unit; 31711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req->erp_action = erp_action; 31721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 31741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); 31751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 31761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send a close unit request for " 31771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx onadapter %s.\n", 31781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->unit->fcp_lun, 31791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, 31801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter)); 31811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(erp_action->fsf_req); 31821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->fsf_req = NULL; 31831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 31841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 31851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Close LUN request initiated (adapter %s, " 31871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 31881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(erp_action->adapter), 31891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds erp_action->port->wwpn, erp_action->unit->fcp_lun); 31901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 31911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, 31921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_flags); 31931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 31941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 31951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_close_unit_handler 31981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Close LUN FSF command 32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 32021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 32031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) 32051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 32061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 32071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 32081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3209059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 32101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 32121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't change unit status in our bookkeeping */ 32131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 32141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 32171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status) { 32181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 32201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 32211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid. This may " 32221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "happen in rare circumstances\n", 32231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 32241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 32261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 32271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 32281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 32291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 32301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 32311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 32321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 32331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 32371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary LUN identifier 0x%x of unit " 32381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 32391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen occasionally.\n", 32401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 32411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 32421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 32441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Status qualifier data:\n"); 32451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 32461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb->header.fsf_status_qual, 32471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 32481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 32491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_lhand_nv"); 32501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 32511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 32551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 32561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 32571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 32591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); 3260d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 32611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 32621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 32631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 32661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { 32671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 32681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* re-establish link to port */ 32691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 32701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 327165a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 32721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 32751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ERP strategy will escalate */ 32761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 32771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 32781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 32791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 32811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 32821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: Wrong status qualifier 0x%x arrived.\n", 32831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status_qual.word[0]); 32841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 32851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 32861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception( 32871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->erp_dbf, 0, 32881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status_qual.word[0], 32891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 32901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 32951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("unit 0x%016Lx on port 0x%016Lx on adapter %s " 32961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "closed, port handle 0x%x\n", 32971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 32981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 32991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 33001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 33011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mark unit as closed */ 33021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); 33031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 33041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 33051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 33071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " 33081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 33091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.fsf_status); 33101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 33111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 33121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fsf_req->qtcb->header.fsf_status, 33131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (u32)); 33141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 33151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 33181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &unit->status); 33191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 33201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 33211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 33231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) 33241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: adapter where scsi command is issued 33251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @unit: unit where command is sent to 33261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scsi_cmnd: scsi command to be sent 33271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @timer: timer to be started when request is initiated 33281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @req_flags: flags for fsf_request 33291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 33301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 33311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, 33321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit, 33331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_cmnd * scsi_cmnd, 33341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct timer_list *timer, int req_flags) 33351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 33361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 33371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu; 33381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int sbtype; 33391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 33401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int real_bytes = 0; 33411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 33421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mask; 33431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 33451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, 33461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->pool.fsf_req_scsi, 33471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 33481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval < 0)) { 33491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: Could not create FCP command request " 33501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "for unit 0x%016Lx on port 0x%016Lx on " 33511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 33521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 33531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 33541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 33551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_req_create; 33561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3358059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_get(unit); 3359059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->unit = unit; 33601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann /* associate FSF request with SCSI request (for look up on abort) */ 3362059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann scsi_cmnd->host_scribble = (char *) fsf_req; 3363059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 3364059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann /* associate SCSI command with FSF request */ 3365059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) scsi_cmnd; 33661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set handles of unit and its parent port in QTCB */ 33681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 33691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 33701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FSF does not define the structure of the FCP_CMND IU */ 33721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu = (struct fcp_cmnd_iu *) 33731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 33741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 33761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set depending on data direction: 33771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in SBALE (SB Type) 33781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in QTCB 33791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data direction bits in FCP_CMND IU 33801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 33811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (scsi_cmnd->sc_data_direction) { 33821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_NONE: 33831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; 33841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 33851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(qdio): 33861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * what is the correct type for commands 33871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without 'real' data buffers? 33881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 33891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_READ; 33901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 33911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_FROM_DEVICE: 33921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ; 33931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_READ; 33941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->rddata = 1; 33951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 33961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_TO_DEVICE: 33971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE; 33981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbtype = SBAL_FLAGS0_TYPE_WRITE; 33991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->wddata = 1; 34001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 34011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_BIDIRECTIONAL: 34021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 34031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 34041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dummy, catch this condition earlier 34051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in zfcp_scsi_queuecommand 34061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 34071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_scsi_cmnd; 34081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FC service class in QTCB (3 per default) */ 34111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class; 34121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FCP_LUN in FCP_CMND IU in QTCB */ 34141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->fcp_lun = unit->fcp_lun; 34151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = ZFCP_STATUS_UNIT_READONLY | ZFCP_STATUS_UNIT_SHARED; 34171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set task attributes in FCP_CMND IU in QTCB */ 34191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely((scsi_cmnd->device->simple_tags) || 34201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (atomic_test_mask(mask, &unit->status)))) 34211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_attribute = SIMPLE_Q; 34221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 34231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_attribute = UNTAGGED; 34241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set additional length of FCP_CDB in FCP_CMND IU in QTCB, if needed */ 34261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH)) { 34271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length 34281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds = (scsi_cmnd->cmd_len - FCP_CDB_LENGTH) >> 2; 34291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("SCSI CDB length is 0x%x, " 34301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "additional FCP_CDB length is 0x%x " 34311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(shifted right 2 bits)\n", 34321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmnd->cmd_len, 34331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length); 34341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 34361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy SCSI CDB (including additional length, if any) to 34371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FCP_CDB in FCP_CMND IU in QTCB 34381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 34391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len); 34401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FCP CMND IU length in QTCB */ 34421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length = 34431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_cmnd_iu) + 34441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->add_fcp_cdb_length + sizeof (fcp_dl_t); 34451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* generate SBALEs from data buffer */ 34471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds real_bytes = zfcp_qdio_sbals_from_scsicmnd(fsf_req, sbtype, scsi_cmnd); 34481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(real_bytes < 0)) { 34491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->sbal_number < ZFCP_MAX_SBALS_PER_REQ) { 34501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG( 34511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Data did not fit into available buffer(s), " 34521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "waiting for more...\n"); 34531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 34541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 34551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: No truncation implemented but " 34561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "required. Shutting down unit " 34571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx, " 34581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx)\n", 34591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 34601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 34611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 34621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_shutdown(unit, 0); 34631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 34641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_fit; 34661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set length of FCP data length in FCP_CMND IU in QTCB */ 34691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes); 34701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Sending SCSI command:\n"); 34721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 34731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) scsi_cmnd->cmnd, scsi_cmnd->cmd_len); 34741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 34761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * start QDIO request for this FSF request 34771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * covered by an SBALE) 34781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 34791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(fsf_req, timer); 34801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval < 0)) { 34811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send FCP command request " 34821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n", 34831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 34841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 34851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 34861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto send_failed; 34871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Send FCP Command initiated (adapter %s, " 34901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "port 0x%016Lx, unit 0x%016Lx)\n", 34911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 34921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 34931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 34941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto success; 34951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_failed: 34971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds no_fit: 34981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_scsi_cmnd: 3499059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_put(unit); 35001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 35011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 35021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmnd->host_scribble = NULL; 35031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds success: 35041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_req_create: 35051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 35061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 35071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 35081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 35101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_task_management 35111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 35121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: 35131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 35141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 35151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 35161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(design): should be watched by a timeout!!! 35171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(design) shouldn't this be modified to return an int 35181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * also...don't know how though 35191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 35201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 35211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct zfcp_fsf_req * 35221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, 35231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit, 35241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 tm_flags, int req_flags) 35251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 35261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 35271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 35281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu; 35291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 35301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 35311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup new FSF request */ 35331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, 35341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->pool.fsf_req_scsi, 35351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &lock_flags, &fsf_req); 35361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 35371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create FCP command (task " 35381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "management) request for adapter %s, port " 35391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " 0x%016Lx, unit 0x%016Lx.\n", 35401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 35411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, unit->fcp_lun); 35421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 35431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 35441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 35461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used to decide on proper handler in the return path, 35471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could be either zfcp_fsf_send_fcp_command_task_handler or 35481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_send_fcp_command_task_management_handler */ 35491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT; 35511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 35531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hold a pointer to the unit being target of this 35541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * task management request 35551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3556059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->data = (unsigned long) unit; 35571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FSF related fields in QTCB */ 35591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.lun_handle = unit->handle; 35601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.port_handle = unit->port->handle; 35611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; 35621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class; 35631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length = 35641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t); 35651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 35671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; 35681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 35691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set FCP related fields in FCP_CMND IU in QTCB */ 35711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu = (struct fcp_cmnd_iu *) 35721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 35731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->fcp_lun = unit->fcp_lun; 35741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_cmnd_iu->task_management_flags = tm_flags; 35751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start QDIO request for this FSF request */ 35771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_start_scsi_er_timer(adapter); 35781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(fsf_req, NULL); 35791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 35801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&adapter->scsi_er_timer); 35811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not send an FCP-command (task " 35821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "management) on adapter %s, port 0x%016Lx for " 35831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit LUN 0x%016Lx\n", 35841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 35851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 35861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 35871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 35881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 35891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 35901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 35911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("Send FCP Command (task management function) initiated " 35931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s, port 0x%016Lx, unit 0x%016Lx, " 35941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tm_flags=0x%x)\n", 35951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 35961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 35971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 35981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tm_flags); 35991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 36001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 36011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fsf_req; 36021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 36031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 36051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_handler 36061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 36071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: is called for finished Send FCP Command 36081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 36091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 36101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 36111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 36121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) 36131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 36141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = -EINVAL; 36151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_unit *unit; 36161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header; 36171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 subtable, rule, counter; 36181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header = &fsf_req->qtcb->header; 36201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) 3622059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = (struct zfcp_unit *) fsf_req->data; 36231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3624059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann unit = fsf_req->unit; 36251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 36271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* go directly to calls of special handlers */ 36281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 36291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 36301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* evaluate FSF status in QTCB */ 36321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 36331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 36351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary port identifier 0x%x for port " 36361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s invalid\n", 36371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 36381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 36391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 36401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 36411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 36421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 36431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_phand_nv"); 36441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 36451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 36461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 36471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 36491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Temporary LUN identifier 0x%x for unit " 36501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s is " 36511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "invalid. This may happen occasionally.\n", 36521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle, 36531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 36541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 36551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 36561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Status qualifier data:\n"); 36571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 36581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 36591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 36601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 36611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_uhand_nv"); 36621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 36631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 36641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 36651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_HANDLE_MISMATCH: 36671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The port handle 0x%x has changed " 36681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unexpectedly. (adapter %s, port 0x%016Lx, " 36691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx)\n", 36701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->handle, 36711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 36721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 36731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun); 36741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("status qualifier:\n"); 36751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, 36761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 36771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 36781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 36791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_hand_mis"); 36801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_reopen(unit->port->adapter, 0); 36811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 36821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 36831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 36851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->adapter->fc_service_class <= 3) { 36861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("error: The adapter %s does " 36871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "not support fibrechannel class %d.\n", 36881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 36891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->fc_service_class); 36901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 36911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The fibrechannel class at " 36921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s is invalid. " 36931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info %d)\n", 36941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 36951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->adapter->fc_service_class); 36961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 36971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 36981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_exception(fsf_req->adapter->erp_dbf, 0, 36991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_class_nsup"); 37001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 37011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 37021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCPLUN_NOT_VALID: 37051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: unit 0x%016Lx on port 0x%016Lx on " 37061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s does not have correct unit " 37071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "handle 0x%x\n", 37081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 37091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 37101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 37111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->handle); 37121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status qualifier:\n"); 37131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 37141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &header->fsf_status_qual, 37151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (union fsf_status_qual)); 37161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 37171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_fcp_lun_nv"); 37181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_port_reopen(unit->port, 0); 37191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 37201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 37231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Access denied, cannot send FCP command to " 37241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx on port 0x%016Lx on " 37251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", unit->fcp_lun, unit->port->wwpn, 37261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 37271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (counter = 0; counter < 2; counter++) { 37281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subtable = header->fsf_status_qual.halfword[counter * 2]; 37291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rule = header->fsf_status_qual.halfword[counter * 2 + 1]; 37301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (subtable) { 37311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_OS: 37321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: 37331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_PORT_DID: 37341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_SUBTABLE_LUN: 37351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Access denied (%s rule %d)\n", 37361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_act_subtable_type[subtable], rule); 37371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 37401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); 37411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_unit_access_denied(unit); 37421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 37431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_DIRECTION_INDICATOR_NOT_VALID: 37461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("bug: Invalid data direction given for unit " 37471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on adapter %s " 37481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info %d)\n", 37491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 37501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 37511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 37521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.data_direction); 37531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 37541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 37551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_dir_ind_nv"); 37561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 37571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 37581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CMND_LENGTH_NOT_VALID: 37611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 37621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("bug: An invalid control-data-block length field " 37631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was found in a command for unit 0x%016Lx on port " 37641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on adapter %s " "(debug info %d)\n", 37651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, unit->port->wwpn, 37661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 37671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->bottom.io.fcp_cmnd_length); 37681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop operation for this adapter */ 37691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 37701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_s_cmd_len_nv"); 37711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_erp_adapter_shutdown(unit->port->adapter, 0); 37721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 37731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 37761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s " 37771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "needs to be reopened\n", 37781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, zfcp_get_busid_by_unit(unit)); 37791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); 3780d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_port_boxed(unit->port); 37811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | 37821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_FSFREQ_RETRY; 37831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_BOXED: 37861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("unit needs to be reopened (adapter %s, " 37871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n", 37881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 37891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, unit->fcp_lun); 37901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); 3791d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann zfcp_erp_unit_boxed(unit); 37921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR 37931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ZFCP_STATUS_FSFREQ_RETRY; 37941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 37951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 37971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 37981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 37991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* re-establish link to port */ 38001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 38011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ltest"); 380265a8d4e1a3754f0bfaa62949ebe919930e3127a1Andreas Herrmann zfcp_test_link(unit->port); 38031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 38051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME(hw) need proper specs for proper action */ 38061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* let scsi stack deal with retries and escalation */ 38071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 1, 38081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_ulp"); 38091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 38111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL 3812516a4201bacfd61ea957039d6f47276ee9c32a0dAndreas Herrmann ("Unknown status qualifier 0x%x arrived.\n", 38131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 38141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, 38151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fsf_sq_inval:"); 38161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 38171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], 38181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(u32)); 38191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821516a4201bacfd61ea957039d6f47276ee9c32a0dAndreas Herrmann fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 38221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 38251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_RSP_AVAILABLE: 38281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 38311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); 38321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 38331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status, sizeof(u32)); 38341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 38381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) { 38391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 38401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_send_fcp_command_task_management_handler(fsf_req); 38411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 38421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req); 3843059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann fsf_req->unit = NULL; 3844059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann zfcp_unit_put(unit); 38451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 38471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 38481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 38501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_task_handler 38511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 38521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FCP_RSP IU 38531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 38541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 38551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 38561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 38571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) 38581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 38591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 38601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_cmnd *scpnt; 38611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) 38621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_rsp); 38631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_cmnd_iu *fcp_cmnd_iu = (struct fcp_cmnd_iu *) 38641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_cmnd); 38651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 sns_len; 38661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); 38671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 3868059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit = fsf_req->unit; 38691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_lock_irqsave(&fsf_req->adapter->abort_lock, flags); 3871059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann scpnt = (struct scsi_cmnd *) fsf_req->data; 38721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(!scpnt)) { 38731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG 38741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("Command with fsf_req %p is not associated to " 38751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "a scsi command anymore. Aborted?\n", fsf_req); 38761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 38771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTED)) { 38791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME: (design) mid-layer should handle DID_ABORT like 38801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DID_SOFT_ERROR by retrying the request for devices 38811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that allow retries. 38821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 38831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Setting DID_SOFT_ERROR and SUGGEST_RETRY\n"); 38841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_SOFT_ERROR); 38851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_driver_byte(&scpnt->result, SUGGEST_RETRY); 38861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 38871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 38901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("Setting DID_ERROR\n"); 38911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 38921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 38931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set message byte of result in SCSI command */ 38961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result |= COMMAND_COMPLETE << 8; 38971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 38991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy SCSI status code of FCP_STATUS of FCP_RSP IU to status byte 39001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of result in SCSI command 39011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 39021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result |= fcp_rsp_iu->scsi_status; 39031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->scsi_status)) { 39041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* DEBUG */ 39051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("status for SCSI Command:\n"); 39061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 39071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->cmnd, scpnt->cmd_len); 39081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("SCSI status code 0x%x\n", 39091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->scsi_status); 39101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 39111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) fcp_rsp_iu, sizeof (struct fcp_rsp_iu)); 39121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 39131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), 39141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_sns_len); 39151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check FCP_RSP_INFO */ 39181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) { 39191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("rsp_len is valid\n"); 39201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fcp_rsp_info[3]) { 39211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_GOOD: 39221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ok, continue */ 39231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("no failure or Task Management " 39241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Function complete\n"); 39251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_OK); 39261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_LENGTH_MISMATCH: 39281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* hardware bug */ 39291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: FCP response code indictates " 39301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that the fibrechannel protocol data " 39311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "length differs from the burst length. " 39321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on unit 0x%016Lx " 39331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on port 0x%016Lx on adapter %s", 39341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 39351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 39361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 39371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 39381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 39391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 39401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 39411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 39421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 39431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_FIELD_INVALID: 39441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* driver or hardware bug */ 39451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: FCP response code indictates " 39461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that the fibrechannel protocol data " 39471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fields were incorrectly set up. " 39481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on the unit " 39491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on " 39501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s", 39511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 39521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 39531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 39541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 39551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 39561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 39571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 39581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 39591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 39601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_RO_MISMATCH: 39611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* hardware bug */ 39621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: The FCP response code indicates " 39631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "that conflicting values for the " 39641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "fibrechannel payload offset from the " 39651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "header were found. " 39661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on unit 0x%016Lx " 39671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on port 0x%016Lx on adapter %s.\n", 39681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 39691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 39701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 39711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 39721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 39731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 39741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 39751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 39761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 39771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 39781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An invalid FCP response " 39791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "code was detected for a command. " 39801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The problem occured on the unit " 39811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%016Lx on port 0x%016Lx on " 39821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s (debug info 0x%x)\n", 39831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 39841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 39851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 39861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_info[3]); 39871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump SCSI CDB as prepared by zfcp */ 39881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, 39891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (char *) &fsf_req->qtcb-> 39901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); 39911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_host_byte(&scpnt->result, DID_ERROR); 39926f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> goto skip_fsfstatus; 39931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for sense data */ 39971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) { 39981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = FSF_FCP_RSP_SIZE - 39991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (struct fcp_rsp_iu) + fcp_rsp_iu->fcp_rsp_len; 40001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("room for %i bytes sense data in QTCB\n", 40011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len); 40021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE); 40031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("room for %i bytes sense data in SCSI command\n", 40041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_SENSE_BUFFERSIZE); 40051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len); 40061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n", 40071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->result); 40081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 40091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) &scpnt->cmnd, scpnt->cmd_len); 40101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n", 40121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_sns_len); 40131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&scpnt->sense_buffer, 40141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len); 40151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 40161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *) &scpnt->sense_buffer, sns_len); 40171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for overrun */ 40201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_over)) { 40211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("A data overrun was detected for a command. " 40221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s. " 40231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The response data length is " 40241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d, the original length was %d.\n", 40251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 40261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 40271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 40281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_resid, 40291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (int) zfcp_get_fcp_dl(fcp_cmnd_iu)); 40301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for underrun */ 40331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) { 40341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("A data underrun was detected for a command. " 40351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s. " 40361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The response data length is " 40371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d, the original length was %d.\n", 40381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 40401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 40411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_iu->fcp_resid, 40421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (int) zfcp_get_fcp_dl(fcp_cmnd_iu)); 40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->resid = fcp_rsp_iu->fcp_resid; 40451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (scpnt->request_bufflen - scpnt->resid < scpnt->underflow) 40466f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> set_host_byte(&scpnt->result, DID_ERROR); 40471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); 40511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40528a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (scpnt->result != 0) 40538a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt); 40548a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin else if (scpnt->retries > 0) 40558a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt); 40568a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin else 40578a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt); 40581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* cleanup pointer (need this especially for abort) */ 40601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scpnt->host_scribble = NULL; 40611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* always call back */ 40631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (scpnt->scsi_done) (scpnt); 40641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 40661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We must hold this lock until scsi_done has been called. 40671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise we may call scsi_done after abort regarding this 40681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command has completed. 40691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: scsi_done must not block! 40701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 40711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 40721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_unlock_irqrestore(&fsf_req->adapter->abort_lock, flags); 40731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 40741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 40751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 40771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_send_fcp_command_task_management_handler 40781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 40791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: evaluates FCP_RSP IU 40801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 40811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 40821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 40831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 40841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req) 40851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 40861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 40871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) 40881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &(fsf_req->qtcb->bottom.io.fcp_rsp); 40891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); 4090059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data; 40911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&fsf_req->adapter->scsi_er_timer); 40931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 40941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 40951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 40961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check FCP_RSP_INFO */ 40991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fcp_rsp_info[3]) { 41001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_GOOD: 41011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ok, continue */ 41021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("no failure or Task Management " 41031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Function complete\n"); 41041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 41051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_TASKMAN_UNSUPP: 41061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: A reuested task management function " 41071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "is not supported on the target device " 41081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s\n ", 41091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 41111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 41121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP; 41131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 41141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RSP_CODE_TASKMAN_FAILED: 41151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: A reuested task management function " 41161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "failed to complete successfully. " 41171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s.\n", 41181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 41201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit)); 41211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 41221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 41231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 41241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("bug: An invalid FCP response " 41251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "code was detected for a command. " 41261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unit 0x%016Lx, port 0x%016Lx, adapter %s " 41271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(debug info 0x%x)\n", 41281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->fcp_lun, 41291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit->port->wwpn, 41301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_unit(unit), 41311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fcp_rsp_info[3]); 41321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 41331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_fsfstatus: 41361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 41371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 41381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 41411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_control_file 41421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Initiator of the control file upload/download FSF requests 41441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - FSF request is successfuly created and queued 41461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EOPNOTSUPP - The FCP adapter does not have Control File support 41471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - Invalid direction specified 41481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENOMEM - Insufficient memory 41491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EPERM - Cannot create FSF request or place it in QDIO queue 41501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 41521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_control_file(struct zfcp_adapter *adapter, 41531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req **fsf_req_ptr, 41541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 fsf_command, 41551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 option, 41561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_sg_list *sg_list) 41571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 41581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req; 41591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom; 41601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 41611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct timer_list *timer; 41621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lock_flags; 41631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int req_flags = 0; 41641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int direction; 41651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 41661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(adapter->supported_features & FSF_FEATURE_CFDC)) { 41681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", 41691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 41701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EOPNOTSUPP; 41711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 41721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fsf_command) { 41751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_DOWNLOAD_CONTROL_FILE: 41771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds direction = SBAL_FLAGS0_TYPE_WRITE; 41781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((option != FSF_CFDC_OPTION_FULL_ACCESS) && 41791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (option != FSF_CFDC_OPTION_RESTRICTED_ACCESS)) 41801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_flags = ZFCP_WAIT_FOR_SBAL; 41811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 41821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_QTCB_UPLOAD_CONTROL_FILE: 41841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds direction = SBAL_FLAGS0_TYPE_READ; 41851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 41861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 41881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("Invalid FSF command code 0x%08x\n", fsf_command); 41891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 41901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 41911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); 41941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!timer) { 41951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -ENOMEM; 41961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 41971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 41981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags, 42001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, &lock_flags, &fsf_req); 42011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 42021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("error: Could not create FSF request for the " 42031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 42041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 42051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 42061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto unlock_queue_lock; 42071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 42101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= direction; 42111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom = &fsf_req->qtcb->bottom.support; 42131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; 42141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option = option; 42151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sg_list->count > 0) { 42171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytes; 42181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytes = zfcp_qdio_sbals_from_sg(fsf_req, direction, 42201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sg_list->sg, sg_list->count, 42211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_MAX_SBALS_PER_REQ); 42221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bytes != ZFCP_CFDC_MAX_CONTROL_FILE_SIZE) { 42231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO( 42241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "error: Could not create sufficient number of " 42251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "SBALS for an FSF request to the adapter %s\n", 42261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 42271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -ENOMEM; 42281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto free_fsf_req; 42291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 42311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; 42321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(timer); 42341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer->function = zfcp_fsf_request_timeout_handler; 42351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer->data = (unsigned long) adapter; 42361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; 42371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = zfcp_fsf_req_send(fsf_req, timer); 42391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 42401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_INFO("initiation of cfdc up/download failed" 42411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "(adapter %s)\n", 42421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 42431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 42441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto free_fsf_req; 42451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 42471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("Control file %s FSF request has been sent to the " 42491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "adapter %s\n", 42501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ? 42511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "download" : "upload", 42521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 42531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_event(fsf_req->completion_wq, 42551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 42561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fsf_req_ptr = fsf_req; 42581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer_sync(timer); 42591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto free_timer; 42601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_fsf_req: 42621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 42631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_queue_lock: 42641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 42651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_timer: 42661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(timer); 42671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 42681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 42691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 42701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 42731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_control_file_handler 42741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 42751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: Handler of the control file upload/download FSF requests 42761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 42771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - FSF request successfuly processed 42781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EAGAIN - Operation has to be repeated because of a temporary problem 42791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EACCES - There is no permission to execute an operation 42801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EPERM - The control file is not in a right format 42811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO - There is a problem with the FCP adapter 42821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - Invalid operation 42831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EFAULT - User space memory I/O operation fault 42841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 42851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 42861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req) 42871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 42881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter = fsf_req->adapter; 42891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_header *header = &fsf_req->qtcb->header; 42901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fsf_qtcb_bottom_support *bottom = &fsf_req->qtcb->bottom.support; 42911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 42921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { 42941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 42951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 42961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 42991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 43011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "The FSF request has been successfully completed " 43031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s\n", 43041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_OPERATION_PARTIALLY_SUCCESSFUL: 43081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) { 43091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 43101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43116f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> case FSF_SQ_CFDC_HARDENED_ON_SE: 43126f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> ZFCP_LOG_NORMAL( 43136f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "CFDC on the adapter %s has being " 43146f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> "hardened on primary and secondary SE\n", 43156f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> zfcp_get_busid_by_adapter(adapter)); 43166f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> break; 43176f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com> 43181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE: 43191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC of the adapter %s could not " 43211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be saved on the SE\n", 43221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2: 43261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC of the adapter %s could not " 43281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "be copied to the secondary SE\n", 43291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 43331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC could not be hardened " 43351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "on the adapter %s\n", 43361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 43401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EAGAIN; 43411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_AUTHORIZATION_FAILURE: 43441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Adapter %s does not accept privileged commands\n", 43461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 43481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EACCES; 43491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CFDC_ERROR_DETECTED: 43521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Error at position %d in the CFDC, " 43541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC is discarded by the adapter %s\n", 43551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0], 43561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 43581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EPERM; 43591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONTROL_FILE_UPDATE_ERROR: 43621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Adapter %s cannot harden the control file, " 43641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "file is discarded\n", 43651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 43671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 43681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONTROL_FILE_TOO_LARGE: 43711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Control file is too large, file is discarded " 43731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "by the adapter %s\n", 43741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 43751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 43761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 43771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_CONFLICT_DETECTED: 43801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) 43811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC has been discarded by the adapter %s, " 43831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "because activation would impact " 43841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d active connection(s)\n", 43851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 43861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 43871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 43881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 43891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 43901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_CONFLICTS_OVERRULED: 43921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) 43931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 43941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CFDC has been activated on the adapter %s, " 43951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "but activation has impacted " 43961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%d active connection(s)\n", 43971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 43981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status_qual.word[0]); 43991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 44011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_OP_SUBTYPE: 44041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL("unknown operation subtype (adapter: %s, " 44051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "op_subtype=0x%x)\n", 44061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 44071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->operation_subtype); 44081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 44101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_INVALID_COMMAND_OPTION: 44131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Invalid option 0x%x has been specified " 44151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "in QTCB bottom sent to the adapter %s\n", 44161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bottom->option, 44171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 44201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 44231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_NORMAL( 44241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bug: An unknown/unexpected FSF status 0x%08x " 44251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "was presented on the adapter %s\n", 44261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->fsf_status, 44271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter)); 44281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval"); 44291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug_exception(fsf_req->adapter->erp_dbf, 0, 44301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->fsf_status_qual.word[0], sizeof(u32)); 44311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 44321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 44331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 44341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 44371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 44381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 44391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 44411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_sbal_check(unsigned long *flags, 44421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *queue, int needed) 44431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 44441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_lock_irqsave(&queue->queue_lock, *flags); 44451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(atomic_read(&queue->free_count) >= needed)) 44461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 44471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&queue->queue_lock, *flags); 44481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 44491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 44501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 44521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set qtcb pointer in fsf_req and initialize QTCB 44531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 44541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 44558a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetyninzfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) 44561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 44571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->qtcb != NULL)) { 44588a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no; 44591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req; 44601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; 44618a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command]; 44621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; 44631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req; 44648a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; 44651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 44671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 44691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_req_sbal_get - try to get one SBAL in the request queue 44701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter: adapter for which request queue is examined 44711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @req_flags: flags indicating whether to wait for needed SBAL or not 44721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @lock_flags: lock_flags if queue_lock is taken 44731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return: 0 on success, otherwise -EIO, or -ERESTARTSYS 44741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Locks: lock adapter->request_queue->queue_lock on success 44751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 44761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 44771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags, 44781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *lock_flags) 44791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 44801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long ret; 44811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue = &adapter->request_queue; 44821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) { 44841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = wait_event_interruptible_timeout(adapter->request_wq, 44851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1), 44861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_SBAL_TIMEOUT); 44871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 44881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 44891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) 44901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 44911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1)) 44921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 44931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 44951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 44961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 44981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_create 44991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 45001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: create an FSF request at the specified adapter and 45011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * setup common fields 45021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 45031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: -ENOMEM if there was insufficient memory for a request 45041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO if no qdio buffers could be allocate to the request 45051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL/-EPERM on bug conditions in req_dequeue 45061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 in success 45071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 45081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * note: The created request is returned by reference. 45091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 45101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locks: lock of concerned request queue must not be held, 45111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but is held on completion (write, irqsave) 45121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 45131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 45141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, 45151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_t *pool, unsigned long *lock_flags, 45161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req **fsf_req_p) 45171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 45181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 45191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_fsf_req *fsf_req = NULL; 45201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 45211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue = &adapter->request_queue; 45221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate new FSF request */ 45241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = zfcp_fsf_req_alloc(pool, req_flags); 45251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(NULL == fsf_req)) { 45261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("error: Could not put an FSF request into" 45271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the outbound (send) queue.\n"); 45281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 45291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_fsf_req; 45301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45328a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->adapter = adapter; 45338a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->fsf_command = fsf_cmd; 45348a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 45358a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin zfcp_fsf_req_qtcb_init(fsf_req); 45361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* initialize waitqueue which may be used to wait on 45381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this request completion */ 45391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&fsf_req->completion_wq); 45401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = zfcp_fsf_req_sbal_get(adapter, req_flags, lock_flags); 45421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(ret < 0) { 45431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_sbals; 45441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 45471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We hold queue_lock here. Check if QDIOUP is set and let request fail 45481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if it is not set (see also *_open_qdio and *_close_qdio). 45491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 45501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) { 45521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_unlock_irqrestore(&req_queue->queue_lock, *lock_flags); 45531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EIO; 45541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_sbals; 45551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45578a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (fsf_req->qtcb) { 45588a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->seq_no = adapter->fsf_req_seq_no; 45598a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; 45608a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin } 45611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_number = 1; 45621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_first = req_queue->free_index; 45631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_curr = req_queue->free_index; 45641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbale_curr = 1; 45651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP)) { 45671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 45681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); 45711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup common SBALE fields */ 45731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].addr = fsf_req; 45741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[0].flags |= SBAL_FLAGS0_COMMAND; 45751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(fsf_req->qtcb != NULL)) { 45761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].addr = (void *) fsf_req->qtcb; 45771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].length = sizeof(struct fsf_qtcb); 45781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("got %i free BUFFERs starting at index %i\n", 45811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_number, fsf_req->sbal_first); 45821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto success; 45841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_sbals: 45861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* dequeue new FSF request previously enqueued */ 45871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_fsf_req_free(fsf_req); 45881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req = NULL; 45891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed_fsf_req: 45911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_lock_irqsave(&req_queue->queue_lock, *lock_flags); 45921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds success: 45931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fsf_req_p = fsf_req; 45941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 45951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 45961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 45981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function: zfcp_fsf_req_send 45991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 46001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * purpose: start transfer of FSF request via QDIO 46011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 46021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns: 0 - request transfer succesfully started 46031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * !0 - start of request transfer failed 46041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 46051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 46061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) 46071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 46081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_adapter *adapter; 46091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct zfcp_qdio_queue *req_queue; 46101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile struct qdio_buffer_element *sbale; 46118a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin int inc_seq_no; 46121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int new_distance_from_int; 46131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 46141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 46151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter = fsf_req->adapter; 46171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue = &adapter->request_queue, 46181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME(debug): remove it later */ 46211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_first, 0); 46221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("SBALE0 flags=0x%x\n", sbale[0].flags); 46231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("HEX DUMP OF SBALE1 PAYLOAD:\n"); 46241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, 46251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbale[1].length); 46261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* put allocated FSF request at list tail */ 46281db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); 46291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); 46301db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); 46311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46328a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin inc_seq_no = (fsf_req->qtcb != NULL); 46338a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 46341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* figure out expiration time of timeout and start timeout */ 46351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(timer)) { 46361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer->expires += jiffies; 46371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(timer); 46381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 46391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("request queue of adapter %s: " 46411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "next free SBAL is %i, %i free SBALs\n", 46421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 46431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index, 46441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&req_queue->free_count)); 46451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG("calling do_QDIO adapter %s, flags=0x%x, queue_no=%i, " 46471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "index_in_queue=%i, count=%i, buffers=%p\n", 46481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_get_busid_by_adapter(adapter), 46491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QDIO_FLAG_SYNC_OUTPUT, 46501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, fsf_req->sbal_first, fsf_req->sbal_number, 46511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &req_queue->buffer[fsf_req->sbal_first]); 46521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 46541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adjust the number of free SBALs in request queue as well as 46551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * position of first one 46561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 46571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_sub(fsf_req->sbal_number, &req_queue->free_count); 46581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_TRACE("free_count=%d\n", atomic_read(&req_queue->free_count)); 46591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index += fsf_req->sbal_number; /* increase */ 46601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap if needed */ 46611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req); 46621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46638a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin fsf_req->issued = get_clock(); 46648a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 46651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = do_QDIO(adapter->ccw_device, 46661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QDIO_FLAG_SYNC_OUTPUT, 46671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); 46681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(retval)) { 46701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Queues are down..... */ 46711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EIO; 46721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 46731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME(potential race): 46741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * timer might be expired (absolutely unlikely) 46751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 46761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timer) 46771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(timer); 46781db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); 46791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&fsf_req->list); 46801db2c9c0931a53fe013db55fd2ff58859db31e8dAndreas Herrmann spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); 46811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 46821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adjust the number of free SBALs in request queue as well as 46831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * position of first one 46841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 46851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds zfcp_qdio_zero_sbals(req_queue->buffer, 46861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsf_req->sbal_first, fsf_req->sbal_number); 46871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_add(fsf_req->sbal_number, &req_queue->free_count); 46881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index -= fsf_req->sbal_number; /* increase */ 46891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q; 46901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ 46911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_LOG_DEBUG 46921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ("error: do_QDIO failed. Buffers could not be enqueued " 46931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "to request queue.\n"); 46941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 46951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req_queue->distance_from_int = new_distance_from_int; 46961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 46971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * increase FSF sequence counter - 46981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this must only be done for request successfully enqueued to 46991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * QDIO this rejected requests may be cleaned up by calling 47001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routines resulting in missing sequence counter values 47011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * otherwise, 47021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 47038a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 47041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't increase for unsolicited status */ 47058a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin if (inc_seq_no) 47061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->fsf_req_seq_no++; 47078a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 47081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* count FSF requests pending */ 47091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&adapter->fsf_reqs_active); 47101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 47111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 47121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 47131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef ZFCP_LOG_AREA 4715