11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * zfcp device driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * Implementation of FSF commands. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt * Copyright IBM Corporation 2002, 2010 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define KMSG_COMPONENT "zfcp" 10ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 11ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt 120997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl#include <linux/blktrace_api.h> 135a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 149d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt#include <scsi/fc/fc_els.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "zfcp_ext.h" 164318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt#include "zfcp_fc.h" 17dcd20e2316cdc333dfdee09649dbe3642eb30e75Christof Schmitt#include "zfcp_dbf.h" 1834c2b712992540ca436e97432ffc57c84c8f8c18Christof Schmitt#include "zfcp_qdio.h" 19b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt#include "zfcp_reqlist.h" 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmittstruct kmem_cache *zfcp_fsf_qtcb_cache; 22259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt 23287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_request_timeout_handler(unsigned long data) 24287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{ 25287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; 26339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt zfcp_qdio_siosl(adapter); 275ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 28ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fsrth_1"); 29287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt} 30287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt 31287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, 32287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt unsigned long timeout) 33287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{ 34287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt fsf_req->timer.function = zfcp_fsf_request_timeout_handler; 35287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt fsf_req->timer.data = (unsigned long) fsf_req->adapter; 36287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt fsf_req->timer.expires = jiffies + timeout; 37287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt add_timer(&fsf_req->timer); 38287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt} 39287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt 40287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_start_erp_timer(struct zfcp_fsf_req *fsf_req) 41287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{ 42287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt BUG_ON(!fsf_req->erp_action); 43287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt fsf_req->timer.function = zfcp_erp_timeout_handler; 44287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt fsf_req->timer.data = (unsigned long) fsf_req->erp_action; 45287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt fsf_req->timer.expires = jiffies + 30 * HZ; 46287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt add_timer(&fsf_req->timer); 47287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt} 48287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* association between FSF command and FSF QTCB type */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 fsf_qtcb_type[] = { 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_FCP_CMND] = FSF_IO_COMMAND, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_ABORT_FCP_CMND] = FSF_SUPPORT_COMMAND, 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_OPEN_PORT_WITH_DID] = FSF_SUPPORT_COMMAND, 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_OPEN_LUN] = FSF_SUPPORT_COMMAND, 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_LUN] = FSF_SUPPORT_COMMAND, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_PORT] = FSF_SUPPORT_COMMAND, 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_CLOSE_PHYSICAL_PORT] = FSF_SUPPORT_COMMAND, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_SEND_ELS] = FSF_SUPPORT_COMMAND, 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_SEND_GENERIC] = FSF_SUPPORT_COMMAND, 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND, 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_EXCHANGE_PORT_DATA] = FSF_PORT_COMMAND, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND, 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 66553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) 67553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{ 68ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt dev_err(&req->adapter->ccw_device->dev, "FCP device not " 69ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "operational because of an unsupported FC class\n"); 70ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1"); 71553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 72553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt} 73553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt 74c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 75c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_req_free - free memory used by fsf request 76c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_req: pointer to struct zfcp_fsf_req 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 78c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligvoid zfcp_fsf_req_free(struct zfcp_fsf_req *req) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 80c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (likely(req->pool)) { 81a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig if (likely(req->qtcb)) 82a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig mempool_free(req->qtcb, req->adapter->pool.qtcb_pool); 83c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig mempool_free(req, req->pool); 84dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens return; 85dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens } 86dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens 87a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig if (likely(req->qtcb)) 88259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt kmem_cache_free(zfcp_fsf_qtcb_cache, req->qtcb); 89a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig kfree(req); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 92c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 94ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig unsigned long flags; 95c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_status_read_buffer *sr_buf = req->data; 96c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 97c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_port *port; 98800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt int d_id = ntoh24(sr_buf->d_id); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 100ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig read_lock_irqsave(&adapter->port_list_lock, flags); 101ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig list_for_each_entry(port, &adapter->port_list, list) 102c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (port->d_id == d_id) { 103ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_port_reopen(port, 0, "fssrpc1"); 104ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig break; 105c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 106ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig read_unlock_irqrestore(&adapter->port_list_lock, flags); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 109edaed859e63aac174fcc3fed81886b91bb124661Swen Schilligstatic void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, 110c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_link_down_info *link_down) 111aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin{ 112c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 113698ec01635819c5ae60090bb4efcbeffc41642fbMartin Peschke 114c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED) 115ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin return; 116ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin 117ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); 11870932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt 119a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt zfcp_scsi_schedule_rports_block(adapter); 120ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin 121c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (!link_down) 1222f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann goto out; 123ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin 124aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin switch (link_down->error_code) { 125aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_LIGHT: 126c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 127ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "There is no light signal from the local " 128ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "fibre channel cable\n"); 129aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 130aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_WRAP_PLUG: 131c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 132ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "There is a wrap plug instead of a fibre " 133ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "channel cable\n"); 134aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 135aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_FCP: 136c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 137ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The adjacent fibre channel node does not " 138ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "support FCP\n"); 139aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 140aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_FIRMWARE_UPDATE: 141c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 142ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The FCP device is suspended because of a " 143ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "firmware update\n"); 144553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt break; 145aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_INVALID_WWPN: 146c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 147ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The FCP device detected a WWPN that is " 148ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "duplicate or not valid\n"); 149aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 150aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_NPIV_SUPPORT: 151c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 152ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The fibre channel fabric does not support NPIV\n"); 153aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 154aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_FCP_RESOURCES: 155c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 156ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The FCP adapter cannot support more NPIV ports\n"); 157aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 158aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_FABRIC_RESOURCES: 159c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 160ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The adjacent switch cannot support " 161ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "more NPIV ports\n"); 162aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 163aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE: 164c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 165ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The FCP adapter could not log in to the " 166ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "fibre channel fabric\n"); 167aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 168aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED: 169c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 170ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The WWPN assignment file on the FCP adapter " 171ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "has been damaged\n"); 172aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 173aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED: 174c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 175ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The mode table on the FCP adapter " 176ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "has been damaged\n"); 177aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 178aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT: 179c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 180ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "All NPIV ports on the FCP adapter have " 181ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "been assigned\n"); 182aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 183aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin default: 184c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 185ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The link between the FCP adapter and " 186ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "the FC fabric is down\n"); 187aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin } 188c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 189edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); 190aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin} 191aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 192c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 194c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_status_read_buffer *sr_buf = req->data; 195c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_link_down_info *ldi = 196c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig (struct fsf_link_down_info *) &sr_buf->payload; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (sr_buf->status_subtype) { 199c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: 200edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_fsf_link_down_info_eval(req, ldi); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 202c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_SUB_FDISC_FAILED: 203edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_fsf_link_down_info_eval(req, ldi); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 205c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: 206edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_fsf_link_down_info_eval(req, NULL); 207c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig }; 208c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 210c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) 211c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 212c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 213c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_status_read_buffer *sr_buf = req->data; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 215c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { 216a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig zfcp_dbf_hba_fsf_uss("fssrh_1", req); 217c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data); 218c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 219c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 220c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 222a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig zfcp_dbf_hba_fsf_uss("fssrh_2", req); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 224c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (sr_buf->status_type) { 225c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_PORT_CLOSED: 226c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_status_read_port_closed(req); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 228c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_INCOMING_ELS: 229c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fc_incoming_els(req); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 231c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_SENSE_DATA_AVAIL: 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 233c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: 234ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt dev_warn(&adapter->ccw_device->dev, 235ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The error threshold for checksum statistics " 236ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "has been exceeded\n"); 237a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig zfcp_dbf_hba_bit_err("fssrh_3", req); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 239c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_LINK_DOWN: 240c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_status_read_link_down(req); 2412d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKDOWN, 0); 242c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 243c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_LINK_UP: 244c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_info(&adapter->ccw_device->dev, 245ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The local link has been restored\n"); 246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* All ports should be marked as ready to run again */ 247edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_adapter_status(adapter, 248edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig ZFCP_STATUS_COMMON_RUNNING); 249c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_erp_adapter_reopen(adapter, 250c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | 251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ZFCP_STATUS_COMMON_ERP_FAILED, 252ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fssrh_2"); 2532d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0); 2542d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz 255c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 256c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_NOTIFICATION_LOST: 257c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED) 258a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_adapter_access_changed(adapter); 259c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS) 2609eae07ef6bb5988163d8bb82cd952905db47b721Swen Schillig queue_work(adapter->work_queue, &adapter->scan_work); 261c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 262c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_CFDC_UPDATED: 263a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_adapter_access_changed(adapter); 264c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 265c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: 266c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->adapter_features = sr_buf->payload.word[0]; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 270c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data); 271c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 273c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig atomic_inc(&adapter->stat_miss); 2744544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig queue_work(adapter->work_queue, &adapter->stat_work); 275c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 277c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) 278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 279c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (req->qtcb->header.fsf_status_qual.word[0]) { 280c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_SQ_FCP_RSP_AVAILABLE: 281c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 282c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_SQ_NO_RETRY_POSSIBLE: 283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 284c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 285c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_SQ_COMMAND_ABORTED: 286c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 287c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_SQ_NO_RECOM: 288c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&req->adapter->ccw_device->dev, 289ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The FCP adapter reported a problem " 290ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "that cannot be recovered\n"); 291339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt zfcp_qdio_siosl(req->adapter); 292ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1"); 293c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 294c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* all non-return stats set FSFREQ_ERROR*/ 296c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 299c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 301c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) 302c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 304c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (req->qtcb->header.fsf_status) { 305c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_UNKNOWN_COMMAND: 306c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&req->adapter->ccw_device->dev, 307ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The FCP adapter does not recognize the command 0x%x\n", 308c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->header.fsf_command); 309ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1"); 310c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 311c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_ADAPTER_STATUS_AVAILABLE: 313c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_fsfstatus_qual_eval(req); 314c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 315c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 316c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) 319c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 320c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 321c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb *qtcb = req->qtcb; 322c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig union fsf_prot_status_qual *psq = &qtcb->prefix.prot_status_qual; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3245771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig zfcp_dbf_hba_fsf_response(req); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 326c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { 3274c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 328c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 329c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (qtcb->prefix.prot_status) { 332c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_GOOD: 333c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_FSF_STATUS_PRESENTED: 334c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 335c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_QTCB_VERSION_ERROR: 336c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&adapter->ccw_device->dev, 337ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "QTCB version 0x%x not supported by FCP adapter " 338ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION, 339ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt psq->word[0], psq->word[1]); 340ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1"); 341c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 342c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_ERROR_STATE: 343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_SEQ_NUMB_ERROR: 344ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(adapter, 0, "fspse_2"); 3454c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 346c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 347c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_UNSUPP_QTCB_TYPE: 348c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&adapter->ccw_device->dev, 349ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The QTCB type is not supported by the FCP adapter\n"); 350ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3"); 351c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_HOST_CONNECTION_INITIALIZING: 353c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, 354c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig &adapter->status); 355c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 356c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_DUPLICATE_REQUEST_ID: 357c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&adapter->ccw_device->dev, 358ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "0x%Lx is an ambiguous request identifier\n", 359c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig (unsigned long long)qtcb->bottom.support.req_handle); 360ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4"); 361c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 362c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_LINK_DOWN: 363edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_fsf_link_down_info_eval(req, &psq->link_down_info); 364452b505c5ada345103bdfdb39dc550df3ffe9eeaChristof Schmitt /* go through reopen to flush pending requests */ 365ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(adapter, 0, "fspse_6"); 366c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 367c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PROT_REEST_QUEUE: 368c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* All ports should be marked as ready to run again */ 369edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_adapter_status(adapter, 370edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig ZFCP_STATUS_COMMON_RUNNING); 371c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_erp_adapter_reopen(adapter, 372c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | 3735ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig ZFCP_STATUS_COMMON_ERP_FAILED, 374ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fspse_8"); 375c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 376c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig default: 377c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&adapter->ccw_device->dev, 378ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "0x%x is not a valid transfer protocol status\n", 379c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig qtcb->prefix.prot_status); 380339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt zfcp_qdio_siosl(adapter); 381ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9"); 382c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 383c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 386c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 387c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_req_complete - process completion of a FSF request 388c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_req: The FSF request that has been completed. 389c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * 390c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * When a request has been completed either from the FCP adapter, 391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * or it has been dismissed due to a queue shutdown, this function 392c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * is called to process the completion status and trigger further 393c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * events related to the FSF request. 394c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig */ 395bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schilligstatic void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 397c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) { 398c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_status_read_handler(req); 399c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 400c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 402c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig del_timer(&req->timer); 403c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_protstatus_eval(req); 404c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_fsfstatus_eval(req); 405c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler(req); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 407c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->erp_action) 408287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt zfcp_erp_notify(req->erp_action, 0); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 410c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) 411c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 412c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig else 413058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig complete(&req->completion); 414c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 416bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig/** 417bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * zfcp_fsf_req_dismiss_all - dismiss all fsf requests 418bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @adapter: pointer to struct zfcp_adapter 419bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * 420bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Never ever call this without shutting down the adapter first. 421bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Otherwise the adapter would continue using and corrupting s390 storage. 422bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Included BUG_ON() call to ensure this is done. 423bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * ERP is supposed to be the only user of this function. 424bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */ 425bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schilligvoid zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) 426bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig{ 427bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig struct zfcp_fsf_req *req, *tmp; 428bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig LIST_HEAD(remove_queue); 429bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 430bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP); 431b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt zfcp_reqlist_move(adapter->req_list, &remove_queue); 432bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 433bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig list_for_each_entry_safe(req, tmp, &remove_queue, list) { 434bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig list_del(&req->list); 435bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; 436bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig zfcp_fsf_req_complete(req); 437bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig } 438bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig} 439bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 440c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) 441c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 4429d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config; 443c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 444c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct Scsi_Host *shost = adapter->scsi_host; 4459d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt struct fc_els_flogi *nsp, *plogi; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4479d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt /* adjust pointers for missing command code */ 4489d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param 4499d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt - sizeof(u32)); 4509d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload 4519d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt - sizeof(u32)); 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 453c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->data) 454c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig memcpy(req->data, bottom, sizeof(*bottom)); 455c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 4569d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt fc_host_port_name(shost) = nsp->fl_wwpn; 4579d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt fc_host_node_name(shost) = nsp->fl_wwnn; 458800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt fc_host_port_id(shost) = ntoh24(bottom->s_id); 459c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_speed(shost) = bottom->fc_link_speed; 460c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; 461c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 462c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->hydra_version = bottom->adapter_type; 463faf4cd854203b26527d81e7e13d66e78774dad44Christof Schmitt adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK; 4648d88cf3f3b9af4713642caeb221b6d6a42019001Christof Schmitt adapter->stat_read_buf_num = max(bottom->status_read_buf_num, 4658d88cf3f3b9af4713642caeb221b6d6a42019001Christof Schmitt (u16)FSF_STATUS_READS_RECOM); 466c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 467c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (fc_host_permanent_port_name(shost) == -1) 468c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_permanent_port_name(shost) = fc_host_port_name(shost); 469c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 470c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (bottom->fc_topology) { 471c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_TOPO_P2P: 472800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt adapter->peer_d_id = ntoh24(bottom->peer_d_id); 4739d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt adapter->peer_wwpn = plogi->fl_wwpn; 4749d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt adapter->peer_wwnn = plogi->fl_wwnn; 475c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_port_type(shost) = FC_PORTTYPE_PTP; 476c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 477c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_TOPO_FABRIC: 478c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_port_type(shost) = FC_PORTTYPE_NPORT; 479c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 480c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_TOPO_AL: 481c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; 482dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt /* fall through */ 483c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig default: 484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&adapter->ccw_device->dev, 485ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "Unknown or unsupported arbitrated loop " 486ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "fibre channel topology detected\n"); 487ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1"); 488c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return -EIO; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 490c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 491ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck zfcp_scsi_set_prot(adapter); 492ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) 497553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{ 498553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt struct zfcp_adapter *adapter = req->adapter; 499c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb *qtcb = req->qtcb; 500c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config; 501c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct Scsi_Host *shost = adapter->scsi_host; 502553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt 503c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 506c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->fsf_lic_version = bottom->lic_version; 507c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->adapter_features = bottom->adapter_features; 508c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->connection_features = bottom->connection_features; 509c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->peer_wwpn = 0; 510c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->peer_wwnn = 0; 511c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->peer_d_id = 0; 5128a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 513c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (qtcb->header.fsf_status) { 514c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_GOOD: 515c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (zfcp_fsf_exchange_config_evaluate(req)) 516c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 518c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { 519c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&adapter->ccw_device->dev, 520ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "FCP adapter maximum QTCB size (%d bytes) " 521ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "is too small\n", 522ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt bottom->max_qtcb_size); 523ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1"); 524c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 525c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 526c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, 527c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig &adapter->status); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 529c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: 530c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_node_name(shost) = 0; 531c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_port_name(shost) = 0; 532c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_port_id(shost) = 0; 533c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 534c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; 535c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->hydra_version = 0; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 537edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_fsf_link_down_info_eval(req, 538c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig &qtcb->header.fsf_status_qual.link_down_info); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 540c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig default: 541ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3"); 542c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 543c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 545c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { 546c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->hardware_version = bottom->hardware_version; 547c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig memcpy(fc_host_serial_number(shost), bottom->serial_number, 548c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig min(FC_SERIAL_NUMBER_SIZE, 17)); 549c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig EBCASC(fc_host_serial_number(shost), 550c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig min(FC_SERIAL_NUMBER_SIZE, 17)); 551c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 553c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) { 554c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&adapter->ccw_device->dev, 555ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The FCP adapter only supports newer " 556ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "control block versions\n"); 557ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4"); 558c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 559c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 560c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) { 561c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&adapter->ccw_device->dev, 562ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "The FCP adapter only supports older " 563ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "control block versions\n"); 564ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5"); 565c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 566c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 568c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) 569c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 570c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 571c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_bottom_port *bottom = &req->qtcb->bottom.port; 572c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct Scsi_Host *shost = adapter->scsi_host; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 574c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->data) 575c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig memcpy(req->data, bottom, sizeof(*bottom)); 5769eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin 5770282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { 578c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_permanent_port_name(shost) = bottom->wwpn; 5790282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt fc_host_port_type(shost) = FC_PORTTYPE_NPIV; 5800282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt } else 581c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_permanent_port_name(shost) = fc_host_port_name(shost); 582c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_maxframe_size(shost) = bottom->maximum_frame_size; 583c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig fc_host_supported_speeds(shost) = bottom->supported_speed; 5842d8e62bbf7e83facd5701c100f62fbf0df4ee486Christof Schmitt memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, 5852d8e62bbf7e83facd5701c100f62fbf0df4ee486Christof Schmitt FC_FC4_LIST_SIZE); 5862d8e62bbf7e83facd5701c100f62fbf0df4ee486Christof Schmitt memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, 5872d8e62bbf7e83facd5701c100f62fbf0df4ee486Christof Schmitt FC_FC4_LIST_SIZE); 588c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 590c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) 591c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 592c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb *qtcb = req->qtcb; 593c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 594c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 595c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 596c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 597c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (qtcb->header.fsf_status) { 598c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_GOOD: 599c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_exchange_port_evaluate(req); 600c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 601c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: 602c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_exchange_port_evaluate(req); 603edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_fsf_link_down_info_eval(req, 604c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig &qtcb->header.fsf_status_qual.link_down_info); 605aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin break; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 607c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 608d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig 609a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligstatic struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool) 610c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 611c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 612a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig 613a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig if (likely(pool)) 614a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig req = mempool_alloc(pool, GFP_ATOMIC); 615a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig else 616a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig req = kmalloc(sizeof(*req), GFP_ATOMIC); 617a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig 618a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig if (unlikely(!req)) 619c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return NULL; 620a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig 621c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig memset(req, 0, sizeof(*req)); 62288f2a977870af655296a682fe2a58c822cd25bb2Christof Schmitt req->pool = pool; 623c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return req; 624c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 625c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 626a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligstatic struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool) 627c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 628a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig struct fsf_qtcb *qtcb; 629c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 630c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (likely(pool)) 631c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig qtcb = mempool_alloc(pool, GFP_ATOMIC); 632c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig else 633259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt qtcb = kmem_cache_alloc(zfcp_fsf_qtcb_cache, GFP_ATOMIC); 634a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig 635c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (unlikely(!qtcb)) 636c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return NULL; 637c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 638c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig memset(qtcb, 0, sizeof(*qtcb)); 639a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig return qtcb; 640c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 641c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 642564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligstatic struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, 6433ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber u32 fsf_cmd, u8 sbtype, 6441674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt mempool_t *pool) 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 646564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_adapter *adapter = qdio->adapter; 647a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 649c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (unlikely(!req)) 6501e9b16430ff4fd09408a74342d6b8338228e2f70Christof Schmitt return ERR_PTR(-ENOMEM); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 652c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (adapter->req_no == 0) 653c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->req_no++; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 655c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig INIT_LIST_HEAD(&req->list); 656c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig init_timer(&req->timer); 657058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig init_completion(&req->completion); 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 659c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->adapter = adapter; 660c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->fsf_command = fsf_cmd; 66152bfb558d2803590f86360ec3af1750897a9c010Christof Schmitt req->req_id = adapter->req_no; 662c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 663a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) { 664a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig if (likely(pool)) 665a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool); 666a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig else 667a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig req->qtcb = zfcp_qtcb_alloc(NULL); 668a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig 669a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig if (unlikely(!req->qtcb)) { 670a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig zfcp_fsf_req_free(req); 671a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig return ERR_PTR(-ENOMEM); 672a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig } 673a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig 6745bdecd2248d4af6f3b311b4d8ca7f3f5f83a7191Christof Schmitt req->seq_no = adapter->fsf_req_seq_no; 675564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; 676c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->prefix.req_id = req->req_id; 677c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->prefix.ulp_info = 26; 678c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command]; 679c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION; 680c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->header.req_handle = req->req_id; 681c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->header.fsf_command = req->fsf_command; 682c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 683c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 6841674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype, 6851674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt req->qtcb, sizeof(struct fsf_qtcb)); 6861674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt 687c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return req; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 690c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic int zfcp_fsf_req_send(struct zfcp_fsf_req *req) 691c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 692c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 693564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = adapter->qdio; 694b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt int with_qtcb = (req->qtcb != NULL); 695e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt int req_id = req->req_id; 696c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 697b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt zfcp_reqlist_add(adapter->req_list, req); 698c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 699706eca49a044a1ea89352dcc4b96ffc1631b2cb5Swen Schillig req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free); 700c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->issued = get_clock(); 70134c2b712992540ca436e97432ffc57c84c8f8c18Christof Schmitt if (zfcp_qdio_send(qdio, &req->qdio_req)) { 702c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig del_timer(&req->timer); 7033765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt /* lookup request again, list might have changed */ 704b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt zfcp_reqlist_find_rm(adapter->req_list, req_id); 705ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1"); 706c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return -EIO; 707c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 708c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 709c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* Don't increase for unsolicited status */ 710135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann if (with_qtcb) 711c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig adapter->fsf_req_seq_no++; 71252bfb558d2803590f86360ec3af1750897a9c010Christof Schmitt adapter->req_no++; 713c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 714c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return 0; 715c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 716c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 717c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 718c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_status_read - send status read request 719c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @adapter: pointer to struct zfcp_adapter 720c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @req_flags: request flags 721c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, ERROR otherwise 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 723564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_status_read(struct zfcp_qdio *qdio) 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 725564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_adapter *adapter = qdio->adapter; 726c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 727c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_status_read_buffer *sr_buf; 728c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt struct page *page; 729c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 73144a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 7326b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 733c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 734c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 7351674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, 0, 736a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig adapter->pool.status_read_req); 737025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 738c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 739c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 742c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt page = mempool_alloc(adapter->pool.sr_data, GFP_ATOMIC); 743c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt if (!page) { 744c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = -ENOMEM; 745c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto failed_buf; 746c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 747c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt sr_buf = page_address(page); 748c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig memset(sr_buf, 0, sizeof(*sr_buf)); 749c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->data = sr_buf; 7501674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt 7511674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_fill_next(qdio, &req->qdio_req, sr_buf, sizeof(*sr_buf)); 7521674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 753059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann 754c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 755c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (retval) 756c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto failed_req_send; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 758c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 759c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 760c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_req_send: 761a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig req->data = NULL; 762c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data); 763c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_buf: 764a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig zfcp_dbf_hba_fsf_uss("fssr__1", req); 765c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 766c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 76744a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 768c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return retval; 769c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 770c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 771c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) 772c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 773b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct scsi_device *sdev = req->data; 774b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 775c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual; 776c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 777c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 778c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return; 779c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 780c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (req->qtcb->header.fsf_status) { 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 782c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (fsq->word[0] == fsq->word[1]) { 783b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, 784ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fsafch1"); 785c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 789c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (fsq->word[0] == fsq->word[1]) { 790ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2"); 791c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_FCP_COMMAND_DOES_NOT_EXIST: 795c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 798edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_port_status(zfcp_sdev->port, 799edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig ZFCP_STATUS_COMMON_ACCESS_BOXED); 800edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_port_reopen(zfcp_sdev->port, 801ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3"); 8024c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_BOXED: 805edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED); 806edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, 807ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fsafch4"); 8084c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 811c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (fsq->word[0]) { 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 813b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt zfcp_fc_test_link(zfcp_sdev->port); 814dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt /* fall through */ 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 816c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 821c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 827b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command 828b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * @scmnd: The SCSI command to abort 829c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: pointer to struct zfcp_fsf_req 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 832b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstruct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd) 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 834c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req = NULL; 835b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct scsi_device *sdev = scmnd->device; 836b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 837b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; 838b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt unsigned long old_req_id = (unsigned long) scmnd->host_scribble; 8398a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 84044a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 8416b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 842c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 843564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND, 8443ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 845564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.scsi_abort); 846633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig if (IS_ERR(req)) { 847633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig req = NULL; 848c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 849633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig } 8502abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann 851b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt if (unlikely(!(atomic_read(&zfcp_sdev->status) & 852c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ZFCP_STATUS_COMMON_UNBLOCKED))) 853c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out_error_free; 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8551674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8576fbf25e86beef1c6719e760a241a7aef9ad145e3Swen Schillig req->data = sdev; 858c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_abort_fcp_command_handler; 859b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; 860b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->qtcb->header.port_handle = zfcp_sdev->port->handle; 861c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->bottom.support.req_handle = (u64) old_req_id; 862c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 863c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); 864c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (!zfcp_fsf_req_send(req)) 865c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 866c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 867c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout_error_free: 868c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 869c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req = NULL; 870c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 87144a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 872c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return req; 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 875c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 877c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 8787c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt struct zfcp_fsf_ct_els *ct = req->data; 879c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_header *header = &req->qtcb->header; 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8817c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt ct->status = -EINVAL; 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 883c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 8882c55b750a884b86dea8b4cc5f15e1484cc47a25cSwen Schillig zfcp_dbf_san_res("fsscth1", req); 8897c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt ct->status = 0; 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 892c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_class_not_supp(req); 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]){ 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 898c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 9054c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 907c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PORT_HANDLE_NOT_VALID: 908ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(adapter, 0, "fsscth1"); 909dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt /* fall through */ 910c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_GENERIC_COMMAND_REJECTED: 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PAYLOAD_SIZE_MISMATCH: 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_REQUEST_SIZE_TOO_LARGE: 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_RESPONSE_SIZE_TOO_LARGE: 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SBAL_MISMATCH: 915c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 9207c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt if (ct->handler) 9217c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt ct->handler(ct->handler_data); 922c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9241674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmittstatic void zfcp_fsf_setup_ct_els_unchained(struct zfcp_qdio *qdio, 9251674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt struct zfcp_qdio_req *q_req, 926426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt struct scatterlist *sg_req, 927426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt struct scatterlist *sg_resp) 928426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt{ 9291674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_fill_next(qdio, q_req, sg_virt(sg_req), sg_req->length); 9301674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_fill_next(qdio, q_req, sg_virt(sg_resp), sg_resp->length); 9311674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, q_req); 932426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt} 933426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt 93439eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmittstatic int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, 93539eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt struct scatterlist *sg_req, 93601b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig struct scatterlist *sg_resp) 937c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 93842428f747a8a0db9c6de03e105932316defad65dSwen Schillig struct zfcp_adapter *adapter = req->adapter; 93986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig struct zfcp_qdio *qdio = adapter->qdio; 94086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig struct fsf_qtcb *qtcb = req->qtcb; 94142428f747a8a0db9c6de03e105932316defad65dSwen Schillig u32 feat = adapter->adapter_features; 942c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 94386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (zfcp_adapter_multi_buffer_active(adapter)) { 94486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req)) 94586a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig return -EIO; 94686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp)) 94786a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig return -EIO; 94839eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt 94986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_set_data_div(qdio, &req->qdio_req, 95086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_sbale_count(sg_req)); 95186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 95286a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_set_scount(qdio, &req->qdio_req); 953426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt return 0; 954426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt } 955426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt 956426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt /* use single, unchained SBAL if it can hold the request */ 95730b6777b8931afc5f3aa42858fe917938b570f79Swen Schillig if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) { 95886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_fsf_setup_ct_els_unchained(qdio, &req->qdio_req, 9591674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt sg_req, sg_resp); 96039eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt return 0; 96139eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt } 96239eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt 96386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) 96486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig return -EOPNOTSUPP; 96586a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig 96686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req)) 9679072df4dc6e8fd569d583815edb0198af4b688b8Christof Schmitt return -EIO; 968c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 96986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig qtcb->bottom.support.req_buf_length = zfcp_qdio_real_bytes(sg_req); 97086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig 97186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 97286a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_skip_to_last_sbale(qdio, &req->qdio_req); 97386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig 97486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp)) 9759072df4dc6e8fd569d583815edb0198af4b688b8Christof Schmitt return -EIO; 97686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig 97786a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig qtcb->bottom.support.resp_buf_length = zfcp_qdio_real_bytes(sg_resp); 97886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig 97986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 98098fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt 981b1a58985853574346f1518531bdd82069501b317Christof Schmitt return 0; 982b1a58985853574346f1518531bdd82069501b317Christof Schmitt} 983b1a58985853574346f1518531bdd82069501b317Christof Schmitt 984b1a58985853574346f1518531bdd82069501b317Christof Schmittstatic int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req, 985b1a58985853574346f1518531bdd82069501b317Christof Schmitt struct scatterlist *sg_req, 986b1a58985853574346f1518531bdd82069501b317Christof Schmitt struct scatterlist *sg_resp, 98701b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig unsigned int timeout) 988b1a58985853574346f1518531bdd82069501b317Christof Schmitt{ 989b1a58985853574346f1518531bdd82069501b317Christof Schmitt int ret; 990b1a58985853574346f1518531bdd82069501b317Christof Schmitt 99101b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp); 992b1a58985853574346f1518531bdd82069501b317Christof Schmitt if (ret) 993b1a58985853574346f1518531bdd82069501b317Christof Schmitt return ret; 994b1a58985853574346f1518531bdd82069501b317Christof Schmitt 99598fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt /* common settings for ct/gs and els requests */ 99651375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig if (timeout > 255) 99751375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig timeout = 255; /* max value accepted by hardware */ 99898fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt req->qtcb->bottom.support.service_class = FSF_CLASS_3; 99951375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig req->qtcb->bottom.support.timeout = timeout; 100051375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig zfcp_fsf_start_timer(req, (timeout + 10) * HZ); 1001c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1002c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return 0; 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1006c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS) 1007c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @ct: pointer to struct zfcp_send_ct with data for request 1008c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10107c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmittint zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, 101151375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig struct zfcp_fsf_ct_els *ct, mempool_t *pool, 101251375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig unsigned int timeout) 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1014564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = wka_port->adapter->qdio; 1015c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 1016c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int ret = -EIO; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101844a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 10196b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 1020c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10221674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, 10233ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_WRITE_READ, pool); 102409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1025025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1026c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ret = PTR_ERR(req); 1027c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 10283f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt } 10293f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt 103009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 103101b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout); 1032553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt if (ret) 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_send; 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1035c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_send_ct_handler; 10365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig req->qtcb->header.port_handle = wka_port->handle; 1037c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->data = ct; 1038c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 10392c55b750a884b86dea8b4cc5f15e1484cc47a25cSwen Schillig zfcp_dbf_san_req("fssct_1", req, wka_port->d_id); 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ret = zfcp_fsf_req_send(req); 1042c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (ret) 1043c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto failed_send; 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1045c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1047c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_send: 1048c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1049c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 105044a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 1051c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return ret; 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1054c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10567c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt struct zfcp_fsf_ct_els *send_els = req->data; 1057c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_port *port = send_els->port; 1058c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_header *header = &req->qtcb->header; 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1060c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig send_els->status = -EINVAL; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1062c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto skip_fsfstatus; 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 10672c55b750a884b86dea8b4cc5f15e1484cc47a25cSwen Schillig zfcp_dbf_san_res("fsselh1", req); 1068c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig send_els->status = 0; 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SERVICE_CLASS_NOT_SUPPORTED: 1071c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_class_not_supp(req); 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]){ 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_RETRY_IF_POSSIBLE: 1078c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ELS_COMMAND_REJECTED: 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PAYLOAD_SIZE_MISMATCH: 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_REQUEST_SIZE_TOO_LARGE: 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_RESPONSE_SIZE_TOO_LARGE: 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 1088a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt if (port) { 1089a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_port_denied(port, &header->fsf_status_qual); 1090a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 1091a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt } 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1093c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_SBAL_MISMATCH: 109425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* should never occur, avoided in zfcp_fsf_send_els */ 1095c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* fall through */ 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1097c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus: 1101aa551daf5cc6fb6c6e09bb993737f9cd46dc7145Heiko Carstens if (send_els->handler) 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_els->handler(send_els->handler_data); 1103c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1105c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 1106c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_els - initiate an ELS command (FC-FS) 1107c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @els: pointer to struct zfcp_send_els with data for the command 1108c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig */ 11097c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmittint zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, 111051375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig struct zfcp_fsf_ct_els *els, unsigned int timeout) 1111c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 1112c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 11137c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt struct zfcp_qdio *qdio = adapter->qdio; 1114c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int ret = -EIO; 1115c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 111644a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 11176b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 1118c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 111909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 11201674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, 11213ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_WRITE_READ, NULL); 112209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1123025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1124c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ret = PTR_ERR(req); 1125c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 1126c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 1127c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 112809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 112901b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig 113086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (!zfcp_adapter_multi_buffer_active(adapter)) 113186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2); 113201b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig 113301b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout); 113444cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig 1135c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (ret) 1136c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto failed_send; 1137c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 11387c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt hton24(req->qtcb->bottom.support.d_id, d_id); 1139c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_send_els_handler; 1140c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->data = els; 1141c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 11422c55b750a884b86dea8b4cc5f15e1484cc47a25cSwen Schillig zfcp_dbf_san_req("fssels1", req, d_id); 1143c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1144c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ret = zfcp_fsf_req_send(req); 1145c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (ret) 1146c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto failed_send; 1147c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1148c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 1149c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1150c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_send: 1151c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1152c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 115344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 1154c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return ret; 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1157c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1159c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 1160564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = erp_action->adapter->qdio; 1161c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 1162c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 116344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 11646b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 1165c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 116609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1167564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, 11683ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1169564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.erp_req); 117009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1171025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1172c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 1173c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 11771674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1179c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->bottom.config.feature_selection = 1180aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_CFDC | 1181aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_LUN_SHARING | 11829eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin FSF_FEATURE_NOTIFICATION_LOST | 1183aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin FSF_FEATURE_UPDATE_ALERT; 1184c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->erp_action = erp_action; 1185c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_exchange_config_data_handler; 1186e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = req->req_id; 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1188287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt zfcp_fsf_start_erp_timer(req); 1189c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 1191c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1192e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = 0; 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1194c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 119544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 119652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return retval; 119752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig} 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1199564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, 1200c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_bottom_config *data) 120152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{ 1202c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req = NULL; 1203c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 1204c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 120544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 12066b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 1207ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt goto out_unlock; 1208c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 12091674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, 12103ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, NULL); 121109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1212025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1213c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 1214ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt goto out_unlock; 121552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig } 121652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 12171674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 1218c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_exchange_config_data_handler; 121952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 1220c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->bottom.config.feature_selection = 122152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FSF_FEATURE_CFDC | 122252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FSF_FEATURE_LUN_SHARING | 122352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FSF_FEATURE_NOTIFICATION_LOST | 122452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig FSF_FEATURE_UPDATE_ALERT; 122552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 122652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (data) 1227c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->data = data; 122852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 1229c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); 1230c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 123144a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 1232553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt if (!retval) 1233058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig wait_for_completion(&req->completion); 123452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 1235c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1236ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt return retval; 123752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 1238ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmittout_unlock: 123944a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data - request information about local port 1245aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin * @erp_action: ERP action for the adapter for which port data is requested 1246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1248c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1250564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = erp_action->adapter->qdio; 1251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 1252c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1254564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) 125552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return -EOPNOTSUPP; 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 125744a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 12586b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 1259c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 126009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1261564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, 12623ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1263564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.erp_req); 126409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1265025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1266c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 1267c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 1268aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin } 1269aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin 127009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 12711674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1273c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_exchange_port_data_handler; 1274c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->erp_action = erp_action; 1275e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = req->req_id; 127652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 1277287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt zfcp_fsf_start_erp_timer(req); 1278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 1280c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1281e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = 0; 128252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig } 1283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 128444a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 128552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return retval; 128652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig} 128752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 128852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig/** 128952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig * zfcp_fsf_exchange_port_data_sync - request information about local port 1290564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig * @qdio: pointer to struct zfcp_qdio 1291c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @data: pointer to struct fsf_qtcb_bottom_port 1292c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise 129352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig */ 1294564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, 1295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_bottom_port *data) 129652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{ 1297c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req = NULL; 1298c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 129952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 1300564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) 130152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig return -EOPNOTSUPP; 130252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 130344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 13046b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 1305ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt goto out_unlock; 1306c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 13071674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, 13083ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, NULL); 130909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1310025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1311c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 1312ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt goto out_unlock; 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig if (data) 1316c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->data = data; 131752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 13181674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 131952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig 1320c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_exchange_port_data_handler; 1321c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); 1322c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 132344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 1324ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt 1325553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt if (!retval) 1326058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig wait_for_completion(&req->completion); 1327058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig 1328c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 1331ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt 1332ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmittout_unlock: 133344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 1334ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt return retval; 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1337c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1339c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_port *port = req->data; 1340c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_header *header = &req->qtcb->header; 13419d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt struct fc_els_flogi *plogi; 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 1344a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann goto out; 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_ALREADY_OPEN: 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 1350a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_port_denied(port, &header->fsf_status_qual); 1351a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: 1354c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&req->adapter->ccw_device->dev, 1355ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "Not enough FCP adapter resources to open " 13567ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig "remote port 0x%016Lx\n", 13577ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig (unsigned long long)port->wwpn); 1358edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_port_status(port, 1359edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig ZFCP_STATUS_COMMON_ERP_FAILED); 1360c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_NO_RETRY_POSSIBLE: 1367c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->handle = header->port_handle; 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set_mask(ZFCP_STATUS_COMMON_OPEN | 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 1375d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 1376d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann ZFCP_STATUS_COMMON_ACCESS_BOXED, 1377d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann &port->status); 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check whether D_ID has changed during open */ 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: This check is not airtight, as the FCP channel does 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not monitor closures of target port connections caused on 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the remote side. Thus, they might miss out on invalidating 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locally cached WWPNs (and other N_Port parameters) of gone 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * target ports. So, our heroic attempt to make things safe 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could be undermined by 'open port' response data tagged with 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * obsolete WWPNs. Another reason to monitor potential 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connection closures ourself at least (by interpreting 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * incoming ELS' and unsolicited status). It just crosses my 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mind that one should be able to cross-check by means of 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * another GID_PN straight after a port has been opened. 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alternately, an ADISC/PDISC ELS should suffice, as well. 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13939d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els; 139439eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt if (req->qtcb->bottom.support.els1_length >= 13959d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt FSF_PLOGI_MIN_LEN) 1396c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fc_plogi_evaluate(port, plogi); 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_UNKNOWN_OP_SUBTYPE: 1399c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1402a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann 1403a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermannout: 1404615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt put_device(&port->dev); 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1407c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 1408c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_open_port - create and send open port request 1409c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action 1410c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1412c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1414564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = erp_action->adapter->qdio; 1415a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann struct zfcp_port *port = erp_action->port; 1416564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_fsf_req *req; 1417c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 1418c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 141944a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 14206b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 1421c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 1422c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1423564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID, 14243ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1425564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.erp_req); 142609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1427025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1428c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1430c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 143209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 14331674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1435c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_open_port_handler; 1436800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt hton24(req->qtcb->bottom.support.d_id, port->d_id); 1437a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann req->data = port; 1438c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->erp_action = erp_action; 1439e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = req->req_id; 1440615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt get_device(&port->dev); 1441c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1442287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt zfcp_fsf_start_erp_timer(req); 1443c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 1445c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1446e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = 0; 1447615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt put_device(&port->dev); 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1449c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 145044a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1454c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1456c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_port *port = req->data; 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1458c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 145944cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig return; 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (req->qtcb->header.fsf_status) { 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 1463ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1"); 1464c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 1469edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN); 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1474c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 1475c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_port - create and send close port request 1476c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action 1477c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1479c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1481564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = erp_action->adapter->qdio; 1482c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 1483c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 1484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 148544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 14866b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 1487c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 1488c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1489564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT, 14903ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1491564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.erp_req); 149209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1493025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1494c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 149809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 14991674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_close_port_handler; 1502c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->data = erp_action->port; 1503c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->erp_action = erp_action; 1504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->header.port_handle = erp_action->port->handle; 1505e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = req->req_id; 1506c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1507287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt zfcp_fsf_start_erp_timer(req); 1508c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 1510c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1511e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = 0; 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1513c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 151444a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15185ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligstatic void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req) 15195ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{ 1520bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt struct zfcp_fc_wka_port *wka_port = req->data; 15215ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig struct fsf_qtcb_header *header = &req->qtcb->header; 15225ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 15235ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) { 1524bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; 15255ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig goto out; 15265ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig } 15275ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 15285ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig switch (header->fsf_status) { 15295ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: 15305ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig dev_warn(&req->adapter->ccw_device->dev, 15315ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig "Opening WKA port 0x%x failed\n", wka_port->d_id); 1532dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt /* fall through */ 15335ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig case FSF_ADAPTER_STATUS_AVAILABLE: 15345ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 1535dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt /* fall through */ 15365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig case FSF_ACCESS_DENIED: 1537bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; 15385ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig break; 15395ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig case FSF_GOOD: 15405ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig wka_port->handle = header->port_handle; 154127f492ccec94b6acd8440c83bfe0515ce4db0af0Swen Schillig /* fall through */ 154227f492ccec94b6acd8440c83bfe0515ce4db0af0Swen Schillig case FSF_PORT_ALREADY_OPEN: 1543bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt wka_port->status = ZFCP_FC_WKA_PORT_ONLINE; 15445ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig } 15455ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout: 15465ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig wake_up(&wka_port->completion_wq); 15475ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig} 15485ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 15495ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig/** 15505ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * zfcp_fsf_open_wka_port - create and send open wka-port request 1551bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt * @wka_port: pointer to struct zfcp_fc_wka_port 15525ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * Returns: 0 on success, error otherwise 15535ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig */ 1554bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmittint zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) 15555ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{ 1556564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = wka_port->adapter->qdio; 15575ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig struct zfcp_fsf_req *req; 15585ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig int retval = -EIO; 15595ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 156044a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 15616b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 15625ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig goto out; 15635ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 1564564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID, 15653ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1566564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.erp_req); 156709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 15684e7d7af4dfea65b50b0fc694e3febc202e4e9839Tobias Klauser if (IS_ERR(req)) { 15695ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig retval = PTR_ERR(req); 15705ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig goto out; 15715ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig } 15725ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 157309a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 15741674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 15755ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 15765ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig req->handler = zfcp_fsf_open_wka_port_handler; 1577800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt hton24(req->qtcb->bottom.support.d_id, wka_port->d_id); 15785ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig req->data = wka_port; 15795ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 15805ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); 15815ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig retval = zfcp_fsf_req_send(req); 15825ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig if (retval) 15835ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig zfcp_fsf_req_free(req); 15845ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout: 158544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 15865ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig return retval; 15875ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig} 15885ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 15895ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligstatic void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) 15905ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{ 1591bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt struct zfcp_fc_wka_port *wka_port = req->data; 15925ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 15935ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) { 15945ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 1595ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1"); 15965ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig } 15975ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 1598bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; 15995ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig wake_up(&wka_port->completion_wq); 16005ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig} 16015ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 16025ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig/** 16035ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * zfcp_fsf_close_wka_port - create and send close wka port request 1604bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt * @wka_port: WKA port to open 16055ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * Returns: 0 on success, error otherwise 16065ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig */ 1607bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmittint zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) 16085ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{ 1609564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = wka_port->adapter->qdio; 16105ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig struct zfcp_fsf_req *req; 16115ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig int retval = -EIO; 16125ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 161344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 16146b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 16155ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig goto out; 16165ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 1617564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT, 16183ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1619564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.erp_req); 162009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 16214e7d7af4dfea65b50b0fc694e3febc202e4e9839Tobias Klauser if (IS_ERR(req)) { 16225ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig retval = PTR_ERR(req); 16235ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig goto out; 16245ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig } 16255ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 162609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 16271674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 16285ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 16295ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig req->handler = zfcp_fsf_close_wka_port_handler; 16305ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig req->data = wka_port; 16315ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig req->qtcb->header.port_handle = wka_port->handle; 16325ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 16335ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); 16345ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig retval = zfcp_fsf_req_send(req); 16355ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig if (retval) 16365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig zfcp_fsf_req_free(req); 16375ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout: 163844a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 16395ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig return retval; 16405ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig} 16415ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig 1642c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1644c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_port *port = req->data; 1645c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_header *header = &req->qtcb->header; 1646b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct scsi_device *sdev; 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1648c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 1649a5b11dda12ed7e3a79180b10ad6209a40a02989fChristof Schmitt return; 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 1653ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1"); 1654c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 1657a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_port_denied(port, &header->fsf_status_qual); 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 16605c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt /* can't use generic zfcp_erp_modify_port_status because 16615c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */ 16625c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 1663b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt shost_for_each_device(sdev, port->adapter->scsi_host) 1664b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt if (sdev_to_zfcp(sdev)->port == port) 1665b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, 1666b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt &sdev_to_zfcp(sdev)->status); 1667edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED); 1668edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, 1669ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fscpph2"); 16704c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 1675c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* fall through */ 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 1677c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* can't use generic zfcp_erp_modify_port_status because 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ZFCP_STATUS_COMMON_OPEN must not be reset for the port 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 1686b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt shost_for_each_device(sdev, port->adapter->scsi_host) 1687b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt if (sdev_to_zfcp(sdev)->port == port) 1688b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, 1689b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt &sdev_to_zfcp(sdev)->status); 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1694c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 1695c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_physical_port - close physical port 1696c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action 1697c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1699c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1701564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = erp_action->adapter->qdio; 1702c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 1703c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 1704c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 170544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 17066b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1709564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT, 17103ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1711564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.erp_req); 171209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1713025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1714c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 1715c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 1716c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 17191674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->data = erp_action->port; 1722c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->header.port_handle = erp_action->port->handle; 1723c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->erp_action = erp_action; 1724c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_close_physical_port_handler; 1725e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = req->req_id; 1726c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1727287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt zfcp_fsf_start_erp_timer(req); 1728c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 1730c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1731e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = 0; 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1733c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 173444a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1738b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstatic void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1740c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = req->adapter; 1741b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct scsi_device *sdev = req->data; 1742b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 1743c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_header *header = &req->qtcb->header; 1744c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1746c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 174744cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig return; 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 1750b64ddf96456cde17be22bf74cafed381a29d58baHeiko Carstens ZFCP_STATUS_COMMON_ACCESS_BOXED | 1751b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt ZFCP_STATUS_LUN_SHARED | 1752b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt ZFCP_STATUS_LUN_READONLY, 1753b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt &zfcp_sdev->status); 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status) { 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 1758ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1"); 1759c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* fall through */ 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_ALREADY_OPEN: 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ACCESS_DENIED: 1763a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual); 1764a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 1767edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_port_status(zfcp_sdev->port, 1768edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig ZFCP_STATUS_COMMON_ACCESS_BOXED); 1769edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_port_reopen(zfcp_sdev->port, 1770ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2"); 17714c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_SHARING_VIOLATION: 1774a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual); 1775c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: 1778c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_warn(&adapter->ccw_device->dev, 1779ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "No handle is available for LUN " 1780ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "0x%016Lx on port 0x%016Lx\n", 1781b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt (unsigned long long)zfcp_scsi_dev_lun(sdev), 1782b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt (unsigned long long)zfcp_sdev->port->wwpn); 1783edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); 1784c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* fall through */ 1785c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_INVALID_COMMAND_OPTION: 1786c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (header->fsf_status_qual.word[0]) { 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 1791b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt zfcp_fc_test_link(zfcp_sdev->port); 1792c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* fall through */ 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 1794c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 1800b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt zfcp_sdev->lun_handle = header->lun_handle; 1801b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status); 1802a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_open_lun_eval(sdev, bottom); 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1807c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 1808b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_open_lun - open LUN 1809c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action 1810c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1812b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittint zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action) 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1814c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_adapter *adapter = erp_action->adapter; 1815564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = adapter->qdio; 1816c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 1817c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 1818c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 181944a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 18206b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1823564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN, 18243ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1825a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig adapter->pool.erp_req); 182609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1827025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1828c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 1829c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 1830c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 1831c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 183209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 18331674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1835c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->header.port_handle = erp_action->port->handle; 1836b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->qtcb->bottom.support.fcp_lun = zfcp_scsi_dev_lun(erp_action->sdev); 1837b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->handler = zfcp_fsf_open_lun_handler; 1838b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->data = erp_action->sdev; 1839c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->erp_action = erp_action; 1840e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = req->req_id; 1841c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1842c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) 1843c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING; 1844c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 1845287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt zfcp_fsf_start_erp_timer(req); 1846c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) { 1848c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1849e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = 0; 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1851c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 185244a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1856b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstatic void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1858b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct scsi_device *sdev = req->data; 1859b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 186244cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig return; 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1864c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (req->qtcb->header.fsf_status) { 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_HANDLE_NOT_VALID: 1866ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); 1867c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_LUN_HANDLE_NOT_VALID: 1870ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2"); 1871c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_PORT_BOXED: 1874edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_port_status(zfcp_sdev->port, 1875edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig ZFCP_STATUS_COMMON_ACCESS_BOXED); 1876edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_port_reopen(zfcp_sdev->port, 1877ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3"); 18784c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_ADAPTER_STATUS_AVAILABLE: 1881c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (req->qtcb->header.fsf_status_qual.word[0]) { 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 1883b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt zfcp_fc_test_link(zfcp_sdev->port); 1884c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig /* fall through */ 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 1886c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FSF_GOOD: 1891b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status); 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1897b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_close_LUN - close LUN 1898b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * @erp_action: pointer to erp_action triggering the "close LUN" 1899c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1901b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittint zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action) 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1903564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = erp_action->adapter->qdio; 1904b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev); 1905c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 1906c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig int retval = -EIO; 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 190844a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 19096b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 191109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1912564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN, 19133ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_READ, 1914564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.erp_req); 191509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 1916025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 1917c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 1918c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 1919c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 19221674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1924c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->header.port_handle = erp_action->port->handle; 1925b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; 1926b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->handler = zfcp_fsf_close_lun_handler; 1927b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->data = erp_action->sdev; 1928c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->erp_action = erp_action; 1929e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = req->req_id; 1930fdf234527a070f6fc89f3ec5ee4ae1b263e59939Christof Schmitt 1931287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt zfcp_fsf_start_erp_timer(req); 1932c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 1933c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (retval) { 1934c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 1935e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt erp_action->fsf_req_id = 0; 1936c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 1937c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 193844a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 1939c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return retval; 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1942c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmittstatic void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat) 1943c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt{ 1944c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt lat_rec->sum += lat; 1945c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig lat_rec->min = min(lat_rec->min, lat); 1946c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig lat_rec->max = max(lat_rec->max, lat); 1947c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt} 1948c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt 1949d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmittstatic void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) 1950c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt{ 1951d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt struct fsf_qual_latency_info *lat_in; 1952d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt struct latency_cont *lat = NULL; 1953b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device); 1954d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt struct zfcp_blk_drv_data blktrc; 1955d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt int ticks = req->adapter->timer_ticks; 1956c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt 1957d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt lat_in = &req->qtcb->prefix.prot_status_qual.latency_info; 1958c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt 1959d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt blktrc.flags = 0; 1960d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC; 1961d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 1962d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt blktrc.flags |= ZFCP_BLK_REQ_ERROR; 1963706eca49a044a1ea89352dcc4b96ffc1631b2cb5Swen Schillig blktrc.inb_usage = 0; 196434c2b712992540ca436e97432ffc57c84c8f8c18Christof Schmitt blktrc.outb_usage = req->qdio_req.qdio_outb_usage; 1965d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt 19665bbf297cc652713a0a6511004b8d4c1cc21a3b02Christof Schmitt if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA && 19675bbf297cc652713a0a6511004b8d4c1cc21a3b02Christof Schmitt !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 1968d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt blktrc.flags |= ZFCP_BLK_LAT_VALID; 1969d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt blktrc.channel_lat = lat_in->channel_lat * ticks; 1970d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt blktrc.fabric_lat = lat_in->fabric_lat * ticks; 1971d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt 1972d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt switch (req->qtcb->bottom.io.data_direction) { 1973ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case FSF_DATADIR_DIF_READ_STRIP: 1974ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case FSF_DATADIR_DIF_READ_CONVERT: 1975d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt case FSF_DATADIR_READ: 1976b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt lat = &zfcp_sdev->latencies.read; 1977d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt break; 1978ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case FSF_DATADIR_DIF_WRITE_INSERT: 1979ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case FSF_DATADIR_DIF_WRITE_CONVERT: 1980d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt case FSF_DATADIR_WRITE: 1981b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt lat = &zfcp_sdev->latencies.write; 1982d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt break; 1983d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt case FSF_DATADIR_CMND: 1984b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt lat = &zfcp_sdev->latencies.cmd; 1985d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt break; 1986d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt } 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1988d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt if (lat) { 1989b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt spin_lock(&zfcp_sdev->latencies.lock); 1990d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat); 1991d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat); 1992d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt lat->counter++; 1993b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt spin_unlock(&zfcp_sdev->latencies.lock); 1994d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt } 19950997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl } 19960997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl 1997d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt blk_add_driver_data(scsi->request->q, scsi->request, &blktrc, 1998d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt sizeof(blktrc)); 19990997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl} 20000997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl 2001c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmittstatic void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) 2002c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 2003b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct scsi_cmnd *scmnd = req->data; 2004b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct scsi_device *sdev = scmnd->device; 2005b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 2006c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_header *header = &req->qtcb->header; 2007c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 2008c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) 2009c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt return; 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (header->fsf_status) { 2012c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_HANDLE_MISMATCH: 2013c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PORT_HANDLE_NOT_VALID: 2014ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1"); 2015c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 2016c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 2017c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_FCPLUN_NOT_VALID: 2018c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_LUN_HANDLE_NOT_VALID: 2019ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2"); 2020c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2022c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_SERVICE_CLASS_NOT_SUPPORTED: 2023c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_class_not_supp(req); 20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2025c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_ACCESS_DENIED: 2026a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual); 2027a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 2028c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 2029c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_DIRECTION_INDICATOR_NOT_VALID: 2030c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&req->adapter->ccw_device->dev, 2031b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt "Incorrect direction %d, LUN 0x%016Lx on port " 2032ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "0x%016Lx closed\n", 2033c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->bottom.io.data_direction, 2034b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt (unsigned long long)zfcp_scsi_dev_lun(sdev), 2035b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt (unsigned long long)zfcp_sdev->port->wwpn); 2036b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, 2037ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fssfch3"); 2038c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 2039c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 2040c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_CMND_LENGTH_NOT_VALID: 2041c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig dev_err(&req->adapter->ccw_device->dev, 2042b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt "Incorrect CDB length %d, LUN 0x%016Lx on " 2043ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt "port 0x%016Lx closed\n", 2044c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->bottom.io.fcp_cmnd_length, 2045b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt (unsigned long long)zfcp_scsi_dev_lun(sdev), 2046b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt (unsigned long long)zfcp_sdev->port->wwpn); 2047b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, 2048ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fssfch4"); 2049c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 2050c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 2051c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_PORT_BOXED: 2052edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_port_status(zfcp_sdev->port, 2053edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig ZFCP_STATUS_COMMON_ACCESS_BOXED); 2054edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_port_reopen(zfcp_sdev->port, 2055ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5"); 20564c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 2057c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 2058c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_LUN_BOXED: 2059edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED); 2060edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, 2061ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig "fssfch6"); 20624c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt req->status |= ZFCP_STATUS_FSFREQ_ERROR; 2063c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 2064c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_ADAPTER_STATUS_AVAILABLE: 2065c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (header->fsf_status_qual.word[0] == 2066c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig FSF_SQ_INVOKE_LINK_TEST_PROCEDURE) 2067b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt zfcp_fc_test_link(zfcp_sdev->port); 2068c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->status |= ZFCP_STATUS_FSFREQ_ERROR; 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2071c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt} 2072c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2073c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmittstatic void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req) 2074c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt{ 2075c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt struct scsi_cmnd *scpnt; 2076c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt struct fcp_resp_with_ext *fcp_rsp; 2077c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt unsigned long flags; 2078c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2079c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt read_lock_irqsave(&req->adapter->abort_lock, flags); 2080c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2081c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt scpnt = req->data; 2082c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt if (unlikely(!scpnt)) { 2083c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt read_unlock_irqrestore(&req->adapter->abort_lock, flags); 2084c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt return; 2085c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 2086c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 20875bfb2c31487eaff3840e02548e6acf89a048765bSwen Schillig zfcp_fsf_fcp_handler_common(req); 20885bfb2c31487eaff3840e02548e6acf89a048765bSwen Schillig 2089c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 2090c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED); 2091c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt goto skip_fsfstatus; 2092c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt } 2093c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2094c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt switch (req->qtcb->header.fsf_status) { 2095c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt case FSF_INCONSISTENT_PROT_DATA: 2096c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt case FSF_INVALID_PROT_PARM: 2097c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt set_host_byte(scpnt, DID_ERROR); 2098c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt goto skip_fsfstatus; 2099c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt case FSF_BLOCK_GUARD_CHECK_FAILURE: 2100c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt zfcp_scsi_dif_sense_error(scpnt, 0x1); 2101c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt goto skip_fsfstatus; 2102c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt case FSF_APP_TAG_CHECK_FAILURE: 2103c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt zfcp_scsi_dif_sense_error(scpnt, 0x2); 2104c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt goto skip_fsfstatus; 2105c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt case FSF_REF_TAG_CHECK_FAILURE: 2106c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt zfcp_scsi_dif_sense_error(scpnt, 0x3); 2107c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt goto skip_fsfstatus; 2108c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt } 2109c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; 2110c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt); 2111c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2112c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmittskip_fsfstatus: 2113c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt zfcp_fsf_req_trace(req, scpnt); 2114250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig zfcp_dbf_scsi_result(scpnt, req); 2115c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2116c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt scpnt->host_scribble = NULL; 2117c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt (scpnt->scsi_done) (scpnt); 2118c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt /* 2119c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt * We must hold this lock until scsi_done has been called. 2120c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt * Otherwise we may call scsi_done after abort regarding this 2121c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt * command has completed. 2122c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt * Note: scsi_done must not block! 2123c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt */ 2124c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt read_unlock_irqrestore(&req->adapter->abort_lock, flags); 21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2127ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beckstatic int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir) 2128ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck{ 2129ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck switch (scsi_get_prot_op(scsi_cmnd)) { 2130ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case SCSI_PROT_NORMAL: 2131ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck switch (scsi_cmnd->sc_data_direction) { 2132ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case DMA_NONE: 2133ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck *data_dir = FSF_DATADIR_CMND; 2134ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck break; 2135ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case DMA_FROM_DEVICE: 2136ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck *data_dir = FSF_DATADIR_READ; 2137ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck break; 2138ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case DMA_TO_DEVICE: 2139ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck *data_dir = FSF_DATADIR_WRITE; 2140ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck break; 2141ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case DMA_BIDIRECTIONAL: 2142ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck return -EINVAL; 2143ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck } 2144ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck break; 2145ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck 2146ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case SCSI_PROT_READ_STRIP: 2147ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck *data_dir = FSF_DATADIR_DIF_READ_STRIP; 2148ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck break; 2149ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case SCSI_PROT_WRITE_INSERT: 2150ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck *data_dir = FSF_DATADIR_DIF_WRITE_INSERT; 2151ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck break; 2152ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case SCSI_PROT_READ_PASS: 2153ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck *data_dir = FSF_DATADIR_DIF_READ_CONVERT; 2154ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck break; 2155ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck case SCSI_PROT_WRITE_PASS: 2156ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck *data_dir = FSF_DATADIR_DIF_WRITE_CONVERT; 2157ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck break; 2158ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck default: 2159ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck return -EINVAL; 2160ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck } 2161ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck 2162ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck return 0; 2163ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck} 2164ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck 2165c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 2166b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command) 2167c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @scsi_cmnd: scsi command to be sent 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2169b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittint zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) 21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2171c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req; 21724318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt struct fcp_cmnd *fcp_cmnd; 21733ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber u8 sbtype = SBAL_SFLAGS0_TYPE_READ; 217486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig int retval = -EIO; 2175b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct scsi_device *sdev = scsi_cmnd->device; 2176b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 2177b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; 2178564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = adapter->qdio; 2179ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck struct fsf_qtcb_bottom_io *io; 2180e55f87531c2c1eb071a296df7eb67f83d5f0b5dfChristof Schmitt unsigned long flags; 21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2182b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt if (unlikely(!(atomic_read(&zfcp_sdev->status) & 2183c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ZFCP_STATUS_COMMON_UNBLOCKED))) 2184c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return -EBUSY; 21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2186e55f87531c2c1eb071a296df7eb67f83d5f0b5dfChristof Schmitt spin_lock_irqsave(&qdio->req_q_lock, flags); 2187706eca49a044a1ea89352dcc4b96ffc1631b2cb5Swen Schillig if (atomic_read(&qdio->req_q_free) <= 0) { 2188564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig atomic_inc(&qdio->req_q_full); 2189c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 21908fdf30d5429605a4c30cc515c73e5eab140035deChristof Schmitt } 219109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 21921674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) 21933ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber sbtype = SBAL_SFLAGS0_TYPE_WRITE; 21941674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt 2195564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND, 21961674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt sbtype, adapter->pool.scsi_req); 219709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 2198025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 2199c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = PTR_ERR(req); 2200c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 2201c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 2202c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 2203ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck scsi_cmnd->host_scribble = (unsigned char *) req->req_id; 2204ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck 2205ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck io = &req->qtcb->bottom.io; 220609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 2207c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->data = scsi_cmnd; 2208c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt req->handler = zfcp_fsf_fcp_cmnd_handler; 2209b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; 2210b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->qtcb->header.port_handle = zfcp_sdev->port->handle; 2211ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck io->service_class = FSF_CLASS_3; 2212ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck io->fcp_cmnd_length = FCP_CMND_LEN; 2213c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 2214ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck if (scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) { 2215ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck io->data_block_length = scsi_cmnd->device->sector_size; 2216ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck io->ref_tag_value = scsi_get_lba(scsi_cmnd) & 0xFFFFFFFF; 22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2219cc405acee244310cc87ddc5e3f4bc61342ec8161Steffen Maier if (zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction)) 2220cc405acee244310cc87ddc5e3f4bc61342ec8161Steffen Maier goto failed_scsi_cmnd; 2221ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck 22224318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; 22232443c8b23aea83d529868030e28f45a6fa6553b2Christof Schmitt zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0); 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2225ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck if (scsi_prot_sg_count(scsi_cmnd)) { 2226ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck zfcp_qdio_set_data_div(qdio, &req->qdio_req, 2227ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck scsi_prot_sg_count(scsi_cmnd)); 222886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, 222986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig scsi_prot_sglist(scsi_cmnd)); 223086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (retval) 223186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig goto failed_scsi_cmnd; 223286a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig io->prot_data_length = zfcp_qdio_real_bytes( 2233ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck scsi_prot_sglist(scsi_cmnd)); 2234ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck } 2235ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck 223686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, 223786a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig scsi_sglist(scsi_cmnd)); 223886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (unlikely(retval)) 2239c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto failed_scsi_cmnd; 22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req); 224286a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (zfcp_adapter_multi_buffer_active(adapter)) 224386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_set_scount(qdio, &req->qdio_req); 2244ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck 2245c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 2246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (unlikely(retval)) 2247c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto failed_scsi_cmnd; 22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2249c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_scsi_cmnd: 2252c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 2253c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig scsi_cmnd->host_scribble = NULL; 2254c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 2255e55f87531c2c1eb071a296df7eb67f83d5f0b5dfChristof Schmitt spin_unlock_irqrestore(&qdio->req_q_lock, flags); 2256c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return retval; 22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2259c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmittstatic void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req) 2260c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt{ 2261c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt struct fcp_resp_with_ext *fcp_rsp; 2262c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt struct fcp_resp_rsp_info *rsp_info; 2263c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2264c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt zfcp_fsf_fcp_handler_common(req); 2265c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2266c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; 2267c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; 2268c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 2269c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt if ((rsp_info->rsp_code != FCP_TMF_CMPL) || 2270c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt (req->status & ZFCP_STATUS_FSFREQ_ERROR)) 2271c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; 2272c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt} 2273c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt 22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2275b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_fcp_task_mgmt - send SCSI task management command 2276b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * @scmnd: SCSI command to send the task management command for 2277c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @tm_flags: unsigned byte for task management flags 2278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: on success pointer to struct fsf_req, NULL otherwise 22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2280b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstruct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, 2281b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt u8 tm_flags) 22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req = NULL; 22844318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt struct fcp_cmnd *fcp_cmnd; 2285b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device); 2286b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; 22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2288b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt if (unlikely(!(atomic_read(&zfcp_sdev->status) & 2289c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig ZFCP_STATUS_COMMON_UNBLOCKED))) 2290c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return NULL; 22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 229244a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 22936b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 2294c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 229509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 2296564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND, 22973ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber SBAL_SFLAGS0_TYPE_WRITE, 2298564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig qdio->adapter->pool.scsi_req); 229909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig 2300633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig if (IS_ERR(req)) { 2301633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig req = NULL; 2302c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 2303633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig } 23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2305b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->data = scmnd; 2306c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt req->handler = zfcp_fsf_fcp_task_mgmt_handler; 2307b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; 2308b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt req->qtcb->header.port_handle = zfcp_sdev->port->handle; 2309c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; 2310c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->qtcb->bottom.io.service_class = FSF_CLASS_3; 23114318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN; 2312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 23131674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23154318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; 23162443c8b23aea83d529868030e28f45a6fa6553b2Christof Schmitt zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags); 23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); 2319c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (!zfcp_fsf_req_send(req)) 2320c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2322c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 2323c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req = NULL; 2324c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 232544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 2326c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return req; 2327c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig} 23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2329c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req) 2330c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{ 23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2333c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/** 2334c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_control_file - control file upload/download 2335c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @adapter: pointer to struct zfcp_adapter 2336c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_cfdc: pointer to struct zfcp_fsf_cfdc 2337c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: on success pointer to struct zfcp_fsf_req, NULL otherwise 23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2339c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstruct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, 2340c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_cfdc *fsf_cfdc) 23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2342564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_qdio *qdio = adapter->qdio; 2343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct zfcp_fsf_req *req = NULL; 2344c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig struct fsf_qtcb_bottom_support *bottom; 234586a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig int retval = -EIO; 23463ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber u8 direction; 2347c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 2348c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) 2349c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return ERR_PTR(-EOPNOTSUPP); 2350c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig 2351c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig switch (fsf_cfdc->command) { 2352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_QTCB_DOWNLOAD_CONTROL_FILE: 23533ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber direction = SBAL_SFLAGS0_TYPE_WRITE; 2354c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 2355c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig case FSF_QTCB_UPLOAD_CONTROL_FILE: 23563ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber direction = SBAL_SFLAGS0_TYPE_READ; 2357c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig break; 2358c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig default: 2359c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return ERR_PTR(-EINVAL); 2360c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 236244a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_lock_irq(&qdio->req_q_lock); 23636b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt if (zfcp_qdio_sbal_get(qdio)) 2364c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23661674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, direction, NULL); 2367025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa if (IS_ERR(req)) { 2368c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = -EPERM; 2369c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 2370c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2372c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig req->handler = zfcp_fsf_control_file_handler; 23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2374c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig bottom = &req->qtcb->bottom.support; 2375c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; 2376c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig bottom->option = fsf_cfdc->option; 23778a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 237886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg); 237901b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig 238086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (retval || 238186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig (zfcp_qdio_real_bytes(fsf_cfdc->sg) != ZFCP_CFDC_MAX_SIZE)) { 2382c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_req_free(req); 238386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig retval = -EIO; 2384c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig goto out; 2385c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig } 238686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); 238786a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig if (zfcp_adapter_multi_buffer_active(adapter)) 238886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig zfcp_qdio_set_scount(qdio, &req->qdio_req); 23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2390c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); 2391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig retval = zfcp_fsf_req_send(req); 2392c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout: 239344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt spin_unlock_irq(&qdio->req_q_lock); 23948a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin 2395c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig if (!retval) { 2396058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig wait_for_completion(&req->completion); 2397c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return req; 23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2399c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig return ERR_PTR(retval); 24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2401bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 2402bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig/** 2403bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO 2404bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @adapter: pointer to struct zfcp_adapter 2405bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @sbal_idx: response queue index of SBAL to be processed 2406bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */ 2407564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligvoid zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) 2408bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig{ 2409564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig struct zfcp_adapter *adapter = qdio->adapter; 2410706eca49a044a1ea89352dcc4b96ffc1631b2cb5Swen Schillig struct qdio_buffer *sbal = qdio->res_q[sbal_idx]; 2411bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig struct qdio_buffer_element *sbale; 2412bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig struct zfcp_fsf_req *fsf_req; 2413b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt unsigned long req_id; 2414bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig int idx; 2415bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 2416bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) { 2417bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 2418bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig sbale = &sbal->element[idx]; 2419bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig req_id = (unsigned long) sbale->addr; 2420b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id); 2421bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 2422339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt if (!fsf_req) { 2423bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig /* 2424bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Unknown request means that we have potentially memory 2425bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * corruption and must stop the machine immediately. 2426bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */ 2427339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt zfcp_qdio_siosl(adapter); 2428bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig panic("error: unknown req_id (%lx) on adapter %s.\n", 2429bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig req_id, dev_name(&adapter->ccw_device->dev)); 2430339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt } 2431bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 243234c2b712992540ca436e97432ffc57c84c8f8c18Christof Schmitt fsf_req->qdio_req.sbal_response = sbal_idx; 2433bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig zfcp_fsf_req_complete(fsf_req); 2434bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig 24353ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber if (likely(sbale->eflags & SBAL_EFLAGS_LAST_ENTRY)) 2436bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig break; 2437bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig } 2438bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig} 2439a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig 2440a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schilligstruct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *qdio, 2441a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig struct qdio_buffer *sbal) 2442a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig{ 2443a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig struct qdio_buffer_element *sbale = &sbal->element[0]; 2444a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig u64 req_id = (unsigned long) sbale->addr; 2445a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig 2446a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig return zfcp_reqlist_find(qdio->adapter->req_list, req_id); 2447a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig} 2448