11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright IBM Corporation 1994, 2004 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Authors: Colin DeVilbiss (devilbis@us.ibm.com) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Santiago Leon (santil@us.ibm.com) 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dave Boutcher (sleddog@us.ibm.com) 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * USA 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Emulation of a SCSI host adapter for Virtual I/O devices 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver supports the SCSI adapter implemented by the IBM 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Power5 firmware. That SCSI adapter is not a physical adapter, 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but allows Linux SCSI peripheral drivers to directly 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * access devices in another logical partition on the physical system. 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The virtual adapter(s) are present in the open firmware device 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tree just like real adapters. 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * One of the capabilities provided on these systems is the ability 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to DMA between partitions. The architecture states that for VSCSI, 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the server side is allowed to DMA to and from the client. The client 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is never trusted to DMA to or from the server directly. 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Messages are sent between partitions on a "Command/Response Queue" 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (CRQ), which is just a buffer of 16 byte entries in the receiver's 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Senders cannot access the buffer directly, but send messages by 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * making a hypervisor call and passing in the 16 bytes. The hypervisor 439b7dac086bec7c71722d6e79464609e17f0996e7Bart Van Assche * puts the message in the next 16 byte space in round-robin fashion, 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * turns on the high order bit of the message (the valid bit), and 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * generates an interrupt to the receiver (if interrupts are turned on.) 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The receiver just turns off the valid bit when they have copied out 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the message. 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The VSCSI client builds a SCSI Remote Protocol (SRP) Information Unit 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (IU) (as defined in the T10 standard available at www.t10.org), gets 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a DMA address for the message, and sends it to the server as the 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * payload of a CRQ message. The server DMAs the SRP IU and processes it, 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * including doing any additional data transfers. When it is done, it 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMAs the SRP response back to the same address as the request came from, 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and sends a CRQ message back to inform the client that the request has 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * completed. 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 587834799a6c8fed36d06d6b78bfd17831ecfa93c4Stephen Rothwell * TODO: This is currently pretty tied to the IBM pSeries hypervisor 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interfaces. It would be really nice to abstract this above an RDMA 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * layer. 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/dma-mapping.h> 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 675a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 68126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King#include <linux/of.h> 6964355b929dec0cb6271e4ac7834c9cf262961e40Brian King#include <linux/pm.h> 700f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King#include <linux/kthread.h> 71d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse#include <asm/firmware.h> 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/vio.h> 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi.h> 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_cmnd.h> 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h> 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_device.h> 774d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori#include <scsi/scsi_transport_srp.h> 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ibmvscsi.h" 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The values below are somewhat arbitrary default values, but 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OS/400 will use 3 busses (disks, CDs, tapes, I think.) 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that there are 3 bits of channel value, 6 bits of id, and 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5 bits of LUN. 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int max_id = 64; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int max_channel = 3; 87e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int init_timeout = 300; 88e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int login_timeout = 60; 89e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int info_timeout = 30; 90e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int abort_timeout = 60; 91e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int reset_timeout = 60; 92a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jenningsstatic int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; 934f10aae0d1a285df6b16bf6ca5abd366140fd371Brian Kingstatic int max_events = IBMVSCSI_MAX_REQUESTS_DEFAULT + 2; 94c1988e3123751fd425fbae99d5c1776608e965a9Robert Jenningsstatic int fast_fail = 1; 95126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic int client_reserve = 1; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 974d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonoristatic struct scsi_transport_template *ibmvscsi_transport_template; 984d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 99aac3118d33e275a7b1134cb19227c982f4d43877Brian King#define IBMVSCSI_VERSION "1.5.9" 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhousestatic struct ibmvscsi_ops *ibmvscsi_ops; 102d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("IBM Virtual SCSI"); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Dave Boutcher"); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(IBMVSCSI_VERSION); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_id, "Largest ID value for each channel"); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_channel, "Largest channel value"); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR); 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds"); 11421465eda9eafa275ed11c27779d90aa95559b6f6Brian Kingmodule_param_named(max_requests, max_requests, int, S_IRUGO); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_requests, "Maximum requests for this adapter"); 116c1988e3123751fd425fbae99d5c1776608e965a9Robert Jenningsmodule_param_named(fast_fail, fast_fail, int, S_IRUGO | S_IWUSR); 117c1988e3123751fd425fbae99d5c1776608e965a9Robert JenningsMODULE_PARM_DESC(fast_fail, "Enable fast fail. [Default=1]"); 118126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingmodule_param_named(client_reserve, client_reserve, int, S_IRUGO ); 119126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian KingMODULE_PARM_DESC(client_reserve, "Attempt client managed reserve/release"); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for the event pool and event structs 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initialize_event_pool: - Allocates and initializes the event pool for a host 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool to be initialized 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @size: Number of events in pool 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data who owns the event pool 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns zero on success. 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int initialize_event_pool(struct event_pool *pool, 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size, struct ibmvscsi_host_data *hostdata) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->size = size; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->next = 0; 1394c021dd136c0ad524e6d117296beafad2bf570c0FUJITA Tomonori pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pool->events) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->iu_storage = 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_alloc_coherent(hostdata->dev, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->size * sizeof(*pool->iu_storage), 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &pool->iu_token, 0); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pool->iu_storage) { 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(pool->events); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < pool->size; ++i) { 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt = &pool->events[i]; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&evt->crq, 0x00, sizeof(evt->crq)); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&evt->free, 1); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->crq.valid = 0x80; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->crq.IU_length = sizeof(*evt->xfer_iu); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->crq.IU_data_ptr = pool->iu_token + 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(*evt->xfer_iu) * i; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->xfer_iu = pool->iu_storage + i; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->hostdata = hostdata; 1624dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt->ext_list = NULL; 1634dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt->ext_list_token = 0; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * release_event_pool: - Frees memory of an event pool of a host 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool to be released 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data who owns the even pool 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns zero on success. 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void release_event_pool(struct event_pool *pool, 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmvscsi_host_data *hostdata) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, in_use = 0; 1804dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley for (i = 0; i < pool->size; ++i) { 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&pool->events[i].free) != 1) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++in_use; 1834dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (pool->events[i].ext_list) { 1844dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley dma_free_coherent(hostdata->dev, 185ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori SG_ALL * sizeof(struct srp_direct_buf), 1864dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley pool->events[i].ext_list, 1874dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley pool->events[i].ext_list_token); 1884dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 1894dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (in_use) 1916c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_warn(hostdata->dev, "releasing event pool with %d " 1926c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "events still in use?\n", in_use); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(pool->events); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_free_coherent(hostdata->dev, 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->size * sizeof(*pool->iu_storage), 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->iu_storage, pool->iu_token); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * valid_event_struct: - Determines if event is valid. 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool that contains the event 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt: srp_event_struct to be checked for validity 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns zero if event is invalid, one otherwise. 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int valid_event_struct(struct event_pool *pool, 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt) 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int index = evt - pool->events; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (index < 0 || index >= pool->size) /* outside of bounds */ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt != pool->events + index) /* unaligned */ 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_free-event_struct: - Changes status of event to "free" 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool that contains the event 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt: srp_event_struct to be modified 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void free_event_struct(struct event_pool *pool, 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt) 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!valid_event_struct(pool, evt)) { 2276c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(evt->hostdata->dev, "Freeing invalid event_struct %p " 2286c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "(not in pool %p)\n", evt, pool->events); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_inc_return(&evt->free) != 1) { 2326c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(evt->hostdata->dev, "Freeing event_struct %p " 2336c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "which is not in use!\n", evt); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_evt_struct: - Gets the next free event in pool 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool that contains the events to be searched 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the next event in "free" state, and NULL if none are free. 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that no synchronization is done here, we assume the host_lock 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will syncrhonze things. 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct srp_event_struct *get_event_struct(struct event_pool *pool) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int poolsize = pool->size; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int offset = pool->next; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < poolsize; i++) { 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = (offset + 1) % poolsize; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_dec_if_positive(&pool->events[offset].free)) { 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->next = offset; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &pool->events[offset]; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "ibmvscsi: found no event struct in pool!\n"); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * init_event_struct: Initialize fields in an event struct that are always 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * required. 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt: The event 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @done: Routine to call when the event is responded to 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @format: SRP or MAD format 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @timeout: timeout value set in the CRQ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void init_event_struct(struct srp_event_struct *evt_struct, 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void (*done) (struct srp_event_struct *), 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 format, 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int timeout) 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->cmnd = NULL; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->cmnd_done = NULL; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->sync_srp = NULL; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->crq.format = format; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->crq.timeout = timeout; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->done = done; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for receiving SCSI responses from the hosting partition 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set_srp_direction: Set the fields in the srp related to data 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * direction and number of buffers based on the direction in 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the scsi_cmnd and the number of buffers 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_srp_direction(struct scsi_cmnd *cmd, 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_cmd *srp_cmd, 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int numbuf) 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 298ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori u8 fmt; 299ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (numbuf == 0) 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 303ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (numbuf == 1) 304ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori fmt = SRP_DATA_DESC_DIRECT; 305ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori else { 306ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori fmt = SRP_DATA_DESC_INDIRECT; 307ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori numbuf = min(numbuf, MAX_INDIRECT_BUFS); 308ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd->sc_data_direction == DMA_TO_DEVICE) 310ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->data_out_desc_cnt = numbuf; 311ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori else 312ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->data_in_desc_cnt = numbuf; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 314ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 315ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (cmd->sc_data_direction == DMA_TO_DEVICE) 316ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->buf_fmt = fmt << 4; 317ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori else 318ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->buf_fmt = fmt; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: srp_cmd whose additional_data member will be unmapped 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device for which the memory is mapped 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 3274dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomleystatic void unmap_cmd_data(struct srp_cmd *cmd, 3284dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley struct srp_event_struct *evt_struct, 3294dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley struct device *dev) 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 331ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori u8 out_fmt, in_fmt; 332ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 333ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori out_fmt = cmd->buf_fmt >> 4; 334ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori in_fmt = cmd->buf_fmt & ((1U << 4) - 1); 335ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 336ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (out_fmt == SRP_NO_DATA_DESC && in_fmt == SRP_NO_DATA_DESC) 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3384dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 339a71fa1fc43a29133f13ae6ada1a389ca298c0934FUJITA Tomonori if (evt_struct->cmnd) 340a71fa1fc43a29133f13ae6ada1a389ca298c0934FUJITA Tomonori scsi_dma_unmap(evt_struct->cmnd); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3439413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonoristatic int map_sg_list(struct scsi_cmnd *cmd, int nseg, 344ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_direct_buf *md) 3454dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley{ 3464dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley int i; 3479413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori struct scatterlist *sg; 3484dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley u64 total_length = 0; 3494dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 3509413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori scsi_for_each_sg(cmd, sg, nseg, i) { 351ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_direct_buf *descr = md + i; 3529413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori descr->va = sg_dma_address(sg); 3539413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori descr->len = sg_dma_len(sg); 354ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori descr->key = 0; 3559413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori total_length += sg_dma_len(sg); 3564dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 3574dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley return total_length; 3584dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley} 3594dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: Scsi_Cmnd with the scatterlist 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @srp_cmd: srp_cmd that contains the memory descriptor 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device for which to map dma memory 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd. 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns 1 on success. 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int map_sg_data(struct scsi_cmnd *cmd, 3704dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley struct srp_event_struct *evt_struct, 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_cmd *srp_cmd, struct device *dev) 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3744dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley int sg_mapped; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 total_length = 0; 376ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_direct_buf *data = 377ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori (struct srp_direct_buf *) srp_cmd->add_data; 378ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_indirect_buf *indirect = 379ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori (struct srp_indirect_buf *) data; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3819413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori sg_mapped = scsi_dma_map(cmd); 3829413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori if (!sg_mapped) 3839413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori return 1; 3849413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori else if (sg_mapped < 0) 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_srp_direction(cmd, srp_cmd, sg_mapped); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* special case; we can use a single direct descriptor */ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sg_mapped == 1) { 3919413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori map_sg_list(cmd, sg_mapped, data); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 395ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.va = 0; 396ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.len = sg_mapped * sizeof(struct srp_direct_buf); 397ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.key = 0; 3984dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 3994dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (sg_mapped <= MAX_INDIRECT_BUFS) { 4009413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori total_length = map_sg_list(cmd, sg_mapped, 401ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori &indirect->desc_list[0]); 402ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->len = total_length; 4034dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley return 1; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4064dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley /* get indirect table */ 4074dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (!evt_struct->ext_list) { 408ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori evt_struct->ext_list = (struct srp_direct_buf *) 4099413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori dma_alloc_coherent(dev, 410ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori SG_ALL * sizeof(struct srp_direct_buf), 411ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori &evt_struct->ext_list_token, 0); 4124dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (!evt_struct->ext_list) { 4137912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings if (!firmware_has_feature(FW_FEATURE_CMO)) 4147912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings sdev_printk(KERN_ERR, cmd->device, 4157912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings "Can't allocate memory " 4167912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings "for indirect table\n"); 417e637d553199e264327714da437e6c808f2f4b096Robert Jennings scsi_dma_unmap(cmd); 4184dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley return 0; 4194dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 4204dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 4214dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 4229413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori total_length = map_sg_list(cmd, sg_mapped, evt_struct->ext_list); 4234dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 424ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->len = total_length; 425ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.va = evt_struct->ext_list_token; 426ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.len = sg_mapped * sizeof(indirect->desc_list[0]); 427ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori memcpy(indirect->desc_list, evt_struct->ext_list, 428ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori MAX_INDIRECT_BUFS * sizeof(struct srp_direct_buf)); 4294dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley return 1; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * map_data_for_srp_cmd: - Calls functions to map data for srp cmds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: struct scsi_cmnd with the memory to be mapped 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @srp_cmd: srp_cmd that contains the memory descriptor 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: dma device for which to map dma memory 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by scsi_cmd_to_srp_cmd() when converting scsi cmds to srp cmds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns 1 on success. 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int map_data_for_srp_cmd(struct scsi_cmnd *cmd, 4424dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley struct srp_event_struct *evt_struct, 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_cmd *srp_cmd, struct device *dev) 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd->sc_data_direction) { 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_FROM_DEVICE: 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_TO_DEVICE: 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_NONE: 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_BIDIRECTIONAL: 4526c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_ERR, cmd->device, 4536c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "Can't map DMA_BIDIRECTIONAL to read/write\n"); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4566c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_ERR, cmd->device, 4576c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "Unknown data direction 0x%02x; can't map!\n", 4586c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King cmd->sc_data_direction); 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4629413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori return map_sg_data(cmd, evt_struct, srp_cmd, dev); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4653d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King/** 4663d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * purge_requests: Our virtual adapter just shut down. purge any sent requests 4673d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @hostdata: the adapter 4683d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King */ 4693d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian Kingstatic void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) 4703d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King{ 4711117ef8aed95521f46dae3052c7120baae48c2bbBrian King struct srp_event_struct *evt; 4723d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King unsigned long flags; 4733d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 4743d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King spin_lock_irqsave(hostdata->host->host_lock, flags); 4751117ef8aed95521f46dae3052c7120baae48c2bbBrian King while (!list_empty(&hostdata->sent)) { 4761117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt = list_first_entry(&hostdata->sent, struct srp_event_struct, list); 4771117ef8aed95521f46dae3052c7120baae48c2bbBrian King list_del(&evt->list); 4781117ef8aed95521f46dae3052c7120baae48c2bbBrian King del_timer(&evt->timer); 4791117ef8aed95521f46dae3052c7120baae48c2bbBrian King 4801117ef8aed95521f46dae3052c7120baae48c2bbBrian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 4811117ef8aed95521f46dae3052c7120baae48c2bbBrian King if (evt->cmnd) { 4821117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt->cmnd->result = (error_code << 16); 4831117ef8aed95521f46dae3052c7120baae48c2bbBrian King unmap_cmd_data(&evt->iu.srp.cmd, evt, 4841117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt->hostdata->dev); 4851117ef8aed95521f46dae3052c7120baae48c2bbBrian King if (evt->cmnd_done) 4861117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt->cmnd_done(evt->cmnd); 4871117ef8aed95521f46dae3052c7120baae48c2bbBrian King } else if (evt->done) 4881117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt->done(evt); 4891117ef8aed95521f46dae3052c7120baae48c2bbBrian King free_event_struct(&evt->hostdata->pool, evt); 4901117ef8aed95521f46dae3052c7120baae48c2bbBrian King spin_lock_irqsave(hostdata->host->host_lock, flags); 4913d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King } 4923d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 4933d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King} 4943d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 4953d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King/** 4963d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * ibmvscsi_reset_host - Reset the connection to the server 4973d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @hostdata: struct ibmvscsi_host_data to reset 4983d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King*/ 4993d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian Kingstatic void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata) 5003d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King{ 5013d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King scsi_block_requests(hostdata->host); 5023d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King atomic_set(&hostdata->request_limit, 0); 5033d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5043d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King purge_requests(hostdata, DID_ERROR); 5050f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->reset_crq = 1; 5060f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King wake_up(&hostdata->work_wait_q); 5073d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King} 5083d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5093d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King/** 5103d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * ibmvscsi_timeout - Internal command timeout handler 5113d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @evt_struct: struct srp_event_struct that timed out 5123d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * 5133d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * Called when an internally generated command times out 5143d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King*/ 5153d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian Kingstatic void ibmvscsi_timeout(struct srp_event_struct *evt_struct) 5163d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King{ 5173d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 5183d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5193d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King dev_err(hostdata->dev, "Command timed out (%x). Resetting connection\n", 5203d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King evt_struct->iu.srp.cmd.opcode); 5213d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5223d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King ibmvscsi_reset_host(hostdata); 5233d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King} 5243d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5253d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for sending and receiving SRPs 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_send_srp_event: - Transforms event to u64 array and calls send_crq() 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt_struct: evt_struct to be sent 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data of host 5333d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @timeout: timeout in seconds - 0 means do not time command 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the value returned from ibmvscsi_send_crq(). (Zero for success) 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that this routine assumes that host_lock is held for synchronization 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, 5393d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King struct ibmvscsi_host_data *hostdata, 5403d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King unsigned long timeout) 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 *crq_as_u64 = (u64 *) &evt_struct->crq; 5433c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings int request_status = 0; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 545f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King int srp_req = 0; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 547a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings /* If we have exhausted our request limit, just fail this request, 548a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * unless it is for a reset or abort. 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that there are rare cases involving driver generated requests 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (such as task management requests) that the mid layer may think we 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can handle more requests (can_queue) when we actually can't 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 553cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher if (evt_struct->crq.format == VIOSRP_SRP_FORMAT) { 554f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King srp_req = 1; 555cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher request_status = 556cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher atomic_dec_if_positive(&hostdata->request_limit); 557cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher /* If request limit was -1 when we started, it is now even 558cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher * less than that 559cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher */ 560cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher if (request_status < -1) 561cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher goto send_error; 562a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings /* Otherwise, we may have run out of requests. */ 5633c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings /* If request limit was 0 when we started the adapter is in the 5643c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings * process of performing a login with the server adapter, or 5653c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings * we may have run out of requests. 5663c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings */ 5673c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings else if (request_status == -1 && 5683c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings evt_struct->iu.srp.login_req.opcode != SRP_LOGIN_REQ) 5693c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings goto send_busy; 570a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings /* Abort and reset calls should make it through. 571a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * Nothing except abort and reset should use the last two 572a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * slots unless we had two or less to begin with. 573a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings */ 574a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings else if (request_status < 2 && 575a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings evt_struct->iu.srp.cmd.opcode != SRP_TSK_MGMT) { 576a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings /* In the case that we have less than two requests 577a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * available, check the server limit as a combination 578a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * of the request limit and the number of requests 579a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * in-flight (the size of the send list). If the 580a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * server limit is greater than 2, return busy so 581a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * that the last two are reserved for reset and abort. 582a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings */ 583a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings int server_limit = request_status; 584a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings struct srp_event_struct *tmp_evt; 585a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings 586a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings list_for_each_entry(tmp_evt, &hostdata->sent, list) { 587a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings server_limit++; 588a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings } 589a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings 590a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings if (server_limit > 2) 591a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings goto send_busy; 592a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings } 593cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher } 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Copy the IU into the transfer area */ 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *evt_struct->xfer_iu = evt_struct->iu; 597ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori evt_struct->xfer_iu->srp.rsp.tag = (u64)evt_struct; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Add this to the sent list. We need to do this 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before we actually send 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in case it comes back REALLY fast 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&evt_struct->list, &hostdata->sent); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6053d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King init_timer(&evt_struct->timer); 6063d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King if (timeout) { 6073d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King evt_struct->timer.data = (unsigned long) evt_struct; 6083d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King evt_struct->timer.expires = jiffies + (timeout * HZ); 6093d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King evt_struct->timer.function = (void (*)(unsigned long))ibmvscsi_timeout; 6103d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King add_timer(&evt_struct->timer); 6113d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King } 6123d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((rc = 614d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&evt_struct->list); 6163d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King del_timer(&evt_struct->timer); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 618860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings /* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY. 619860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings * Firmware will send a CRQ with a transport event (0xFF) to 620860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings * tell this client what has happened to the transport. This 621860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings * will be handled in ibmvscsi_handle_crq() 622860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings */ 623860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (rc == H_CLOSED) { 624860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings dev_warn(hostdata->dev, "send warning. " 625860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings "Receive queue closed, will retry.\n"); 626860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings goto send_busy; 627860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 6286c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "send error %d\n", rc); 629f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King if (srp_req) 630f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King atomic_inc(&hostdata->request_limit); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto send_error; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 636cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher send_busy: 6374dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&hostdata->pool, evt_struct); 640f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King if (srp_req && request_status != -1) 6413c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings atomic_inc(&hostdata->request_limit); 642a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings return SCSI_MLQUEUE_HOST_BUSY; 643cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher 644cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher send_error: 645cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); 646cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher 647cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher if (evt_struct->cmnd != NULL) { 648cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher evt_struct->cmnd->result = DID_ERROR << 16; 649cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher evt_struct->cmnd_done(evt_struct->cmnd); 650cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher } else if (evt_struct->done) 651cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher evt_struct->done(evt_struct); 652cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher 653cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher free_event_struct(&hostdata->pool, evt_struct); 654cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher return 0; 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handle_cmd_rsp: - Handle responses from commands 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt_struct: srp_event_struct to be handled 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used as a callback by when sending scsi cmds. 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Gets called by ibmvscsi_handle_crq() 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void handle_cmd_rsp(struct srp_event_struct *evt_struct) 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_cmnd *cmnd = evt_struct->cmnd; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 669ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (unlikely(rsp->opcode != SRP_RSP)) { 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 6716c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_warn(evt_struct->hostdata->dev, 6726c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "bad SRP RSP type %d\n", rsp->opcode); 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmnd) { 676c3a3b55ae80a0d595445064159c69f8e80911e85Brian King cmnd->result |= rsp->status; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION) 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(cmnd->sense_buffer, 679ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori rsp->data, 680ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori rsp->sense_data_len); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unmap_cmd_data(&evt_struct->iu.srp.cmd, 6824dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt_struct, 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->hostdata->dev); 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 685ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (rsp->flags & SRP_RSP_FLAG_DOOVER) 6869413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori scsi_set_resid(cmnd, rsp->data_out_res_cnt); 687ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori else if (rsp->flags & SRP_RSP_FLAG_DIOVER) 6889413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori scsi_set_resid(cmnd, rsp->data_in_res_cnt); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt_struct->cmnd_done) 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->cmnd_done(cmnd); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lun_from_dev: - Returns the lun of the scsi device 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: struct scsi_device 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u16 lun_from_dev(struct scsi_device *dev) 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0x2 << 14) | (dev->id << 8) | (dev->channel << 5) | dev->lun; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_queue: - The queuecommand function of the scsi template 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: struct scsi_cmnd to be executed 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @done: Callback function to be called when cmd is completed 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 710f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzikstatic int ibmvscsi_queuecommand_lck(struct scsi_cmnd *cmnd, 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void (*done) (struct scsi_cmnd *)) 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_cmd *srp_cmd; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt_struct; 715ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_indirect_buf *indirect; 7167603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(cmnd->device->host); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 lun = lun_from_dev(cmnd->device); 718ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori u8 out_fmt, in_fmt; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 720c3a3b55ae80a0d595445064159c69f8e80911e85Brian King cmnd->result = (DID_OK << 16); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct = get_event_struct(&hostdata->pool); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!evt_struct) 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up the actual SRP IU */ 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds srp_cmd = &evt_struct->iu.srp.cmd; 727ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori memset(srp_cmd, 0x00, SRP_MAX_IU_LEN); 728ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->opcode = SRP_CMD; 72964a87b244b9297667ca80264aab849a36f494884Boaz Harrosh memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb)); 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds srp_cmd->lun = ((u64) lun) << 48; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7324dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { 7337912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings if (!firmware_has_feature(FW_FEATURE_CMO)) 7347912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings sdev_printk(KERN_ERR, cmnd->device, 7357912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings "couldn't convert cmd to srp_cmd\n"); 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&hostdata->pool, evt_struct); 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7404dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley init_event_struct(evt_struct, 7414dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley handle_cmd_rsp, 7424dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley VIOSRP_SRP_FORMAT, 743242f9dcb8ba6f68fcd217a119a7648a4f69290e9Jens Axboe cmnd->request->timeout/HZ); 7444dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 7454dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt_struct->cmnd = cmnd; 7464dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt_struct->cmnd_done = done; 7474dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fix up dma address of the buffer itself */ 749ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect = (struct srp_indirect_buf *) srp_cmd->add_data; 750ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori out_fmt = srp_cmd->buf_fmt >> 4; 751ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori in_fmt = srp_cmd->buf_fmt & ((1U << 4) - 1); 752ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if ((in_fmt == SRP_DATA_DESC_INDIRECT || 753ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori out_fmt == SRP_DATA_DESC_INDIRECT) && 754ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.va == 0) { 755ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.va = evt_struct->crq.IU_data_ptr + 756ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori offsetof(struct srp_cmd, add_data) + 757ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori offsetof(struct srp_indirect_buf, desc_list); 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7603d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King return ibmvscsi_send_srp_event(evt_struct, hostdata, 0); 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 763f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzikstatic DEF_SCSI_QCMD(ibmvscsi_queuecommand) 764f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzik 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for driver initialization 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7683507e13fcba6b97501891a410ec8ef9f1f188620Brian King 7693507e13fcba6b97501891a410ec8ef9f1f188620Brian King/** 770126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * map_persist_bufs: - Pre-map persistent data for adapter logins 771126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * @hostdata: ibmvscsi_host_data of host 772126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * 773126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * Map the capabilities and adapter info DMA buffers to avoid runtime failures. 774126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * Return 1 on error, 0 on success. 775126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King */ 776126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic int map_persist_bufs(struct ibmvscsi_host_data *hostdata) 777126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 778126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 779126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps_addr = dma_map_single(hostdata->dev, &hostdata->caps, 780126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->caps), DMA_BIDIRECTIONAL); 781126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 782126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (dma_mapping_error(hostdata->dev, hostdata->caps_addr)) { 783126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(hostdata->dev, "Unable to map capabilities buffer!\n"); 784126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return 1; 785126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 786126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 787126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->adapter_info_addr = dma_map_single(hostdata->dev, 788126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King &hostdata->madapter_info, 789126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->madapter_info), 790126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King DMA_BIDIRECTIONAL); 791126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (dma_mapping_error(hostdata->dev, hostdata->adapter_info_addr)) { 792126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(hostdata->dev, "Unable to map adapter info buffer!\n"); 793126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dma_unmap_single(hostdata->dev, hostdata->caps_addr, 794126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->caps), DMA_BIDIRECTIONAL); 795126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return 1; 796126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 797126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 798126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return 0; 799126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 800126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 801126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King/** 802126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * unmap_persist_bufs: - Unmap persistent data needed for adapter logins 803126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * @hostdata: ibmvscsi_host_data of host 804126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * 805126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * Unmap the capabilities and adapter info DMA buffers 806126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King */ 807126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic void unmap_persist_bufs(struct ibmvscsi_host_data *hostdata) 808126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 809126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dma_unmap_single(hostdata->dev, hostdata->caps_addr, 810126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->caps), DMA_BIDIRECTIONAL); 811126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 812126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dma_unmap_single(hostdata->dev, hostdata->adapter_info_addr, 813126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->madapter_info), DMA_BIDIRECTIONAL); 814126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 815126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 816126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King/** 8173507e13fcba6b97501891a410ec8ef9f1f188620Brian King * login_rsp: - Handle response to SRP login request 8183507e13fcba6b97501891a410ec8ef9f1f188620Brian King * @evt_struct: srp_event_struct with the response 8193507e13fcba6b97501891a410ec8ef9f1f188620Brian King * 8203507e13fcba6b97501891a410ec8ef9f1f188620Brian King * Used as a "done" callback by when sending srp_login. Gets called 8213507e13fcba6b97501891a410ec8ef9f1f188620Brian King * by ibmvscsi_handle_crq() 8223507e13fcba6b97501891a410ec8ef9f1f188620Brian King*/ 8233507e13fcba6b97501891a410ec8ef9f1f188620Brian Kingstatic void login_rsp(struct srp_event_struct *evt_struct) 8243507e13fcba6b97501891a410ec8ef9f1f188620Brian King{ 8253507e13fcba6b97501891a410ec8ef9f1f188620Brian King struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 8263507e13fcba6b97501891a410ec8ef9f1f188620Brian King switch (evt_struct->xfer_iu->srp.login_rsp.opcode) { 8273507e13fcba6b97501891a410ec8ef9f1f188620Brian King case SRP_LOGIN_RSP: /* it worked! */ 8283507e13fcba6b97501891a410ec8ef9f1f188620Brian King break; 8293507e13fcba6b97501891a410ec8ef9f1f188620Brian King case SRP_LOGIN_REJ: /* refused! */ 8303507e13fcba6b97501891a410ec8ef9f1f188620Brian King dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n", 8313507e13fcba6b97501891a410ec8ef9f1f188620Brian King evt_struct->xfer_iu->srp.login_rej.reason); 8323507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* Login failed. */ 8333507e13fcba6b97501891a410ec8ef9f1f188620Brian King atomic_set(&hostdata->request_limit, -1); 8343507e13fcba6b97501891a410ec8ef9f1f188620Brian King return; 8353507e13fcba6b97501891a410ec8ef9f1f188620Brian King default: 8363507e13fcba6b97501891a410ec8ef9f1f188620Brian King dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n", 8373507e13fcba6b97501891a410ec8ef9f1f188620Brian King evt_struct->xfer_iu->srp.login_rsp.opcode); 8383507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* Login failed. */ 8393507e13fcba6b97501891a410ec8ef9f1f188620Brian King atomic_set(&hostdata->request_limit, -1); 8403507e13fcba6b97501891a410ec8ef9f1f188620Brian King return; 8413507e13fcba6b97501891a410ec8ef9f1f188620Brian King } 8423507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8433507e13fcba6b97501891a410ec8ef9f1f188620Brian King dev_info(hostdata->dev, "SRP_LOGIN succeeded\n"); 844126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->client_migrated = 0; 8453507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8463507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* Now we know what the real request-limit is. 8473507e13fcba6b97501891a410ec8ef9f1f188620Brian King * This value is set rather than added to request_limit because 8483507e13fcba6b97501891a410ec8ef9f1f188620Brian King * request_limit could have been set to -1 by this client. 8493507e13fcba6b97501891a410ec8ef9f1f188620Brian King */ 8503507e13fcba6b97501891a410ec8ef9f1f188620Brian King atomic_set(&hostdata->request_limit, 8513507e13fcba6b97501891a410ec8ef9f1f188620Brian King evt_struct->xfer_iu->srp.login_rsp.req_lim_delta); 8523507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8533507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* If we had any pending I/Os, kick them */ 8543507e13fcba6b97501891a410ec8ef9f1f188620Brian King scsi_unblock_requests(hostdata->host); 8553507e13fcba6b97501891a410ec8ef9f1f188620Brian King} 8563507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8573507e13fcba6b97501891a410ec8ef9f1f188620Brian King/** 8583507e13fcba6b97501891a410ec8ef9f1f188620Brian King * send_srp_login: - Sends the srp login 8593507e13fcba6b97501891a410ec8ef9f1f188620Brian King * @hostdata: ibmvscsi_host_data of host 8603507e13fcba6b97501891a410ec8ef9f1f188620Brian King * 8613507e13fcba6b97501891a410ec8ef9f1f188620Brian King * Returns zero if successful. 8623507e13fcba6b97501891a410ec8ef9f1f188620Brian King*/ 8633507e13fcba6b97501891a410ec8ef9f1f188620Brian Kingstatic int send_srp_login(struct ibmvscsi_host_data *hostdata) 8643507e13fcba6b97501891a410ec8ef9f1f188620Brian King{ 8653507e13fcba6b97501891a410ec8ef9f1f188620Brian King int rc; 8663507e13fcba6b97501891a410ec8ef9f1f188620Brian King unsigned long flags; 8673507e13fcba6b97501891a410ec8ef9f1f188620Brian King struct srp_login_req *login; 8683507e13fcba6b97501891a410ec8ef9f1f188620Brian King struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool); 8693507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8703507e13fcba6b97501891a410ec8ef9f1f188620Brian King BUG_ON(!evt_struct); 8713507e13fcba6b97501891a410ec8ef9f1f188620Brian King init_event_struct(evt_struct, login_rsp, 8723507e13fcba6b97501891a410ec8ef9f1f188620Brian King VIOSRP_SRP_FORMAT, login_timeout); 8733507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8743507e13fcba6b97501891a410ec8ef9f1f188620Brian King login = &evt_struct->iu.srp.login_req; 8753507e13fcba6b97501891a410ec8ef9f1f188620Brian King memset(login, 0, sizeof(*login)); 8763507e13fcba6b97501891a410ec8ef9f1f188620Brian King login->opcode = SRP_LOGIN_REQ; 8773507e13fcba6b97501891a410ec8ef9f1f188620Brian King login->req_it_iu_len = sizeof(union srp_iu); 8783507e13fcba6b97501891a410ec8ef9f1f188620Brian King login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; 8793507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8803507e13fcba6b97501891a410ec8ef9f1f188620Brian King spin_lock_irqsave(hostdata->host->host_lock, flags); 8813507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* Start out with a request limit of 0, since this is negotiated in 8823507e13fcba6b97501891a410ec8ef9f1f188620Brian King * the login request we are just sending and login requests always 8833507e13fcba6b97501891a410ec8ef9f1f188620Brian King * get sent by the driver regardless of request_limit. 8843507e13fcba6b97501891a410ec8ef9f1f188620Brian King */ 8853507e13fcba6b97501891a410ec8ef9f1f188620Brian King atomic_set(&hostdata->request_limit, 0); 8863507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8873507e13fcba6b97501891a410ec8ef9f1f188620Brian King rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2); 8883507e13fcba6b97501891a410ec8ef9f1f188620Brian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 8893507e13fcba6b97501891a410ec8ef9f1f188620Brian King dev_info(hostdata->dev, "sent SRP login\n"); 8903507e13fcba6b97501891a410ec8ef9f1f188620Brian King return rc; 8913507e13fcba6b97501891a410ec8ef9f1f188620Brian King}; 8923507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 894126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * capabilities_rsp: - Handle response to MAD adapter capabilities request 895126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * @evt_struct: srp_event_struct with the response 896126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * 897126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * Used as a "done" callback by when sending adapter_info. 898126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King */ 899126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic void capabilities_rsp(struct srp_event_struct *evt_struct) 900126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 901126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 902126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 903126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (evt_struct->xfer_iu->mad.capabilities.common.status) { 904126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(hostdata->dev, "error 0x%X getting capabilities info\n", 905126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King evt_struct->xfer_iu->mad.capabilities.common.status); 906126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } else { 907126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (hostdata->caps.migration.common.server_support != SERVER_SUPPORTS_CAP) 908126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_info(hostdata->dev, "Partition migration not supported\n"); 909126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 910126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (client_reserve) { 911126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (hostdata->caps.reserve.common.server_support == 912126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King SERVER_SUPPORTS_CAP) 913126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_info(hostdata->dev, "Client reserve enabled\n"); 914126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King else 915126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_info(hostdata->dev, "Client reserve not supported\n"); 916126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 917126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 918126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 919126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King send_srp_login(hostdata); 920126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 921126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 922126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King/** 923126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * send_mad_capabilities: - Sends the mad capabilities request 924126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * and stores the result so it can be retrieved with 925126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * @hostdata: ibmvscsi_host_data of host 926126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King */ 927126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic void send_mad_capabilities(struct ibmvscsi_host_data *hostdata) 928126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 929126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct viosrp_capabilities *req; 930126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct srp_event_struct *evt_struct; 931126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King unsigned long flags; 93261c7a080a5a061c976988fd4b844dfb468dda255Grant Likely struct device_node *of_node = hostdata->dev->of_node; 933126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King const char *location; 934126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 935126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King evt_struct = get_event_struct(&hostdata->pool); 936126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King BUG_ON(!evt_struct); 937126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 938126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King init_event_struct(evt_struct, capabilities_rsp, 939126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King VIOSRP_MAD_FORMAT, info_timeout); 940126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 941126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req = &evt_struct->iu.mad.capabilities; 942126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King memset(req, 0, sizeof(*req)); 943126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 944126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.flags = CAP_LIST_SUPPORTED; 945126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (hostdata->client_migrated) 946126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.flags |= CLIENT_MIGRATED; 947126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 948126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King strncpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev), 949126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->caps.name)); 950126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.name[sizeof(hostdata->caps.name) - 1] = '\0'; 951126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 952126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King location = of_get_property(of_node, "ibm,loc-code", NULL); 953126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King location = location ? location : dev_name(hostdata->dev); 954126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King strncpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc)); 955126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.loc[sizeof(hostdata->caps.loc) - 1] = '\0'; 956126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 957126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->common.type = VIOSRP_CAPABILITIES_TYPE; 958126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->buffer = hostdata->caps_addr; 959126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 960126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.migration.common.cap_type = MIGRATION_CAPABILITIES; 961126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.migration.common.length = sizeof(hostdata->caps.migration); 962126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.migration.common.server_support = SERVER_SUPPORTS_CAP; 963126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.migration.ecl = 1; 964126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 965126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (client_reserve) { 966126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.reserve.common.cap_type = RESERVATION_CAPABILITIES; 967126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.reserve.common.length = sizeof(hostdata->caps.reserve); 968126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.reserve.common.server_support = SERVER_SUPPORTS_CAP; 969126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.reserve.type = CLIENT_RESERVE_SCSI_2; 970126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->common.length = sizeof(hostdata->caps); 971126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } else 972126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->common.length = sizeof(hostdata->caps) - sizeof(hostdata->caps.reserve); 973126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 974126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King spin_lock_irqsave(hostdata->host->host_lock, flags); 975126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2)) 976126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(hostdata->dev, "couldn't send CAPABILITIES_REQ!\n"); 977126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 978126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King}; 979126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 980126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King/** 981c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * fast_fail_rsp: - Handle response to MAD enable fast fail 982c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * @evt_struct: srp_event_struct with the response 983c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * 984c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * Used as a "done" callback by when sending enable fast fail. Gets called 985c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * by ibmvscsi_handle_crq() 986c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings */ 987c1988e3123751fd425fbae99d5c1776608e965a9Robert Jenningsstatic void fast_fail_rsp(struct srp_event_struct *evt_struct) 988c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings{ 989c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 990c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings u8 status = evt_struct->xfer_iu->mad.fast_fail.common.status; 991c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 992c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings if (status == VIOSRP_MAD_NOT_SUPPORTED) 993c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings dev_err(hostdata->dev, "fast_fail not supported in server\n"); 994c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings else if (status == VIOSRP_MAD_FAILED) 995c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings dev_err(hostdata->dev, "fast_fail request failed\n"); 996c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings else if (status != VIOSRP_MAD_SUCCESS) 997c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings dev_err(hostdata->dev, "error 0x%X enabling fast_fail\n", status); 998c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 999126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King send_mad_capabilities(hostdata); 1000c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings} 1001c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1002c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings/** 1003c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * init_host - Start host initialization 1004c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * @hostdata: ibmvscsi_host_data of host 1005c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * 1006c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * Returns zero if successful. 1007c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings */ 1008c1988e3123751fd425fbae99d5c1776608e965a9Robert Jenningsstatic int enable_fast_fail(struct ibmvscsi_host_data *hostdata) 1009c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings{ 1010c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings int rc; 1011c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings unsigned long flags; 1012c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings struct viosrp_fast_fail *fast_fail_mad; 1013c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings struct srp_event_struct *evt_struct; 1014c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1015126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (!fast_fail) { 1016126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King send_mad_capabilities(hostdata); 1017126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return 0; 1018126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 1019c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1020c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings evt_struct = get_event_struct(&hostdata->pool); 1021c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings BUG_ON(!evt_struct); 1022c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1023c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings init_event_struct(evt_struct, fast_fail_rsp, VIOSRP_MAD_FORMAT, info_timeout); 1024c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1025c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings fast_fail_mad = &evt_struct->iu.mad.fast_fail; 1026c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings memset(fast_fail_mad, 0, sizeof(*fast_fail_mad)); 1027c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings fast_fail_mad->common.type = VIOSRP_ENABLE_FAST_FAIL; 1028c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings fast_fail_mad->common.length = sizeof(*fast_fail_mad); 1029c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1030c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings spin_lock_irqsave(hostdata->host->host_lock, flags); 1031c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings rc = ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2); 1032c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1033c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings return rc; 1034c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings} 1035c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1036c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings/** 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adapter_info_rsp: - Handle response to MAD adapter info request 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt_struct: srp_event_struct with the response 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used as a "done" callback by when sending adapter_info. Gets called 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by ibmvscsi_handle_crq() 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adapter_info_rsp(struct srp_event_struct *evt_struct) 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt_struct->xfer_iu->mad.adapter_info.common.status) { 10486c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "error %d getting adapter info\n", 10496c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King evt_struct->xfer_iu->mad.adapter_info.common.status); 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10516c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_info(hostdata->dev, "host srp version: %s, " 10526c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "host partition %s (%d), OS %d, max io %u\n", 10536c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.srp_version, 10546c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.partition_name, 10556c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.partition_number, 10566c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.os_type, 10576c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.port_max_txu[0]); 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hostdata->madapter_info.port_max_txu[0]) 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->host->max_sectors = 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.port_max_txu[0] >> 9; 1062154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher 1063154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher if (hostdata->madapter_info.os_type == 3 && 1064154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) { 10656c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "host (Ver. %s) doesn't support large transfers\n", 10666c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.srp_version); 10676c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "limiting scatterlists to %d\n", 10686c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King MAX_INDIRECT_BUFS); 1069154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; 1070154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher } 1071e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King 1072e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King if (hostdata->madapter_info.os_type == 3) { 1073e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King enable_fast_fail(hostdata); 1074e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King return; 1075e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King } 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10773507e13fcba6b97501891a410ec8ef9f1f188620Brian King 1078e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King send_srp_login(hostdata); 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * send_mad_adapter_info: - Sends the mad adapter info request 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and stores the result so it can be retrieved with 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysfs. We COULD consider causing a failure if the 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returned SRP version doesn't match ours. 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data of host 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns zero if successful. 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata) 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct viosrp_adapter_info *req; 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt_struct; 109406f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King unsigned long flags; 1095e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct = get_event_struct(&hostdata->pool); 10973507e13fcba6b97501891a410ec8ef9f1f188620Brian King BUG_ON(!evt_struct); 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_event_struct(evt_struct, 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter_info_rsp, 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VIOSRP_MAD_FORMAT, 1102e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings info_timeout); 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req = &evt_struct->iu.mad.adapter_info; 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(req, 0x00, sizeof(*req)); 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->common.type = VIOSRP_ADAPTER_INFO_TYPE; 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->common.length = sizeof(hostdata->madapter_info); 1109126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->buffer = hostdata->adapter_info_addr; 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111106f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King spin_lock_irqsave(hostdata->host->host_lock, flags); 1112126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2)) 11136c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "couldn't send ADAPTER_INFO_REQ!\n"); 111406f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 11183507e13fcba6b97501891a410ec8ef9f1f188620Brian King * init_adapter: Start virtual adapter initialization sequence 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11203507e13fcba6b97501891a410ec8ef9f1f188620Brian King */ 11213507e13fcba6b97501891a410ec8ef9f1f188620Brian Kingstatic void init_adapter(struct ibmvscsi_host_data *hostdata) 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_mad_adapter_info(hostdata); 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sync_completion: Signal that a synchronous command has completed 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that after returning from this call, the evt_struct is freed. 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the caller waiting on this completion shouldn't touch the evt_struct 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * again. 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sync_completion(struct srp_event_struct *evt_struct) 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy the response back */ 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt_struct->sync_srp) 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *evt_struct->sync_srp = *evt_struct->xfer_iu; 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete(&evt_struct->comp); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_abort: Abort a command...from scsi host template 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * send this over to the server and wait synchronously for the response 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11477603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_tsk_mgmt *tsk_mgmt; 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt; 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *tmp_evt, *found_evt; 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union viosrp_iu srp_rsp; 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rsp_rc; 1153be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher unsigned long flags; 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 lun = lun_from_dev(cmd->device); 1155860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings unsigned long wait_switch = 0; 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First, find this command in our sent list so we can figure 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * out the correct tag 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1160be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_lock_irqsave(hostdata->host->host_lock, flags); 1161860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings wait_switch = jiffies + (init_timeout * HZ); 1162860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings do { 1163860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings found_evt = NULL; 1164860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings list_for_each_entry(tmp_evt, &hostdata->sent, list) { 1165860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (tmp_evt->cmnd == cmd) { 1166860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings found_evt = tmp_evt; 1167860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings break; 1168860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (!found_evt) { 1172860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1173860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings return SUCCESS; 1174860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1176860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings evt = get_event_struct(&hostdata->pool); 1177860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (evt == NULL) { 1178860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1179860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sdev_printk(KERN_ERR, cmd->device, 1180860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings "failed to allocate abort event\n"); 1181860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings return FAILED; 1182860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1184860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings init_event_struct(evt, 1185860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sync_completion, 1186860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings VIOSRP_SRP_FORMAT, 1187e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings abort_timeout); 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1189860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt = &evt->iu.srp.tsk_mgmt; 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings /* Set up an abort SRP command */ 1192860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt)); 1193860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->opcode = SRP_TSK_MGMT; 1194860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->lun = ((u64) lun) << 48; 1195860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK; 1196860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->task_tag = (u64) found_evt; 1197860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1198860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings evt->sync_srp = &srp_rsp; 1199860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1200860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings init_completion(&evt->comp); 1201e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, abort_timeout * 2); 1202860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1203860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY) 1204860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings break; 1205860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1206860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1207860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings msleep(10); 1208860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_lock_irqsave(hostdata->host->host_lock, flags); 1209860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } while (time_before(jiffies, wait_switch)); 1210860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1211be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1212860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1213be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher if (rsp_rc != 0) { 12146c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_ERR, cmd->device, 12156c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "failed to send abort() event. rc=%d\n", rsp_rc); 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1219860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sdev_printk(KERN_INFO, cmd->device, 1220fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar "aborting command. lun 0x%llx, tag 0x%llx\n", 1221860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings (((u64) lun) << 48), (u64) found_evt); 1222860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_for_completion(&evt->comp); 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* make sure we got a good response */ 1226ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) { 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 12286c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_WARNING, cmd->device, "abort bad SRP RSP type %d\n", 12296c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King srp_rsp.srp.rsp.opcode); 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1233ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID) 1234ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori rsp_rc = *((int *)srp_rsp.srp.rsp.data); 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rsp_rc = srp_rsp.srp.rsp.status; 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rsp_rc) { 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 12406c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_WARNING, cmd->device, 1241fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar "abort code %d for task tag 0x%llx\n", 12426c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King rsp_rc, tsk_mgmt->task_tag); 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Because we dropped the spinlock above, it's possible 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The event is no longer in our list. Make sure it didn't 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complete while we were aborting 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1250be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_lock_irqsave(hostdata->host->host_lock, flags); 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found_evt = NULL; 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(tmp_evt, &hostdata->sent, list) { 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp_evt->cmnd == cmd) { 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found_evt = tmp_evt; 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (found_evt == NULL) { 1260be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1261fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%llx completed\n", 12626c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King tsk_mgmt->task_tag); 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1266fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%llx\n", 12676c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King tsk_mgmt->task_tag); 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd->result = (DID_ABORT << 16); 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&found_evt->list); 12714dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt, 12724dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley found_evt->hostdata->dev); 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&found_evt->hostdata->pool, found_evt); 1274be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&hostdata->request_limit); 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_eh_device_reset_handler: Reset a single LUN...from scsi host 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * template send this over to the server and wait synchronously for the 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12867603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_tsk_mgmt *tsk_mgmt; 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt; 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *tmp_evt, *pos; 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union viosrp_iu srp_rsp; 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rsp_rc; 1292be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher unsigned long flags; 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 lun = lun_from_dev(cmd->device); 1294860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings unsigned long wait_switch = 0; 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1296be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_lock_irqsave(hostdata->host->host_lock, flags); 1297860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings wait_switch = jiffies + (init_timeout * HZ); 1298860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings do { 1299860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings evt = get_event_struct(&hostdata->pool); 1300860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (evt == NULL) { 1301860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1302860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sdev_printk(KERN_ERR, cmd->device, 1303860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings "failed to allocate reset event\n"); 1304860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings return FAILED; 1305860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1307860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings init_event_struct(evt, 1308860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sync_completion, 1309860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings VIOSRP_SRP_FORMAT, 1310e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings reset_timeout); 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1312860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt = &evt->iu.srp.tsk_mgmt; 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1314860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings /* Set up a lun reset SRP command */ 1315860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt)); 1316860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->opcode = SRP_TSK_MGMT; 1317860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->lun = ((u64) lun) << 48; 1318860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET; 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1320860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings evt->sync_srp = &srp_rsp; 1321860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1322860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings init_completion(&evt->comp); 1323e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, reset_timeout * 2); 1324860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1325860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY) 1326860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings break; 1327860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1328860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1329860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings msleep(10); 1330860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_lock_irqsave(hostdata->host->host_lock, flags); 1331860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } while (time_before(jiffies, wait_switch)); 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1333be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1334860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1335be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher if (rsp_rc != 0) { 13366c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_ERR, cmd->device, 13376c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "failed to send reset event. rc=%d\n", rsp_rc); 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%llx\n", 1342860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings (((u64) lun) << 48)); 1343860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_for_completion(&evt->comp); 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* make sure we got a good response */ 1347ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) { 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 13496c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_WARNING, cmd->device, "reset bad SRP RSP type %d\n", 13506c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King srp_rsp.srp.rsp.opcode); 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1354ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID) 1355ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori rsp_rc = *((int *)srp_rsp.srp.rsp.data); 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rsp_rc = srp_rsp.srp.rsp.status; 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rsp_rc) { 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 13616c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_WARNING, cmd->device, 1362fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar "reset code %d for task tag 0x%llx\n", 13636c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King rsp_rc, tsk_mgmt->task_tag); 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We need to find all commands for this LUN that have not yet been 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * responded to, and fail them with DID_RESET 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1370be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_lock_irqsave(hostdata->host->host_lock, flags); 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) { 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp_evt->cmnd) 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_evt->cmnd->result = (DID_RESET << 16); 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&tmp_evt->list); 13764dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt, 13774dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley tmp_evt->hostdata->dev); 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&tmp_evt->hostdata->pool, 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_evt); 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&hostdata->request_limit); 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp_evt->cmnd_done) 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_evt->cmnd_done(tmp_evt->cmnd); 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (tmp_evt->done) 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_evt->done(tmp_evt); 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1387be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 13923d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * ibmvscsi_eh_host_reset_handler - Reset the connection to the server 13933d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @cmd: struct scsi_cmnd having problems 13943d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King*/ 13953d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian Kingstatic int ibmvscsi_eh_host_reset_handler(struct scsi_cmnd *cmd) 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13973d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King unsigned long wait_switch = 0; 13987603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14003d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King dev_err(hostdata->dev, "Resetting connection due to error recovery\n"); 14013d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14023d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King ibmvscsi_reset_host(hostdata); 14033d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14043d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King for (wait_switch = jiffies + (init_timeout * HZ); 14053d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King time_before(jiffies, wait_switch) && 14063d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King atomic_read(&hostdata->request_limit) < 2;) { 14073d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14083d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King msleep(10); 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14103d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14113d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King if (atomic_read(&hostdata->request_limit) <= 0) 14123d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King return FAILED; 14133d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14143d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King return SUCCESS; 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_handle_crq: - Handles and frees received events in the CRQ 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @crq: Command/Response queue 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data of host 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ibmvscsi_handle_crq(struct viosrp_crq *crq, 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmvscsi_host_data *hostdata) 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14266c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King long rc; 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt_struct = 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (struct srp_event_struct *)crq->IU_data_ptr; 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (crq->valid) { 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xC0: /* initialization */ 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (crq->format) { 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x01: /* Initialization message */ 14346c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_info(hostdata->dev, "partner initialized\n"); 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send back a response */ 1436d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse if ((rc = ibmvscsi_ops->send_crq(hostdata, 1437d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse 0xC002000000000000LL, 0)) == 0) { 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now login */ 14393507e13fcba6b97501891a410ec8ef9f1f188620Brian King init_adapter(hostdata); 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 14416c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc); 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x02: /* Initialization response */ 14466c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_info(hostdata->dev, "partner initialization complete\n"); 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now login */ 14493507e13fcba6b97501891a410ec8ef9f1f188620Brian King init_adapter(hostdata); 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 14526c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format); 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14552b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher case 0xFF: /* Hypervisor telling us the connection is closed */ 14562b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher scsi_block_requests(hostdata->host); 1457cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher atomic_set(&hostdata->request_limit, 0); 14582b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher if (crq->format == 0x06) { 14592b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher /* We need to re-setup the interpartition connection */ 14606c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_info(hostdata->dev, "Re-enabling adapter!\n"); 1461126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->client_migrated = 1; 14620f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->reenable_crq = 1; 14632b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher purge_requests(hostdata, DID_REQUEUE); 14640f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King wake_up(&hostdata->work_wait_q); 14652b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher } else { 14666c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "Virtual adapter failed rc %d!\n", 14676c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King crq->format); 14680f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King ibmvscsi_reset_host(hostdata); 14692b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher } 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x80: /* real payload */ 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 14746c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "got an invalid message type 0x%02x\n", 14756c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King crq->valid); 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The only kind of payload CRQs we should get are responses to 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * things we send. Make sure this response is to something we 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually sent 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!valid_event_struct(&hostdata->pool, evt_struct)) { 14846c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "returned correlation_token 0x%p is invalid!\n", 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *)crq->IU_data_ptr); 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&evt_struct->free)) { 14906c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "received duplicate correlation_token 0x%p!\n", 14916c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King (void *)crq->IU_data_ptr); 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (crq->format == VIOSRP_SRP_FORMAT) 1496ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori atomic_add(evt_struct->xfer_iu->srp.rsp.req_lim_delta, 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &hostdata->request_limit); 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14993d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King del_timer(&evt_struct->timer); 15003d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 1501ca61668b82a902143997794aae3f681a602e6ebcBrian King if ((crq->status != VIOSRP_OK && crq->status != VIOSRP_OK2) && evt_struct->cmnd) 1502c3a3b55ae80a0d595445064159c69f8e80911e85Brian King evt_struct->cmnd->result = DID_ERROR << 16; 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt_struct->done) 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->done(evt_struct); 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 15066c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "returned done() is NULL; not running it!\n"); 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Lock the host_lock before messing with these structures, since we 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are running in a task context 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(evt_struct->hostdata->host->host_lock, flags); 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&evt_struct->list); 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&evt_struct->hostdata->pool, evt_struct); 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(evt_struct->hostdata->host->host_lock, flags); 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_get_host_config: Send the command to the server to get host 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configuration data. The data is opaque to us. 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *buffer, int length) 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct viosrp_host_config *host_config; 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt_struct; 152706f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King unsigned long flags; 1528e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori dma_addr_t addr; 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct = get_event_struct(&hostdata->pool); 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!evt_struct) { 15336c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "couldn't allocate event for HOST_CONFIG!\n"); 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_event_struct(evt_struct, 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sync_completion, 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VIOSRP_MAD_FORMAT, 1540e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings info_timeout); 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_config = &evt_struct->iu.mad.host_config; 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up a lun reset SRP command */ 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(host_config, 0x00, sizeof(*host_config)); 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_config->common.type = VIOSRP_HOST_CONFIG_TYPE; 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_config->common.length = length; 1548e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori host_config->buffer = addr = dma_map_single(hostdata->dev, buffer, 1549e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori length, 1550e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori DMA_BIDIRECTIONAL); 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15528d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori if (dma_mapping_error(hostdata->dev, host_config->buffer)) { 15537912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings if (!firmware_has_feature(FW_FEATURE_CMO)) 15547912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings dev_err(hostdata->dev, 15557912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings "dma_mapping error getting host config\n"); 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&hostdata->pool, evt_struct); 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_completion(&evt_struct->comp); 156106f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King spin_lock_irqsave(hostdata->host->host_lock, flags); 1562e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings rc = ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2); 156306f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1564e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori if (rc == 0) 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_for_completion(&evt_struct->comp); 1566e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL); 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15710979c84b4affaf924a894380dd0069638b64de03Robert Jennings/** 15720979c84b4affaf924a894380dd0069638b64de03Robert Jennings * ibmvscsi_slave_configure: Set the "allow_restart" flag for each disk. 15730979c84b4affaf924a894380dd0069638b64de03Robert Jennings * @sdev: struct scsi_device device to configure 15740979c84b4affaf924a894380dd0069638b64de03Robert Jennings * 15750979c84b4affaf924a894380dd0069638b64de03Robert Jennings * Enable allow_restart for a device if it is a disk. Adjust the 15760979c84b4affaf924a894380dd0069638b64de03Robert Jennings * queue_depth here also as is required by the documentation for 15770979c84b4affaf924a894380dd0069638b64de03Robert Jennings * struct scsi_host_template. 15780979c84b4affaf924a894380dd0069638b64de03Robert Jennings */ 15790979c84b4affaf924a894380dd0069638b64de03Robert Jenningsstatic int ibmvscsi_slave_configure(struct scsi_device *sdev) 15800979c84b4affaf924a894380dd0069638b64de03Robert Jennings{ 15810979c84b4affaf924a894380dd0069638b64de03Robert Jennings struct Scsi_Host *shost = sdev->host; 15820979c84b4affaf924a894380dd0069638b64de03Robert Jennings unsigned long lock_flags = 0; 15830979c84b4affaf924a894380dd0069638b64de03Robert Jennings 15840979c84b4affaf924a894380dd0069638b64de03Robert Jennings spin_lock_irqsave(shost->host_lock, lock_flags); 1585d1a357fcc8348d325d151f6fe0ea54e317652457Brian King if (sdev->type == TYPE_DISK) { 15860979c84b4affaf924a894380dd0069638b64de03Robert Jennings sdev->allow_restart = 1; 1587e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings blk_queue_rq_timeout(sdev->request_queue, 120 * HZ); 1588d1a357fcc8348d325d151f6fe0ea54e317652457Brian King } 15890979c84b4affaf924a894380dd0069638b64de03Robert Jennings scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun); 15900979c84b4affaf924a894380dd0069638b64de03Robert Jennings spin_unlock_irqrestore(shost->host_lock, lock_flags); 15910979c84b4affaf924a894380dd0069638b64de03Robert Jennings return 0; 15920979c84b4affaf924a894380dd0069638b64de03Robert Jennings} 15930979c84b4affaf924a894380dd0069638b64de03Robert Jennings 1594742d25b819f11dce91b89e6c9ac17402a119f20aBrian King/** 1595742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * ibmvscsi_change_queue_depth - Change the device's queue depth 1596742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * @sdev: scsi device struct 1597742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * @qdepth: depth to set 1598e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie * @reason: calling context 1599742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * 1600742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * Return value: 1601742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * actual depth set 1602742d25b819f11dce91b89e6c9ac17402a119f20aBrian King **/ 1603e881a172dac4d9ea3b2a1540041d872963c269bdMike Christiestatic int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth, 1604e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie int reason) 1605742d25b819f11dce91b89e6c9ac17402a119f20aBrian King{ 1606e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie if (reason != SCSI_QDEPTH_DEFAULT) 1607e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie return -EOPNOTSUPP; 1608e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie 1609742d25b819f11dce91b89e6c9ac17402a119f20aBrian King if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN) 1610742d25b819f11dce91b89e6c9ac17402a119f20aBrian King qdepth = IBMVSCSI_MAX_CMDS_PER_LUN; 1611742d25b819f11dce91b89e6c9ac17402a119f20aBrian King 1612742d25b819f11dce91b89e6c9ac17402a119f20aBrian King scsi_adjust_queue_depth(sdev, 0, qdepth); 1613742d25b819f11dce91b89e6c9ac17402a119f20aBrian King return sdev->queue_depth; 1614742d25b819f11dce91b89e6c9ac17402a119f20aBrian King} 1615742d25b819f11dce91b89e6c9ac17402a119f20aBrian King 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysfs attributes 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1619126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic ssize_t show_host_vhost_loc(struct device *dev, 1620126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct device_attribute *attr, char *buf) 1621126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 1622126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct Scsi_Host *shost = class_to_shost(dev); 1623126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct ibmvscsi_host_data *hostdata = shost_priv(shost); 1624126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King int len; 1625126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1626126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King len = snprintf(buf, sizeof(hostdata->caps.loc), "%s\n", 1627126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.loc); 1628126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return len; 1629126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 1630126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1631126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic struct device_attribute ibmvscsi_host_vhost_loc = { 1632126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .attr = { 1633126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .name = "vhost_loc", 1634126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .mode = S_IRUGO, 1635126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King }, 1636126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .show = show_host_vhost_loc, 1637126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King}; 1638126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1639126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic ssize_t show_host_vhost_name(struct device *dev, 1640126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct device_attribute *attr, char *buf) 1641126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 1642126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct Scsi_Host *shost = class_to_shost(dev); 1643126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct ibmvscsi_host_data *hostdata = shost_priv(shost); 1644126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King int len; 1645126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1646126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King len = snprintf(buf, sizeof(hostdata->caps.name), "%s\n", 1647126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.name); 1648126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return len; 1649126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 1650126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1651126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic struct device_attribute ibmvscsi_host_vhost_name = { 1652126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .attr = { 1653126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .name = "vhost_name", 1654126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .mode = S_IRUGO, 1655126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King }, 1656126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .show = show_host_vhost_name, 1657126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King}; 1658126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1659ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_srp_version(struct device *dev, 1660ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1662ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 16637603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%s\n", 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.srp_version); 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_srp_version = { 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "srp_version", 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_srp_version, 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1679ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_partition_name(struct device *dev, 1680ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf) 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1683ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 16847603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%s\n", 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.partition_name); 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1692ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_partition_name = { 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "partition_name", 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_partition_name, 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1700ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_partition_number(struct device *dev, 1701ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf) 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1704ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 17057603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%d\n", 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.partition_number); 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1713ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_partition_number = { 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "partition_number", 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_partition_number, 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_mad_version(struct device *dev, 1722ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1724ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 17257603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%d\n", 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.mad_version); 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1733ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_mad_version = { 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "mad_version", 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_mad_version, 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_os_type(struct device *dev, 1742ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1744ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 17457603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%d\n", hostdata->madapter_info.os_type); 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1752ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_os_type = { 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "os_type", 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_os_type, 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1760ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_config(struct device *dev, 1761ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1763ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 17647603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* returns null-terminated host config data */ 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ibmvscsi_do_host_config(hostdata, buf, PAGE_SIZE) == 0) 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return strlen(buf); 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1773ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_config = { 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "config", 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_config, 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute *ibmvscsi_attrs[] = { 1782126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King &ibmvscsi_host_vhost_loc, 1783126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King &ibmvscsi_host_vhost_name, 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_srp_version, 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_partition_name, 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_partition_number, 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_mad_version, 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_os_type, 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_config, 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCSI driver registration 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct scsi_host_template driver_template = { 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .module = THIS_MODULE, 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "IBM POWER Virtual SCSI Adapter " IBMVSCSI_VERSION, 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .proc_name = "ibmvscsi", 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .queuecommand = ibmvscsi_queuecommand, 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_abort_handler = ibmvscsi_eh_abort_handler, 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, 18033d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler, 18040979c84b4affaf924a894380dd0069638b64de03Robert Jennings .slave_configure = ibmvscsi_slave_configure, 1805742d25b819f11dce91b89e6c9ac17402a119f20aBrian King .change_queue_depth = ibmvscsi_change_queue_depth, 18067912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings .cmd_per_lun = IBMVSCSI_CMDS_PER_LUN_DEFAULT, 1807a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .this_id = -1, 18094dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley .sg_tablesize = SG_ALL, 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .use_clustering = ENABLE_CLUSTERING, 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .shost_attrs = ibmvscsi_attrs, 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 18157912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * ibmvscsi_get_desired_dma - Calculate IO memory desired by the driver 18167912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * 18177912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * @vdev: struct vio_dev for the device whose desired IO mem is to be returned 18187912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * 18197912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * Return value: 18207912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * Number of bytes of IO data the driver will need to perform well. 18217912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings */ 18227912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jenningsstatic unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev) 18237912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings{ 18247912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings /* iu_storage data allocated in initialize_event_pool */ 18254f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King unsigned long desired_io = max_events * sizeof(union viosrp_iu); 18267912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings 18277912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings /* add io space for sg data */ 1828004dd5e88673516a408f0e8e43edbe6a4424be2fBrian King desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * 512 * 18297912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings IBMVSCSI_CMDS_PER_LUN_DEFAULT); 18307912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings 18317912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings return desired_io; 18327912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings} 18337912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings 18340f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian Kingstatic void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata) 18350f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King{ 18360f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King int rc; 18370f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King char *action = "reset"; 18380f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18390f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (hostdata->reset_crq) { 18400f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King smp_rmb(); 18410f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->reset_crq = 0; 18420f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18430f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata); 18440f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (!rc) 18450f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0); 1846201aed678482f247aa96bd8fcd9e960fefd82d59Brian King vio_enable_interrupts(to_vio_dev(hostdata->dev)); 18470f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } else if (hostdata->reenable_crq) { 18480f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King smp_rmb(); 18490f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King action = "enable"; 18500f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = ibmvscsi_ops->reenable_crq_queue(&hostdata->queue, hostdata); 18510f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->reenable_crq = 0; 18520f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (!rc) 18530f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0); 18540f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } else 18550f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return; 18560f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18570f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (rc) { 18580f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King atomic_set(&hostdata->request_limit, -1); 18590f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King dev_err(hostdata->dev, "error after %s\n", action); 18600f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } 18610f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18620f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King scsi_unblock_requests(hostdata->host); 18630f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King} 18640f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18650f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian Kingstatic int ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata) 18660f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King{ 18670f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (kthread_should_stop()) 18680f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 1; 18690f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King else if (hostdata->reset_crq) { 18700f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King smp_rmb(); 18710f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 1; 18720f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } else if (hostdata->reenable_crq) { 18730f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King smp_rmb(); 18740f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 1; 18750f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } 18760f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18770f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 0; 18780f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King} 18790f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18800f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian Kingstatic int ibmvscsi_work(void *data) 18810f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King{ 18820f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King struct ibmvscsi_host_data *hostdata = data; 18830f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King int rc; 18840f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18850f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King set_user_nice(current, -20); 18860f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18870f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King while (1) { 18880f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = wait_event_interruptible(hostdata->work_wait_q, 18890f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King ibmvscsi_work_to_do(hostdata)); 18900f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18910f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King BUG_ON(rc); 18920f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18930f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (kthread_should_stop()) 18940f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King break; 18950f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18960f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King ibmvscsi_do_work(hostdata); 18970f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } 18980f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18990f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 0; 19000f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King} 19010f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 19027912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings/** 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by bus code for each adapter 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmvscsi_host_data *hostdata; 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *host; 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev = &vdev->dev; 19104d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori struct srp_rport_identifiers ids; 19114d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori struct srp_rport *rport; 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long wait_switch = 0; 1913cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher int rc; 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1915559fde706873256903155b3a62b05d0f52d62ab9Greg Kroah-Hartman dev_set_drvdata(&vdev->dev, NULL); 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host = scsi_host_alloc(&driver_template, sizeof(*hostdata)); 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!host) { 19196c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(&vdev->dev, "couldn't allocate host data\n"); 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto scsi_host_alloc_failed; 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19234d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori host->transportt = ibmvscsi_transport_template; 19247603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori hostdata = shost_priv(host); 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(hostdata, 0x00, sizeof(*hostdata)); 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&hostdata->sent); 19270f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King init_waitqueue_head(&hostdata->work_wait_q); 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->host = host; 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->dev = dev; 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&hostdata->request_limit, -1); 19317912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT; 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1933126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (map_persist_bufs(hostdata)) { 1934126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(&vdev->dev, "couldn't map persistent buffers\n"); 1935126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King goto persist_bufs_failed; 1936126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 1937126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 19380f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->work_thread = kthread_run(ibmvscsi_work, hostdata, "%s_%d", 19390f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King "ibmvscsi", host->host_no); 19400f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 19410f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (IS_ERR(hostdata->work_thread)) { 19420f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King dev_err(&vdev->dev, "couldn't initialize kthread. rc=%ld\n", 19430f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King PTR_ERR(hostdata->work_thread)); 19440f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King goto init_crq_failed; 19450f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } 19460f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 19474f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_events); 1948cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher if (rc != 0 && rc != H_RESOURCE) { 19496c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc); 19500f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King goto kill_kthread; 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19524f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King if (initialize_event_pool(&hostdata->pool, max_events, hostdata) != 0) { 19536c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(&vdev->dev, "couldn't initialize event pool\n"); 19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto init_pool_failed; 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->max_lun = 8; 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->max_id = max_id; 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->max_channel = max_channel; 1960fbc56f0801f58041a4372a030933bac076b46aadBrian King host->max_cmd_len = 16; 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (scsi_add_host(hostdata->host, hostdata->dev)) 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto add_host_failed; 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19654d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori /* we don't have a proper target_port_id so let's use the fake one */ 19664d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori memcpy(ids.port_id, hostdata->madapter_info.partition_name, 19674d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori sizeof(ids.port_id)); 1968aebd5e476ecc8ceb53577b20f2a352ff4ceffd8dFUJITA Tomonori ids.roles = SRP_RPORT_ROLE_TARGET; 19694d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori rport = srp_rport_add(host, &ids); 19704d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori if (IS_ERR(rport)) 19714d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori goto add_srp_port_failed; 19724d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try to send an initialization message. Note that this is allowed 19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to fail if the other end is not acive. In that case we don't 19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * want to scan 19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1977d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0 1978cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher || rc == H_RESOURCE) { 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait around max init_timeout secs for the adapter to finish 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initializing. When we are done initializing, we will have a 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * valid request_limit. We don't want Linux scanning before 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we are ready. 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (wait_switch = jiffies + (init_timeout * HZ); 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds time_before(jiffies, wait_switch) && 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&hostdata->request_limit) < 2;) { 19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if we now have a valid request_limit, initiate a scan */ 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&hostdata->request_limit) > 0) 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_scan_host(host); 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1997559fde706873256903155b3a62b05d0f52d62ab9Greg Kroah-Hartman dev_set_drvdata(&vdev->dev, hostdata); 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20004d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori add_srp_port_failed: 20014d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori scsi_remove_host(hostdata->host); 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_host_failed: 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_event_pool(&hostdata->pool, hostdata); 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_pool_failed: 20054f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_events); 20060f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King kill_kthread: 20070f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King kthread_stop(hostdata->work_thread); 20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_crq_failed: 2009126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King unmap_persist_bufs(hostdata); 2010126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King persist_bufs_failed: 20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_host_put(host); 20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_host_alloc_failed: 20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_remove(struct vio_dev *vdev) 20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2018559fde706873256903155b3a62b05d0f52d62ab9Greg Kroah-Hartman struct ibmvscsi_host_data *hostdata = dev_get_drvdata(&vdev->dev); 2019126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King unmap_persist_bufs(hostdata); 20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_event_pool(&hostdata->pool, hostdata); 2021d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, 20224f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King max_events); 20234d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 20240f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King kthread_stop(hostdata->work_thread); 20254d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori srp_remove_host(hostdata->host); 20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_remove_host(hostdata->host); 20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_host_put(hostdata->host); 20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 203364355b929dec0cb6271e4ac7834c9cf262961e40Brian King * ibmvscsi_resume: Resume from suspend 203464355b929dec0cb6271e4ac7834c9cf262961e40Brian King * @dev: device struct 203564355b929dec0cb6271e4ac7834c9cf262961e40Brian King * 203664355b929dec0cb6271e4ac7834c9cf262961e40Brian King * We may have lost an interrupt across suspend/resume, so kick the 203764355b929dec0cb6271e4ac7834c9cf262961e40Brian King * interrupt handler 203864355b929dec0cb6271e4ac7834c9cf262961e40Brian King */ 203964355b929dec0cb6271e4ac7834c9cf262961e40Brian Kingstatic int ibmvscsi_resume(struct device *dev) 204064355b929dec0cb6271e4ac7834c9cf262961e40Brian King{ 204164355b929dec0cb6271e4ac7834c9cf262961e40Brian King struct ibmvscsi_host_data *hostdata = dev_get_drvdata(dev); 204264355b929dec0cb6271e4ac7834c9cf262961e40Brian King return ibmvscsi_ops->resume(hostdata); 204364355b929dec0cb6271e4ac7834c9cf262961e40Brian King} 204464355b929dec0cb6271e4ac7834c9cf262961e40Brian King 204564355b929dec0cb6271e4ac7834c9cf262961e40Brian King/** 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * support. 20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct vio_device_id ibmvscsi_device_table[] __devinitdata = { 20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"vscsi", "IBM,v-scsi"}, 2051fb120da678c517f72d4b39932062c2191827b331Stephen Rothwell { "", "" } 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(vio, ibmvscsi_device_table); 2054915124d8114ec8c3825b10a39151bf9e851593bbStephen Rothwell 205564355b929dec0cb6271e4ac7834c9cf262961e40Brian Kingstatic struct dev_pm_ops ibmvscsi_pm_ops = { 205664355b929dec0cb6271e4ac7834c9cf262961e40Brian King .resume = ibmvscsi_resume 205764355b929dec0cb6271e4ac7834c9cf262961e40Brian King}; 205864355b929dec0cb6271e4ac7834c9cf262961e40Brian King 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct vio_driver ibmvscsi_driver = { 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = ibmvscsi_device_table, 20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = ibmvscsi_probe, 20626fdf5392caa4c3cba65add0a4beec9f5eb96b723Stephen Rothwell .remove = ibmvscsi_remove, 20637912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings .get_desired_dma = ibmvscsi_get_desired_dma, 2064cb52d8970eee65bf2c47d9a91bd4f58b17f595f4Benjamin Herrenschmidt .name = "ibmvscsi", 2065cb52d8970eee65bf2c47d9a91bd4f58b17f595f4Benjamin Herrenschmidt .pm = &ibmvscsi_pm_ops, 20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20684d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonoristatic struct srp_function_template ibmvscsi_transport_functions = { 20694d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori}; 20704d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init ibmvscsi_module_init(void) 20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20734d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori int ret; 20744d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 20754f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King /* Ensure we have two requests to do error recovery */ 20764f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King driver_template.can_queue = max_requests; 20774f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King max_events = max_requests + 2; 20784f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King 20797834799a6c8fed36d06d6b78bfd17831ecfa93c4Stephen Rothwell if (firmware_has_feature(FW_FEATURE_VIO)) 2080d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse ibmvscsi_ops = &rpavscsi_ops; 2081d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse else 2082d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse return -ENODEV; 2083d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse 20844d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori ibmvscsi_transport_template = 20854d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori srp_attach_transport(&ibmvscsi_transport_functions); 20864d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori if (!ibmvscsi_transport_template) 20874d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori return -ENOMEM; 20884d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 20894d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori ret = vio_register_driver(&ibmvscsi_driver); 20904d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori if (ret) 20914d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori srp_release_transport(ibmvscsi_transport_template); 20924d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori return ret; 20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __exit ibmvscsi_module_exit(void) 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vio_unregister_driver(&ibmvscsi_driver); 20984d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori srp_release_transport(ibmvscsi_transport_template); 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(ibmvscsi_module_init); 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(ibmvscsi_module_exit); 2103