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 * 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that some of the underlying infrastructure is different between 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * machines conforming to the "RS/6000 Platform Architecture" (RPA) and 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the older iSeries hypervisor models. To support both, some low level 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routines have been broken out into rpa_vscsi.c and iseries_vscsi.c. 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The Makefile should pick one, not two, not zero, of these. 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TODO: This is currently pretty tied to the IBM i/pSeries hypervisor 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interfaces. It would be really nice to abstract this above an RDMA 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * layer. 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/dma-mapping.h> 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 735a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 74126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King#include <linux/of.h> 7564355b929dec0cb6271e4ac7834c9cf262961e40Brian King#include <linux/pm.h> 760f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King#include <linux/kthread.h> 77d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse#include <asm/firmware.h> 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/vio.h> 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi.h> 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_cmnd.h> 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h> 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_device.h> 834d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori#include <scsi/scsi_transport_srp.h> 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ibmvscsi.h" 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The values below are somewhat arbitrary default values, but 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OS/400 will use 3 busses (disks, CDs, tapes, I think.) 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that there are 3 bits of channel value, 6 bits of id, and 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5 bits of LUN. 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int max_id = 64; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int max_channel = 3; 93e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int init_timeout = 300; 94e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int login_timeout = 60; 95e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int info_timeout = 30; 96e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int abort_timeout = 60; 97e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jenningsstatic int reset_timeout = 60; 98a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jenningsstatic int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; 994f10aae0d1a285df6b16bf6ca5abd366140fd371Brian Kingstatic int max_events = IBMVSCSI_MAX_REQUESTS_DEFAULT + 2; 100c1988e3123751fd425fbae99d5c1776608e965a9Robert Jenningsstatic int fast_fail = 1; 101126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic int client_reserve = 1; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1034d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonoristatic struct scsi_transport_template *ibmvscsi_transport_template; 1044d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 105aac3118d33e275a7b1134cb19227c982f4d43877Brian King#define IBMVSCSI_VERSION "1.5.9" 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 107d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhousestatic struct ibmvscsi_ops *ibmvscsi_ops; 108d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("IBM Virtual SCSI"); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Dave Boutcher"); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(IBMVSCSI_VERSION); 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_id, "Largest ID value for each channel"); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_channel, "Largest channel value"); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds"); 12021465eda9eafa275ed11c27779d90aa95559b6f6Brian Kingmodule_param_named(max_requests, max_requests, int, S_IRUGO); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_requests, "Maximum requests for this adapter"); 122c1988e3123751fd425fbae99d5c1776608e965a9Robert Jenningsmodule_param_named(fast_fail, fast_fail, int, S_IRUGO | S_IWUSR); 123c1988e3123751fd425fbae99d5c1776608e965a9Robert JenningsMODULE_PARM_DESC(fast_fail, "Enable fast fail. [Default=1]"); 124126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingmodule_param_named(client_reserve, client_reserve, int, S_IRUGO ); 125126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian KingMODULE_PARM_DESC(client_reserve, "Attempt client managed reserve/release"); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for the event pool and event structs 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initialize_event_pool: - Allocates and initializes the event pool for a host 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool to be initialized 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @size: Number of events in pool 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data who owns the event pool 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns zero on success. 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int initialize_event_pool(struct event_pool *pool, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size, struct ibmvscsi_host_data *hostdata) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->size = size; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->next = 0; 1454c021dd136c0ad524e6d117296beafad2bf570c0FUJITA Tomonori pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL); 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pool->events) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->iu_storage = 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_alloc_coherent(hostdata->dev, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->size * sizeof(*pool->iu_storage), 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &pool->iu_token, 0); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pool->iu_storage) { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(pool->events); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < pool->size; ++i) { 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt = &pool->events[i]; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&evt->crq, 0x00, sizeof(evt->crq)); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&evt->free, 1); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->crq.valid = 0x80; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->crq.IU_length = sizeof(*evt->xfer_iu); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->crq.IU_data_ptr = pool->iu_token + 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(*evt->xfer_iu) * i; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->xfer_iu = pool->iu_storage + i; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt->hostdata = hostdata; 1684dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt->ext_list = NULL; 1694dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt->ext_list_token = 0; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * release_event_pool: - Frees memory of an event pool of a host 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool to be released 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data who owns the even pool 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns zero on success. 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void release_event_pool(struct event_pool *pool, 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmvscsi_host_data *hostdata) 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, in_use = 0; 1864dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley for (i = 0; i < pool->size; ++i) { 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&pool->events[i].free) != 1) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++in_use; 1894dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (pool->events[i].ext_list) { 1904dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley dma_free_coherent(hostdata->dev, 191ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori SG_ALL * sizeof(struct srp_direct_buf), 1924dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley pool->events[i].ext_list, 1934dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley pool->events[i].ext_list_token); 1944dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 1954dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (in_use) 1976c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_warn(hostdata->dev, "releasing event pool with %d " 1986c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "events still in use?\n", in_use); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(pool->events); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_free_coherent(hostdata->dev, 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->size * sizeof(*pool->iu_storage), 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->iu_storage, pool->iu_token); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * valid_event_struct: - Determines if event is valid. 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool that contains the event 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt: srp_event_struct to be checked for validity 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns zero if event is invalid, one otherwise. 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int valid_event_struct(struct event_pool *pool, 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt) 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int index = evt - pool->events; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (index < 0 || index >= pool->size) /* outside of bounds */ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt != pool->events + index) /* unaligned */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_free-event_struct: - Changes status of event to "free" 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool that contains the event 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt: srp_event_struct to be modified 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void free_event_struct(struct event_pool *pool, 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt) 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!valid_event_struct(pool, evt)) { 2336c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(evt->hostdata->dev, "Freeing invalid event_struct %p " 2346c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "(not in pool %p)\n", evt, pool->events); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_inc_return(&evt->free) != 1) { 2386c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(evt->hostdata->dev, "Freeing event_struct %p " 2396c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "which is not in use!\n", evt); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_evt_struct: - Gets the next free event in pool 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @pool: event_pool that contains the events to be searched 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the next event in "free" state, and NULL if none are free. 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that no synchronization is done here, we assume the host_lock 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will syncrhonze things. 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct srp_event_struct *get_event_struct(struct event_pool *pool) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int poolsize = pool->size; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int offset = pool->next; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < poolsize; i++) { 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = (offset + 1) % poolsize; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_dec_if_positive(&pool->events[offset].free)) { 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pool->next = offset; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &pool->events[offset]; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "ibmvscsi: found no event struct in pool!\n"); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * init_event_struct: Initialize fields in an event struct that are always 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * required. 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt: The event 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @done: Routine to call when the event is responded to 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @format: SRP or MAD format 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @timeout: timeout value set in the CRQ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void init_event_struct(struct srp_event_struct *evt_struct, 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void (*done) (struct srp_event_struct *), 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 format, 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int timeout) 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->cmnd = NULL; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->cmnd_done = NULL; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->sync_srp = NULL; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->crq.format = format; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->crq.timeout = timeout; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->done = done; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for receiving SCSI responses from the hosting partition 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set_srp_direction: Set the fields in the srp related to data 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * direction and number of buffers based on the direction in 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the scsi_cmnd and the number of buffers 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_srp_direction(struct scsi_cmnd *cmd, 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_cmd *srp_cmd, 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int numbuf) 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 304ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori u8 fmt; 305ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (numbuf == 0) 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 309ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (numbuf == 1) 310ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori fmt = SRP_DATA_DESC_DIRECT; 311ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori else { 312ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori fmt = SRP_DATA_DESC_INDIRECT; 313ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori numbuf = min(numbuf, MAX_INDIRECT_BUFS); 314ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd->sc_data_direction == DMA_TO_DEVICE) 316ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->data_out_desc_cnt = numbuf; 317ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori else 318ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->data_in_desc_cnt = numbuf; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 320ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 321ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (cmd->sc_data_direction == DMA_TO_DEVICE) 322ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->buf_fmt = fmt << 4; 323ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori else 324ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->buf_fmt = fmt; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: srp_cmd whose additional_data member will be unmapped 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device for which the memory is mapped 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 3334dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomleystatic void unmap_cmd_data(struct srp_cmd *cmd, 3344dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley struct srp_event_struct *evt_struct, 3354dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley struct device *dev) 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 337ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori u8 out_fmt, in_fmt; 338ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 339ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori out_fmt = cmd->buf_fmt >> 4; 340ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori in_fmt = cmd->buf_fmt & ((1U << 4) - 1); 341ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori 342ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (out_fmt == SRP_NO_DATA_DESC && in_fmt == SRP_NO_DATA_DESC) 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3444dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 345a71fa1fc43a29133f13ae6ada1a389ca298c0934FUJITA Tomonori if (evt_struct->cmnd) 346a71fa1fc43a29133f13ae6ada1a389ca298c0934FUJITA Tomonori scsi_dma_unmap(evt_struct->cmnd); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3499413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonoristatic int map_sg_list(struct scsi_cmnd *cmd, int nseg, 350ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_direct_buf *md) 3514dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley{ 3524dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley int i; 3539413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori struct scatterlist *sg; 3544dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley u64 total_length = 0; 3554dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 3569413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori scsi_for_each_sg(cmd, sg, nseg, i) { 357ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_direct_buf *descr = md + i; 3589413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori descr->va = sg_dma_address(sg); 3599413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori descr->len = sg_dma_len(sg); 360ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori descr->key = 0; 3619413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori total_length += sg_dma_len(sg); 3624dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 3634dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley return total_length; 3644dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley} 3654dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: Scsi_Cmnd with the scatterlist 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @srp_cmd: srp_cmd that contains the memory descriptor 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device for which to map dma memory 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd. 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns 1 on success. 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int map_sg_data(struct scsi_cmnd *cmd, 3764dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley struct srp_event_struct *evt_struct, 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_cmd *srp_cmd, struct device *dev) 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3804dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley int sg_mapped; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 total_length = 0; 382ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_direct_buf *data = 383ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori (struct srp_direct_buf *) srp_cmd->add_data; 384ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_indirect_buf *indirect = 385ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori (struct srp_indirect_buf *) data; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3879413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori sg_mapped = scsi_dma_map(cmd); 3889413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori if (!sg_mapped) 3899413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori return 1; 3909413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori else if (sg_mapped < 0) 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_srp_direction(cmd, srp_cmd, sg_mapped); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* special case; we can use a single direct descriptor */ 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sg_mapped == 1) { 3979413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori map_sg_list(cmd, sg_mapped, data); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.va = 0; 402ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.len = sg_mapped * sizeof(struct srp_direct_buf); 403ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.key = 0; 4044dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 4054dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (sg_mapped <= MAX_INDIRECT_BUFS) { 4069413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori total_length = map_sg_list(cmd, sg_mapped, 407ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori &indirect->desc_list[0]); 408ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->len = total_length; 4094dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley return 1; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4124dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley /* get indirect table */ 4134dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (!evt_struct->ext_list) { 414ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori evt_struct->ext_list = (struct srp_direct_buf *) 4159413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori dma_alloc_coherent(dev, 416ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori SG_ALL * sizeof(struct srp_direct_buf), 417ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori &evt_struct->ext_list_token, 0); 4184dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (!evt_struct->ext_list) { 4197912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings if (!firmware_has_feature(FW_FEATURE_CMO)) 4207912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings sdev_printk(KERN_ERR, cmd->device, 4217912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings "Can't allocate memory " 4227912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings "for indirect table\n"); 423e637d553199e264327714da437e6c808f2f4b096Robert Jennings scsi_dma_unmap(cmd); 4244dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley return 0; 4254dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 4264dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley } 4274dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 4289413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori total_length = map_sg_list(cmd, sg_mapped, evt_struct->ext_list); 4294dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 430ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->len = total_length; 431ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.va = evt_struct->ext_list_token; 432ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.len = sg_mapped * sizeof(indirect->desc_list[0]); 433ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori memcpy(indirect->desc_list, evt_struct->ext_list, 434ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori MAX_INDIRECT_BUFS * sizeof(struct srp_direct_buf)); 4354dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley return 1; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * map_data_for_srp_cmd: - Calls functions to map data for srp cmds 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: struct scsi_cmnd with the memory to be mapped 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @srp_cmd: srp_cmd that contains the memory descriptor 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: dma device for which to map dma memory 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by scsi_cmd_to_srp_cmd() when converting scsi cmds to srp cmds 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns 1 on success. 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int map_data_for_srp_cmd(struct scsi_cmnd *cmd, 4484dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley struct srp_event_struct *evt_struct, 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_cmd *srp_cmd, struct device *dev) 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd->sc_data_direction) { 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_FROM_DEVICE: 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_TO_DEVICE: 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_NONE: 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DMA_BIDIRECTIONAL: 4586c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_ERR, cmd->device, 4596c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "Can't map DMA_BIDIRECTIONAL to read/write\n"); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4626c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_ERR, cmd->device, 4636c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "Unknown data direction 0x%02x; can't map!\n", 4646c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King cmd->sc_data_direction); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4689413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori return map_sg_data(cmd, evt_struct, srp_cmd, dev); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4713d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King/** 4723d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * purge_requests: Our virtual adapter just shut down. purge any sent requests 4733d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @hostdata: the adapter 4743d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King */ 4753d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian Kingstatic void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) 4763d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King{ 4771117ef8aed95521f46dae3052c7120baae48c2bbBrian King struct srp_event_struct *evt; 4783d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King unsigned long flags; 4793d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 4803d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King spin_lock_irqsave(hostdata->host->host_lock, flags); 4811117ef8aed95521f46dae3052c7120baae48c2bbBrian King while (!list_empty(&hostdata->sent)) { 4821117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt = list_first_entry(&hostdata->sent, struct srp_event_struct, list); 4831117ef8aed95521f46dae3052c7120baae48c2bbBrian King list_del(&evt->list); 4841117ef8aed95521f46dae3052c7120baae48c2bbBrian King del_timer(&evt->timer); 4851117ef8aed95521f46dae3052c7120baae48c2bbBrian King 4861117ef8aed95521f46dae3052c7120baae48c2bbBrian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 4871117ef8aed95521f46dae3052c7120baae48c2bbBrian King if (evt->cmnd) { 4881117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt->cmnd->result = (error_code << 16); 4891117ef8aed95521f46dae3052c7120baae48c2bbBrian King unmap_cmd_data(&evt->iu.srp.cmd, evt, 4901117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt->hostdata->dev); 4911117ef8aed95521f46dae3052c7120baae48c2bbBrian King if (evt->cmnd_done) 4921117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt->cmnd_done(evt->cmnd); 4931117ef8aed95521f46dae3052c7120baae48c2bbBrian King } else if (evt->done) 4941117ef8aed95521f46dae3052c7120baae48c2bbBrian King evt->done(evt); 4951117ef8aed95521f46dae3052c7120baae48c2bbBrian King free_event_struct(&evt->hostdata->pool, evt); 4961117ef8aed95521f46dae3052c7120baae48c2bbBrian King spin_lock_irqsave(hostdata->host->host_lock, flags); 4973d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King } 4983d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 4993d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King} 5003d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5013d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King/** 5023d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * ibmvscsi_reset_host - Reset the connection to the server 5033d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @hostdata: struct ibmvscsi_host_data to reset 5043d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King*/ 5053d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian Kingstatic void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata) 5063d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King{ 5073d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King scsi_block_requests(hostdata->host); 5083d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King atomic_set(&hostdata->request_limit, 0); 5093d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5103d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King purge_requests(hostdata, DID_ERROR); 5110f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->reset_crq = 1; 5120f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King wake_up(&hostdata->work_wait_q); 5133d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King} 5143d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5153d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King/** 5163d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * ibmvscsi_timeout - Internal command timeout handler 5173d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @evt_struct: struct srp_event_struct that timed out 5183d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * 5193d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * Called when an internally generated command times out 5203d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King*/ 5213d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian Kingstatic void ibmvscsi_timeout(struct srp_event_struct *evt_struct) 5223d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King{ 5233d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 5243d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5253d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King dev_err(hostdata->dev, "Command timed out (%x). Resetting connection\n", 5263d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King evt_struct->iu.srp.cmd.opcode); 5273d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5283d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King ibmvscsi_reset_host(hostdata); 5293d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King} 5303d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5313d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for sending and receiving SRPs 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_send_srp_event: - Transforms event to u64 array and calls send_crq() 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt_struct: evt_struct to be sent 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data of host 5393d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @timeout: timeout in seconds - 0 means do not time command 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the value returned from ibmvscsi_send_crq(). (Zero for success) 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that this routine assumes that host_lock is held for synchronization 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, 5453d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King struct ibmvscsi_host_data *hostdata, 5463d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King unsigned long timeout) 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 *crq_as_u64 = (u64 *) &evt_struct->crq; 5493c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings int request_status = 0; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 551f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King int srp_req = 0; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 553a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings /* If we have exhausted our request limit, just fail this request, 554a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * unless it is for a reset or abort. 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that there are rare cases involving driver generated requests 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (such as task management requests) that the mid layer may think we 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can handle more requests (can_queue) when we actually can't 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 559cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher if (evt_struct->crq.format == VIOSRP_SRP_FORMAT) { 560f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King srp_req = 1; 561cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher request_status = 562cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher atomic_dec_if_positive(&hostdata->request_limit); 563cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher /* If request limit was -1 when we started, it is now even 564cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher * less than that 565cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher */ 566cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher if (request_status < -1) 567cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher goto send_error; 568a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings /* Otherwise, we may have run out of requests. */ 5693c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings /* If request limit was 0 when we started the adapter is in the 5703c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings * process of performing a login with the server adapter, or 5713c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings * we may have run out of requests. 5723c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings */ 5733c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings else if (request_status == -1 && 5743c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings evt_struct->iu.srp.login_req.opcode != SRP_LOGIN_REQ) 5753c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings goto send_busy; 576a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings /* Abort and reset calls should make it through. 577a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * Nothing except abort and reset should use the last two 578a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * slots unless we had two or less to begin with. 579a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings */ 580a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings else if (request_status < 2 && 581a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings evt_struct->iu.srp.cmd.opcode != SRP_TSK_MGMT) { 582a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings /* In the case that we have less than two requests 583a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * available, check the server limit as a combination 584a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * of the request limit and the number of requests 585a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * in-flight (the size of the send list). If the 586a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * server limit is greater than 2, return busy so 587a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings * that the last two are reserved for reset and abort. 588a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings */ 589a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings int server_limit = request_status; 590a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings struct srp_event_struct *tmp_evt; 591a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings 592a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings list_for_each_entry(tmp_evt, &hostdata->sent, list) { 593a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings server_limit++; 594a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings } 595a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings 596a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings if (server_limit > 2) 597a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings goto send_busy; 598a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings } 599cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher } 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Copy the IU into the transfer area */ 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *evt_struct->xfer_iu = evt_struct->iu; 603ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori evt_struct->xfer_iu->srp.rsp.tag = (u64)evt_struct; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Add this to the sent list. We need to do this 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before we actually send 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in case it comes back REALLY fast 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&evt_struct->list, &hostdata->sent); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6113d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King init_timer(&evt_struct->timer); 6123d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King if (timeout) { 6133d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King evt_struct->timer.data = (unsigned long) evt_struct; 6143d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King evt_struct->timer.expires = jiffies + (timeout * HZ); 6153d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King evt_struct->timer.function = (void (*)(unsigned long))ibmvscsi_timeout; 6163d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King add_timer(&evt_struct->timer); 6173d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King } 6183d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((rc = 620d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&evt_struct->list); 6223d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King del_timer(&evt_struct->timer); 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 624860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings /* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY. 625860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings * Firmware will send a CRQ with a transport event (0xFF) to 626860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings * tell this client what has happened to the transport. This 627860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings * will be handled in ibmvscsi_handle_crq() 628860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings */ 629860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (rc == H_CLOSED) { 630860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings dev_warn(hostdata->dev, "send warning. " 631860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings "Receive queue closed, will retry.\n"); 632860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings goto send_busy; 633860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 6346c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "send error %d\n", rc); 635f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King if (srp_req) 636f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King atomic_inc(&hostdata->request_limit); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto send_error; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 642cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher send_busy: 6434dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&hostdata->pool, evt_struct); 646f3a9c4d76a955e331e88992cd3b1e1498c231d52Brian King if (srp_req && request_status != -1) 6473c887e8a1a4553ae6263fc9490e33de213e3746fRobert Jennings atomic_inc(&hostdata->request_limit); 648a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings return SCSI_MLQUEUE_HOST_BUSY; 649cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher 650cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher send_error: 651cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); 652cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher 653cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher if (evt_struct->cmnd != NULL) { 654cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher evt_struct->cmnd->result = DID_ERROR << 16; 655cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher evt_struct->cmnd_done(evt_struct->cmnd); 656cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher } else if (evt_struct->done) 657cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher evt_struct->done(evt_struct); 658cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher 659cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher free_event_struct(&hostdata->pool, evt_struct); 660cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher return 0; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handle_cmd_rsp: - Handle responses from commands 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt_struct: srp_event_struct to be handled 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used as a callback by when sending scsi cmds. 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Gets called by ibmvscsi_handle_crq() 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void handle_cmd_rsp(struct srp_event_struct *evt_struct) 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_cmnd *cmnd = evt_struct->cmnd; 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 675ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (unlikely(rsp->opcode != SRP_RSP)) { 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 6776c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_warn(evt_struct->hostdata->dev, 6786c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "bad SRP RSP type %d\n", rsp->opcode); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmnd) { 682c3a3b55ae80a0d595445064159c69f8e80911e85Brian King cmnd->result |= rsp->status; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION) 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(cmnd->sense_buffer, 685ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori rsp->data, 686ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori rsp->sense_data_len); 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unmap_cmd_data(&evt_struct->iu.srp.cmd, 6884dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt_struct, 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->hostdata->dev); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (rsp->flags & SRP_RSP_FLAG_DOOVER) 6929413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori scsi_set_resid(cmnd, rsp->data_out_res_cnt); 693ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori else if (rsp->flags & SRP_RSP_FLAG_DIOVER) 6949413d7b8aa777dd1fc7db9563ce5e80d769fe7b5FUJITA Tomonori scsi_set_resid(cmnd, rsp->data_in_res_cnt); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt_struct->cmnd_done) 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->cmnd_done(cmnd); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lun_from_dev: - Returns the lun of the scsi device 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: struct scsi_device 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u16 lun_from_dev(struct scsi_device *dev) 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0x2 << 14) | (dev->id << 8) | (dev->channel << 5) | dev->lun; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_queue: - The queuecommand function of the scsi template 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: struct scsi_cmnd to be executed 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @done: Callback function to be called when cmd is completed 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 716f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzikstatic int ibmvscsi_queuecommand_lck(struct scsi_cmnd *cmnd, 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void (*done) (struct scsi_cmnd *)) 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_cmd *srp_cmd; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt_struct; 721ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori struct srp_indirect_buf *indirect; 7227603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(cmnd->device->host); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 lun = lun_from_dev(cmnd->device); 724ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori u8 out_fmt, in_fmt; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 726c3a3b55ae80a0d595445064159c69f8e80911e85Brian King cmnd->result = (DID_OK << 16); 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct = get_event_struct(&hostdata->pool); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!evt_struct) 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up the actual SRP IU */ 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds srp_cmd = &evt_struct->iu.srp.cmd; 733ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori memset(srp_cmd, 0x00, SRP_MAX_IU_LEN); 734ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori srp_cmd->opcode = SRP_CMD; 73564a87b244b9297667ca80264aab849a36f494884Boaz Harrosh memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb)); 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds srp_cmd->lun = ((u64) lun) << 48; 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7384dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { 7397912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings if (!firmware_has_feature(FW_FEATURE_CMO)) 7407912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings sdev_printk(KERN_ERR, cmnd->device, 7417912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings "couldn't convert cmd to srp_cmd\n"); 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&hostdata->pool, evt_struct); 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7464dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley init_event_struct(evt_struct, 7474dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley handle_cmd_rsp, 7484dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley VIOSRP_SRP_FORMAT, 749242f9dcb8ba6f68fcd217a119a7648a4f69290e9Jens Axboe cmnd->request->timeout/HZ); 7504dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 7514dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt_struct->cmnd = cmnd; 7524dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley evt_struct->cmnd_done = done; 7534dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fix up dma address of the buffer itself */ 755ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect = (struct srp_indirect_buf *) srp_cmd->add_data; 756ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori out_fmt = srp_cmd->buf_fmt >> 4; 757ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori in_fmt = srp_cmd->buf_fmt & ((1U << 4) - 1); 758ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if ((in_fmt == SRP_DATA_DESC_INDIRECT || 759ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori out_fmt == SRP_DATA_DESC_INDIRECT) && 760ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.va == 0) { 761ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori indirect->table_desc.va = evt_struct->crq.IU_data_ptr + 762ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori offsetof(struct srp_cmd, add_data) + 763ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori offsetof(struct srp_indirect_buf, desc_list); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7663d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King return ibmvscsi_send_srp_event(evt_struct, hostdata, 0); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 769f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzikstatic DEF_SCSI_QCMD(ibmvscsi_queuecommand) 770f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzik 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for driver initialization 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7743507e13fcba6b97501891a410ec8ef9f1f188620Brian King 7753507e13fcba6b97501891a410ec8ef9f1f188620Brian King/** 776126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * map_persist_bufs: - Pre-map persistent data for adapter logins 777126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * @hostdata: ibmvscsi_host_data of host 778126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * 779126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * Map the capabilities and adapter info DMA buffers to avoid runtime failures. 780126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * Return 1 on error, 0 on success. 781126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King */ 782126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic int map_persist_bufs(struct ibmvscsi_host_data *hostdata) 783126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 784126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 785126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps_addr = dma_map_single(hostdata->dev, &hostdata->caps, 786126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->caps), DMA_BIDIRECTIONAL); 787126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 788126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (dma_mapping_error(hostdata->dev, hostdata->caps_addr)) { 789126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(hostdata->dev, "Unable to map capabilities buffer!\n"); 790126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return 1; 791126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 792126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 793126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->adapter_info_addr = dma_map_single(hostdata->dev, 794126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King &hostdata->madapter_info, 795126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->madapter_info), 796126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King DMA_BIDIRECTIONAL); 797126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (dma_mapping_error(hostdata->dev, hostdata->adapter_info_addr)) { 798126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(hostdata->dev, "Unable to map adapter info buffer!\n"); 799126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dma_unmap_single(hostdata->dev, hostdata->caps_addr, 800126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->caps), DMA_BIDIRECTIONAL); 801126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return 1; 802126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 803126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 804126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return 0; 805126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 806126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 807126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King/** 808126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * unmap_persist_bufs: - Unmap persistent data needed for adapter logins 809126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * @hostdata: ibmvscsi_host_data of host 810126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * 811126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * Unmap the capabilities and adapter info DMA buffers 812126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King */ 813126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic void unmap_persist_bufs(struct ibmvscsi_host_data *hostdata) 814126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 815126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dma_unmap_single(hostdata->dev, hostdata->caps_addr, 816126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->caps), DMA_BIDIRECTIONAL); 817126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 818126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dma_unmap_single(hostdata->dev, hostdata->adapter_info_addr, 819126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->madapter_info), DMA_BIDIRECTIONAL); 820126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 821126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 822126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King/** 8233507e13fcba6b97501891a410ec8ef9f1f188620Brian King * login_rsp: - Handle response to SRP login request 8243507e13fcba6b97501891a410ec8ef9f1f188620Brian King * @evt_struct: srp_event_struct with the response 8253507e13fcba6b97501891a410ec8ef9f1f188620Brian King * 8263507e13fcba6b97501891a410ec8ef9f1f188620Brian King * Used as a "done" callback by when sending srp_login. Gets called 8273507e13fcba6b97501891a410ec8ef9f1f188620Brian King * by ibmvscsi_handle_crq() 8283507e13fcba6b97501891a410ec8ef9f1f188620Brian King*/ 8293507e13fcba6b97501891a410ec8ef9f1f188620Brian Kingstatic void login_rsp(struct srp_event_struct *evt_struct) 8303507e13fcba6b97501891a410ec8ef9f1f188620Brian King{ 8313507e13fcba6b97501891a410ec8ef9f1f188620Brian King struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 8323507e13fcba6b97501891a410ec8ef9f1f188620Brian King switch (evt_struct->xfer_iu->srp.login_rsp.opcode) { 8333507e13fcba6b97501891a410ec8ef9f1f188620Brian King case SRP_LOGIN_RSP: /* it worked! */ 8343507e13fcba6b97501891a410ec8ef9f1f188620Brian King break; 8353507e13fcba6b97501891a410ec8ef9f1f188620Brian King case SRP_LOGIN_REJ: /* refused! */ 8363507e13fcba6b97501891a410ec8ef9f1f188620Brian King dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n", 8373507e13fcba6b97501891a410ec8ef9f1f188620Brian King evt_struct->xfer_iu->srp.login_rej.reason); 8383507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* Login failed. */ 8393507e13fcba6b97501891a410ec8ef9f1f188620Brian King atomic_set(&hostdata->request_limit, -1); 8403507e13fcba6b97501891a410ec8ef9f1f188620Brian King return; 8413507e13fcba6b97501891a410ec8ef9f1f188620Brian King default: 8423507e13fcba6b97501891a410ec8ef9f1f188620Brian King dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n", 8433507e13fcba6b97501891a410ec8ef9f1f188620Brian King evt_struct->xfer_iu->srp.login_rsp.opcode); 8443507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* Login failed. */ 8453507e13fcba6b97501891a410ec8ef9f1f188620Brian King atomic_set(&hostdata->request_limit, -1); 8463507e13fcba6b97501891a410ec8ef9f1f188620Brian King return; 8473507e13fcba6b97501891a410ec8ef9f1f188620Brian King } 8483507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8493507e13fcba6b97501891a410ec8ef9f1f188620Brian King dev_info(hostdata->dev, "SRP_LOGIN succeeded\n"); 850126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->client_migrated = 0; 8513507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8523507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* Now we know what the real request-limit is. 8533507e13fcba6b97501891a410ec8ef9f1f188620Brian King * This value is set rather than added to request_limit because 8543507e13fcba6b97501891a410ec8ef9f1f188620Brian King * request_limit could have been set to -1 by this client. 8553507e13fcba6b97501891a410ec8ef9f1f188620Brian King */ 8563507e13fcba6b97501891a410ec8ef9f1f188620Brian King atomic_set(&hostdata->request_limit, 8573507e13fcba6b97501891a410ec8ef9f1f188620Brian King evt_struct->xfer_iu->srp.login_rsp.req_lim_delta); 8583507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8593507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* If we had any pending I/Os, kick them */ 8603507e13fcba6b97501891a410ec8ef9f1f188620Brian King scsi_unblock_requests(hostdata->host); 8613507e13fcba6b97501891a410ec8ef9f1f188620Brian King} 8623507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8633507e13fcba6b97501891a410ec8ef9f1f188620Brian King/** 8643507e13fcba6b97501891a410ec8ef9f1f188620Brian King * send_srp_login: - Sends the srp login 8653507e13fcba6b97501891a410ec8ef9f1f188620Brian King * @hostdata: ibmvscsi_host_data of host 8663507e13fcba6b97501891a410ec8ef9f1f188620Brian King * 8673507e13fcba6b97501891a410ec8ef9f1f188620Brian King * Returns zero if successful. 8683507e13fcba6b97501891a410ec8ef9f1f188620Brian King*/ 8693507e13fcba6b97501891a410ec8ef9f1f188620Brian Kingstatic int send_srp_login(struct ibmvscsi_host_data *hostdata) 8703507e13fcba6b97501891a410ec8ef9f1f188620Brian King{ 8713507e13fcba6b97501891a410ec8ef9f1f188620Brian King int rc; 8723507e13fcba6b97501891a410ec8ef9f1f188620Brian King unsigned long flags; 8733507e13fcba6b97501891a410ec8ef9f1f188620Brian King struct srp_login_req *login; 8743507e13fcba6b97501891a410ec8ef9f1f188620Brian King struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool); 8753507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8763507e13fcba6b97501891a410ec8ef9f1f188620Brian King BUG_ON(!evt_struct); 8773507e13fcba6b97501891a410ec8ef9f1f188620Brian King init_event_struct(evt_struct, login_rsp, 8783507e13fcba6b97501891a410ec8ef9f1f188620Brian King VIOSRP_SRP_FORMAT, login_timeout); 8793507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8803507e13fcba6b97501891a410ec8ef9f1f188620Brian King login = &evt_struct->iu.srp.login_req; 8813507e13fcba6b97501891a410ec8ef9f1f188620Brian King memset(login, 0, sizeof(*login)); 8823507e13fcba6b97501891a410ec8ef9f1f188620Brian King login->opcode = SRP_LOGIN_REQ; 8833507e13fcba6b97501891a410ec8ef9f1f188620Brian King login->req_it_iu_len = sizeof(union srp_iu); 8843507e13fcba6b97501891a410ec8ef9f1f188620Brian King login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; 8853507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8863507e13fcba6b97501891a410ec8ef9f1f188620Brian King spin_lock_irqsave(hostdata->host->host_lock, flags); 8873507e13fcba6b97501891a410ec8ef9f1f188620Brian King /* Start out with a request limit of 0, since this is negotiated in 8883507e13fcba6b97501891a410ec8ef9f1f188620Brian King * the login request we are just sending and login requests always 8893507e13fcba6b97501891a410ec8ef9f1f188620Brian King * get sent by the driver regardless of request_limit. 8903507e13fcba6b97501891a410ec8ef9f1f188620Brian King */ 8913507e13fcba6b97501891a410ec8ef9f1f188620Brian King atomic_set(&hostdata->request_limit, 0); 8923507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8933507e13fcba6b97501891a410ec8ef9f1f188620Brian King rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2); 8943507e13fcba6b97501891a410ec8ef9f1f188620Brian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 8953507e13fcba6b97501891a410ec8ef9f1f188620Brian King dev_info(hostdata->dev, "sent SRP login\n"); 8963507e13fcba6b97501891a410ec8ef9f1f188620Brian King return rc; 8973507e13fcba6b97501891a410ec8ef9f1f188620Brian King}; 8983507e13fcba6b97501891a410ec8ef9f1f188620Brian King 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 900126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * capabilities_rsp: - Handle response to MAD adapter capabilities request 901126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * @evt_struct: srp_event_struct with the response 902126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * 903126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * Used as a "done" callback by when sending adapter_info. 904126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King */ 905126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic void capabilities_rsp(struct srp_event_struct *evt_struct) 906126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 907126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 908126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 909126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (evt_struct->xfer_iu->mad.capabilities.common.status) { 910126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(hostdata->dev, "error 0x%X getting capabilities info\n", 911126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King evt_struct->xfer_iu->mad.capabilities.common.status); 912126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } else { 913126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (hostdata->caps.migration.common.server_support != SERVER_SUPPORTS_CAP) 914126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_info(hostdata->dev, "Partition migration not supported\n"); 915126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 916126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (client_reserve) { 917126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (hostdata->caps.reserve.common.server_support == 918126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King SERVER_SUPPORTS_CAP) 919126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_info(hostdata->dev, "Client reserve enabled\n"); 920126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King else 921126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_info(hostdata->dev, "Client reserve not supported\n"); 922126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 923126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 924126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 925126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King send_srp_login(hostdata); 926126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 927126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 928126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King/** 929126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * send_mad_capabilities: - Sends the mad capabilities request 930126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * and stores the result so it can be retrieved with 931126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King * @hostdata: ibmvscsi_host_data of host 932126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King */ 933126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic void send_mad_capabilities(struct ibmvscsi_host_data *hostdata) 934126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 935126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct viosrp_capabilities *req; 936126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct srp_event_struct *evt_struct; 937126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King unsigned long flags; 93861c7a080a5a061c976988fd4b844dfb468dda255Grant Likely struct device_node *of_node = hostdata->dev->of_node; 939126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King const char *location; 940126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 941126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King evt_struct = get_event_struct(&hostdata->pool); 942126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King BUG_ON(!evt_struct); 943126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 944126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King init_event_struct(evt_struct, capabilities_rsp, 945126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King VIOSRP_MAD_FORMAT, info_timeout); 946126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 947126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req = &evt_struct->iu.mad.capabilities; 948126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King memset(req, 0, sizeof(*req)); 949126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 950126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.flags = CAP_LIST_SUPPORTED; 951126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (hostdata->client_migrated) 952126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.flags |= CLIENT_MIGRATED; 953126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 954126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King strncpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev), 955126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King sizeof(hostdata->caps.name)); 956126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.name[sizeof(hostdata->caps.name) - 1] = '\0'; 957126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 958126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King location = of_get_property(of_node, "ibm,loc-code", NULL); 959126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King location = location ? location : dev_name(hostdata->dev); 960126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King strncpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc)); 961126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.loc[sizeof(hostdata->caps.loc) - 1] = '\0'; 962126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 963126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->common.type = VIOSRP_CAPABILITIES_TYPE; 964126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->buffer = hostdata->caps_addr; 965126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 966126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.migration.common.cap_type = MIGRATION_CAPABILITIES; 967126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.migration.common.length = sizeof(hostdata->caps.migration); 968126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.migration.common.server_support = SERVER_SUPPORTS_CAP; 969126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.migration.ecl = 1; 970126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 971126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (client_reserve) { 972126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.reserve.common.cap_type = RESERVATION_CAPABILITIES; 973126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.reserve.common.length = sizeof(hostdata->caps.reserve); 974126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.reserve.common.server_support = SERVER_SUPPORTS_CAP; 975126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.reserve.type = CLIENT_RESERVE_SCSI_2; 976126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->common.length = sizeof(hostdata->caps); 977126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } else 978126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->common.length = sizeof(hostdata->caps) - sizeof(hostdata->caps.reserve); 979126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 980126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King spin_lock_irqsave(hostdata->host->host_lock, flags); 981126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2)) 982126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(hostdata->dev, "couldn't send CAPABILITIES_REQ!\n"); 983126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 984126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King}; 985126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 986126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King/** 987c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * fast_fail_rsp: - Handle response to MAD enable fast fail 988c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * @evt_struct: srp_event_struct with the response 989c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * 990c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * Used as a "done" callback by when sending enable fast fail. Gets called 991c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * by ibmvscsi_handle_crq() 992c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings */ 993c1988e3123751fd425fbae99d5c1776608e965a9Robert Jenningsstatic void fast_fail_rsp(struct srp_event_struct *evt_struct) 994c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings{ 995c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 996c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings u8 status = evt_struct->xfer_iu->mad.fast_fail.common.status; 997c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 998c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings if (status == VIOSRP_MAD_NOT_SUPPORTED) 999c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings dev_err(hostdata->dev, "fast_fail not supported in server\n"); 1000c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings else if (status == VIOSRP_MAD_FAILED) 1001c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings dev_err(hostdata->dev, "fast_fail request failed\n"); 1002c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings else if (status != VIOSRP_MAD_SUCCESS) 1003c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings dev_err(hostdata->dev, "error 0x%X enabling fast_fail\n", status); 1004c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1005126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King send_mad_capabilities(hostdata); 1006c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings} 1007c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1008c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings/** 1009c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * init_host - Start host initialization 1010c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * @hostdata: ibmvscsi_host_data of host 1011c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * 1012c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings * Returns zero if successful. 1013c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings */ 1014c1988e3123751fd425fbae99d5c1776608e965a9Robert Jenningsstatic int enable_fast_fail(struct ibmvscsi_host_data *hostdata) 1015c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings{ 1016c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings int rc; 1017c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings unsigned long flags; 1018c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings struct viosrp_fast_fail *fast_fail_mad; 1019c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings struct srp_event_struct *evt_struct; 1020c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1021126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (!fast_fail) { 1022126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King send_mad_capabilities(hostdata); 1023126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return 0; 1024126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 1025c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1026c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings evt_struct = get_event_struct(&hostdata->pool); 1027c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings BUG_ON(!evt_struct); 1028c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1029c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings init_event_struct(evt_struct, fast_fail_rsp, VIOSRP_MAD_FORMAT, info_timeout); 1030c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1031c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings fast_fail_mad = &evt_struct->iu.mad.fast_fail; 1032c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings memset(fast_fail_mad, 0, sizeof(*fast_fail_mad)); 1033c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings fast_fail_mad->common.type = VIOSRP_ENABLE_FAST_FAIL; 1034c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings fast_fail_mad->common.length = sizeof(*fast_fail_mad); 1035c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1036c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings spin_lock_irqsave(hostdata->host->host_lock, flags); 1037c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings rc = ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2); 1038c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1039c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings return rc; 1040c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings} 1041c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings 1042c1988e3123751fd425fbae99d5c1776608e965a9Robert Jennings/** 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adapter_info_rsp: - Handle response to MAD adapter info request 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @evt_struct: srp_event_struct with the response 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used as a "done" callback by when sending adapter_info. Gets called 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by ibmvscsi_handle_crq() 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adapter_info_rsp(struct srp_event_struct *evt_struct) 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt_struct->xfer_iu->mad.adapter_info.common.status) { 10546c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "error %d getting adapter info\n", 10556c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King evt_struct->xfer_iu->mad.adapter_info.common.status); 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10576c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_info(hostdata->dev, "host srp version: %s, " 10586c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "host partition %s (%d), OS %d, max io %u\n", 10596c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.srp_version, 10606c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.partition_name, 10616c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.partition_number, 10626c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.os_type, 10636c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.port_max_txu[0]); 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hostdata->madapter_info.port_max_txu[0]) 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->host->max_sectors = 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.port_max_txu[0] >> 9; 1068154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher 1069154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher if (hostdata->madapter_info.os_type == 3 && 1070154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) { 10716c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "host (Ver. %s) doesn't support large transfers\n", 10726c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King hostdata->madapter_info.srp_version); 10736c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "limiting scatterlists to %d\n", 10746c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King MAX_INDIRECT_BUFS); 1075154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; 1076154fb614df83086ceb18a2c19908154e78d4dc98Dave C Boutcher } 1077e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King 1078e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King if (hostdata->madapter_info.os_type == 3) { 1079e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King enable_fast_fail(hostdata); 1080e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King return; 1081e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King } 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10833507e13fcba6b97501891a410ec8ef9f1f188620Brian King 1084e08afeb7e69f45e4ab9fbb8530fe433484b96606Brian King send_srp_login(hostdata); 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * send_mad_adapter_info: - Sends the mad adapter info request 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and stores the result so it can be retrieved with 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysfs. We COULD consider causing a failure if the 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returned SRP version doesn't match ours. 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data of host 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns zero if successful. 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata) 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct viosrp_adapter_info *req; 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt_struct; 110006f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King unsigned long flags; 1101e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct = get_event_struct(&hostdata->pool); 11033507e13fcba6b97501891a410ec8ef9f1f188620Brian King BUG_ON(!evt_struct); 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_event_struct(evt_struct, 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter_info_rsp, 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VIOSRP_MAD_FORMAT, 1108e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings info_timeout); 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req = &evt_struct->iu.mad.adapter_info; 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(req, 0x00, sizeof(*req)); 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->common.type = VIOSRP_ADAPTER_INFO_TYPE; 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->common.length = sizeof(hostdata->madapter_info); 1115126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King req->buffer = hostdata->adapter_info_addr; 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111706f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King spin_lock_irqsave(hostdata->host->host_lock, flags); 1118126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2)) 11196c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "couldn't send ADAPTER_INFO_REQ!\n"); 112006f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 11243507e13fcba6b97501891a410ec8ef9f1f188620Brian King * init_adapter: Start virtual adapter initialization sequence 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11263507e13fcba6b97501891a410ec8ef9f1f188620Brian King */ 11273507e13fcba6b97501891a410ec8ef9f1f188620Brian Kingstatic void init_adapter(struct ibmvscsi_host_data *hostdata) 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_mad_adapter_info(hostdata); 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sync_completion: Signal that a synchronous command has completed 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that after returning from this call, the evt_struct is freed. 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the caller waiting on this completion shouldn't touch the evt_struct 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * again. 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sync_completion(struct srp_event_struct *evt_struct) 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy the response back */ 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt_struct->sync_srp) 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *evt_struct->sync_srp = *evt_struct->xfer_iu; 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete(&evt_struct->comp); 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_abort: Abort a command...from scsi host template 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * send this over to the server and wait synchronously for the response 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11537603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_tsk_mgmt *tsk_mgmt; 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt; 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *tmp_evt, *found_evt; 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union viosrp_iu srp_rsp; 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rsp_rc; 1159be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher unsigned long flags; 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 lun = lun_from_dev(cmd->device); 1161860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings unsigned long wait_switch = 0; 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First, find this command in our sent list so we can figure 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * out the correct tag 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1166be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_lock_irqsave(hostdata->host->host_lock, flags); 1167860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings wait_switch = jiffies + (init_timeout * HZ); 1168860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings do { 1169860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings found_evt = NULL; 1170860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings list_for_each_entry(tmp_evt, &hostdata->sent, list) { 1171860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (tmp_evt->cmnd == cmd) { 1172860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings found_evt = tmp_evt; 1173860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings break; 1174860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1177860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (!found_evt) { 1178860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1179860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings return SUCCESS; 1180860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1182860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings evt = get_event_struct(&hostdata->pool); 1183860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (evt == NULL) { 1184860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1185860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sdev_printk(KERN_ERR, cmd->device, 1186860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings "failed to allocate abort event\n"); 1187860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings return FAILED; 1188860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1190860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings init_event_struct(evt, 1191860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sync_completion, 1192860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings VIOSRP_SRP_FORMAT, 1193e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings abort_timeout); 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1195860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt = &evt->iu.srp.tsk_mgmt; 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1197860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings /* Set up an abort SRP command */ 1198860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt)); 1199860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->opcode = SRP_TSK_MGMT; 1200860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->lun = ((u64) lun) << 48; 1201860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK; 1202860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->task_tag = (u64) found_evt; 1203860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1204860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings evt->sync_srp = &srp_rsp; 1205860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1206860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings init_completion(&evt->comp); 1207e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, abort_timeout * 2); 1208860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1209860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY) 1210860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings break; 1211860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1212860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1213860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings msleep(10); 1214860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_lock_irqsave(hostdata->host->host_lock, flags); 1215860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } while (time_before(jiffies, wait_switch)); 1216860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1217be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1218860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1219be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher if (rsp_rc != 0) { 12206c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_ERR, cmd->device, 12216c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "failed to send abort() event. rc=%d\n", rsp_rc); 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1225860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sdev_printk(KERN_INFO, cmd->device, 1226fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar "aborting command. lun 0x%llx, tag 0x%llx\n", 1227860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings (((u64) lun) << 48), (u64) found_evt); 1228860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_for_completion(&evt->comp); 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* make sure we got a good response */ 1232ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) { 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 12346c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_WARNING, cmd->device, "abort bad SRP RSP type %d\n", 12356c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King srp_rsp.srp.rsp.opcode); 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1239ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID) 1240ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori rsp_rc = *((int *)srp_rsp.srp.rsp.data); 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rsp_rc = srp_rsp.srp.rsp.status; 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rsp_rc) { 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 12466c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_WARNING, cmd->device, 1247fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar "abort code %d for task tag 0x%llx\n", 12486c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King rsp_rc, tsk_mgmt->task_tag); 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Because we dropped the spinlock above, it's possible 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The event is no longer in our list. Make sure it didn't 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complete while we were aborting 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1256be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_lock_irqsave(hostdata->host->host_lock, flags); 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found_evt = NULL; 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(tmp_evt, &hostdata->sent, list) { 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp_evt->cmnd == cmd) { 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found_evt = tmp_evt; 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (found_evt == NULL) { 1266be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1267fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%llx completed\n", 12686c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King tsk_mgmt->task_tag); 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1272fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%llx\n", 12736c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King tsk_mgmt->task_tag); 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd->result = (DID_ABORT << 16); 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&found_evt->list); 12774dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt, 12784dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley found_evt->hostdata->dev); 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&found_evt->hostdata->pool, found_evt); 1280be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&hostdata->request_limit); 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_eh_device_reset_handler: Reset a single LUN...from scsi host 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * template send this over to the server and wait synchronously for the 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12927603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_tsk_mgmt *tsk_mgmt; 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt; 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *tmp_evt, *pos; 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union viosrp_iu srp_rsp; 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rsp_rc; 1298be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher unsigned long flags; 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 lun = lun_from_dev(cmd->device); 1300860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings unsigned long wait_switch = 0; 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1302be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_lock_irqsave(hostdata->host->host_lock, flags); 1303860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings wait_switch = jiffies + (init_timeout * HZ); 1304860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings do { 1305860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings evt = get_event_struct(&hostdata->pool); 1306860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (evt == NULL) { 1307860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1308860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sdev_printk(KERN_ERR, cmd->device, 1309860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings "failed to allocate reset event\n"); 1310860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings return FAILED; 1311860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1313860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings init_event_struct(evt, 1314860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings sync_completion, 1315860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings VIOSRP_SRP_FORMAT, 1316e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings reset_timeout); 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1318860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt = &evt->iu.srp.tsk_mgmt; 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1320860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings /* Set up a lun reset SRP command */ 1321860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt)); 1322860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->opcode = SRP_TSK_MGMT; 1323860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->lun = ((u64) lun) << 48; 1324860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET; 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1326860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings evt->sync_srp = &srp_rsp; 1327860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1328860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings init_completion(&evt->comp); 1329e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, reset_timeout * 2); 1330860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1331860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY) 1332860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings break; 1333860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1334860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1335860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings msleep(10); 1336860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings spin_lock_irqsave(hostdata->host->host_lock, flags); 1337860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings } while (time_before(jiffies, wait_switch)); 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1339be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1340860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 1341be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher if (rsp_rc != 0) { 13426c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_ERR, cmd->device, 13436c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King "failed to send reset event. rc=%d\n", rsp_rc); 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1347fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%llx\n", 1348860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings (((u64) lun) << 48)); 1349860784c8a2b077157b6a51fb8749524d0363cc49Robert Jennings 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_for_completion(&evt->comp); 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* make sure we got a good response */ 1353ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) { 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 13556c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_WARNING, cmd->device, "reset bad SRP RSP type %d\n", 13566c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King srp_rsp.srp.rsp.opcode); 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1360ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID) 1361ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori rsp_rc = *((int *)srp_rsp.srp.rsp.data); 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rsp_rc = srp_rsp.srp.rsp.status; 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rsp_rc) { 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (printk_ratelimit()) 13676c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King sdev_printk(KERN_WARNING, cmd->device, 1368fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar "reset code %d for task tag 0x%llx\n", 13696c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King rsp_rc, tsk_mgmt->task_tag); 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We need to find all commands for this LUN that have not yet been 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * responded to, and fail them with DID_RESET 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1376be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_lock_irqsave(hostdata->host->host_lock, flags); 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) { 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp_evt->cmnd) 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_evt->cmnd->result = (DID_RESET << 16); 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&tmp_evt->list); 13824dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt, 13834dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley tmp_evt->hostdata->dev); 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&tmp_evt->hostdata->pool, 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_evt); 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&hostdata->request_limit); 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp_evt->cmnd_done) 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_evt->cmnd_done(tmp_evt->cmnd); 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (tmp_evt->done) 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_evt->done(tmp_evt); 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1393be042f240a8528b8f6b741a484cdbbf515698388Dave C Boutcher spin_unlock_irqrestore(hostdata->host->host_lock, flags); 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 13983d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * ibmvscsi_eh_host_reset_handler - Reset the connection to the server 13993d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King * @cmd: struct scsi_cmnd having problems 14003d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King*/ 14013d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian Kingstatic int ibmvscsi_eh_host_reset_handler(struct scsi_cmnd *cmd) 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14033d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King unsigned long wait_switch = 0; 14047603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14063d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King dev_err(hostdata->dev, "Resetting connection due to error recovery\n"); 14073d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14083d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King ibmvscsi_reset_host(hostdata); 14093d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14103d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King for (wait_switch = jiffies + (init_timeout * HZ); 14113d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King time_before(jiffies, wait_switch) && 14123d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King atomic_read(&hostdata->request_limit) < 2;) { 14133d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14143d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King msleep(10); 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14163d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14173d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King if (atomic_read(&hostdata->request_limit) <= 0) 14183d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King return FAILED; 14193d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 14203d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King return SUCCESS; 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_handle_crq: - Handles and frees received events in the CRQ 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @crq: Command/Response queue 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hostdata: ibmvscsi_host_data of host 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ibmvscsi_handle_crq(struct viosrp_crq *crq, 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmvscsi_host_data *hostdata) 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14326c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King long rc; 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt_struct = 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (struct srp_event_struct *)crq->IU_data_ptr; 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (crq->valid) { 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xC0: /* initialization */ 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (crq->format) { 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x01: /* Initialization message */ 14406c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_info(hostdata->dev, "partner initialized\n"); 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send back a response */ 1442d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse if ((rc = ibmvscsi_ops->send_crq(hostdata, 1443d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse 0xC002000000000000LL, 0)) == 0) { 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now login */ 14453507e13fcba6b97501891a410ec8ef9f1f188620Brian King init_adapter(hostdata); 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 14476c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc); 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x02: /* Initialization response */ 14526c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_info(hostdata->dev, "partner initialization complete\n"); 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now login */ 14553507e13fcba6b97501891a410ec8ef9f1f188620Brian King init_adapter(hostdata); 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 14586c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format); 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14612b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher case 0xFF: /* Hypervisor telling us the connection is closed */ 14622b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher scsi_block_requests(hostdata->host); 1463cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher atomic_set(&hostdata->request_limit, 0); 14642b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher if (crq->format == 0x06) { 14652b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher /* We need to re-setup the interpartition connection */ 14666c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_info(hostdata->dev, "Re-enabling adapter!\n"); 1467126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->client_migrated = 1; 14680f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->reenable_crq = 1; 14692b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher purge_requests(hostdata, DID_REQUEUE); 14700f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King wake_up(&hostdata->work_wait_q); 14712b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher } else { 14726c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "Virtual adapter failed rc %d!\n", 14736c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King crq->format); 14740f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King ibmvscsi_reset_host(hostdata); 14752b541f8f77fd339e4c5c5cbe8549b52445012704Dave C Boutcher } 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x80: /* real payload */ 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 14806c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "got an invalid message type 0x%02x\n", 14816c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King crq->valid); 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The only kind of payload CRQs we should get are responses to 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * things we send. Make sure this response is to something we 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually sent 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!valid_event_struct(&hostdata->pool, evt_struct)) { 14906c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "returned correlation_token 0x%p is invalid!\n", 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *)crq->IU_data_ptr); 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&evt_struct->free)) { 14966c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "received duplicate correlation_token 0x%p!\n", 14976c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King (void *)crq->IU_data_ptr); 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (crq->format == VIOSRP_SRP_FORMAT) 1502ef265673434680f2307ceafae4a2badc657e94ccFUJITA Tomonori atomic_add(evt_struct->xfer_iu->srp.rsp.req_lim_delta, 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &hostdata->request_limit); 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15053d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King del_timer(&evt_struct->timer); 15063d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King 1507ca61668b82a902143997794aae3f681a602e6ebcBrian King if ((crq->status != VIOSRP_OK && crq->status != VIOSRP_OK2) && evt_struct->cmnd) 1508c3a3b55ae80a0d595445064159c69f8e80911e85Brian King evt_struct->cmnd->result = DID_ERROR << 16; 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evt_struct->done) 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct->done(evt_struct); 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 15126c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "returned done() is NULL; not running it!\n"); 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Lock the host_lock before messing with these structures, since we 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are running in a task context 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(evt_struct->hostdata->host->host_lock, flags); 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&evt_struct->list); 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&evt_struct->hostdata->pool, evt_struct); 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(evt_struct->hostdata->host->host_lock, flags); 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_get_host_config: Send the command to the server to get host 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configuration data. The data is opaque to us. 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *buffer, int length) 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct viosrp_host_config *host_config; 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct srp_event_struct *evt_struct; 153306f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King unsigned long flags; 1534e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori dma_addr_t addr; 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evt_struct = get_event_struct(&hostdata->pool); 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!evt_struct) { 15396c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(hostdata->dev, "couldn't allocate event for HOST_CONFIG!\n"); 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_event_struct(evt_struct, 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sync_completion, 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VIOSRP_MAD_FORMAT, 1546e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings info_timeout); 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_config = &evt_struct->iu.mad.host_config; 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up a lun reset SRP command */ 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(host_config, 0x00, sizeof(*host_config)); 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_config->common.type = VIOSRP_HOST_CONFIG_TYPE; 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_config->common.length = length; 1554e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori host_config->buffer = addr = dma_map_single(hostdata->dev, buffer, 1555e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori length, 1556e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori DMA_BIDIRECTIONAL); 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15588d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori if (dma_mapping_error(hostdata->dev, host_config->buffer)) { 15597912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings if (!firmware_has_feature(FW_FEATURE_CMO)) 15607912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings dev_err(hostdata->dev, 15617912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings "dma_mapping error getting host config\n"); 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_event_struct(&hostdata->pool, evt_struct); 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_completion(&evt_struct->comp); 156706f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King spin_lock_irqsave(hostdata->host->host_lock, flags); 1568e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings rc = ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2); 156906f923cbf080e22d1ffccbf3fd2cbab0176f6025Brian King spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1570e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori if (rc == 0) 15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_for_completion(&evt_struct->comp); 1572e5dbfa6621732a110514fb10f9a43f0e8f4befd4FUJITA Tomonori dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL); 15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15770979c84b4affaf924a894380dd0069638b64de03Robert Jennings/** 15780979c84b4affaf924a894380dd0069638b64de03Robert Jennings * ibmvscsi_slave_configure: Set the "allow_restart" flag for each disk. 15790979c84b4affaf924a894380dd0069638b64de03Robert Jennings * @sdev: struct scsi_device device to configure 15800979c84b4affaf924a894380dd0069638b64de03Robert Jennings * 15810979c84b4affaf924a894380dd0069638b64de03Robert Jennings * Enable allow_restart for a device if it is a disk. Adjust the 15820979c84b4affaf924a894380dd0069638b64de03Robert Jennings * queue_depth here also as is required by the documentation for 15830979c84b4affaf924a894380dd0069638b64de03Robert Jennings * struct scsi_host_template. 15840979c84b4affaf924a894380dd0069638b64de03Robert Jennings */ 15850979c84b4affaf924a894380dd0069638b64de03Robert Jenningsstatic int ibmvscsi_slave_configure(struct scsi_device *sdev) 15860979c84b4affaf924a894380dd0069638b64de03Robert Jennings{ 15870979c84b4affaf924a894380dd0069638b64de03Robert Jennings struct Scsi_Host *shost = sdev->host; 15880979c84b4affaf924a894380dd0069638b64de03Robert Jennings unsigned long lock_flags = 0; 15890979c84b4affaf924a894380dd0069638b64de03Robert Jennings 15900979c84b4affaf924a894380dd0069638b64de03Robert Jennings spin_lock_irqsave(shost->host_lock, lock_flags); 1591d1a357fcc8348d325d151f6fe0ea54e317652457Brian King if (sdev->type == TYPE_DISK) { 15920979c84b4affaf924a894380dd0069638b64de03Robert Jennings sdev->allow_restart = 1; 1593e1a5ce5b88d06344caec0c71b4ee33e7296358ddRobert Jennings blk_queue_rq_timeout(sdev->request_queue, 120 * HZ); 1594d1a357fcc8348d325d151f6fe0ea54e317652457Brian King } 15950979c84b4affaf924a894380dd0069638b64de03Robert Jennings scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun); 15960979c84b4affaf924a894380dd0069638b64de03Robert Jennings spin_unlock_irqrestore(shost->host_lock, lock_flags); 15970979c84b4affaf924a894380dd0069638b64de03Robert Jennings return 0; 15980979c84b4affaf924a894380dd0069638b64de03Robert Jennings} 15990979c84b4affaf924a894380dd0069638b64de03Robert Jennings 1600742d25b819f11dce91b89e6c9ac17402a119f20aBrian King/** 1601742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * ibmvscsi_change_queue_depth - Change the device's queue depth 1602742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * @sdev: scsi device struct 1603742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * @qdepth: depth to set 1604e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie * @reason: calling context 1605742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * 1606742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * Return value: 1607742d25b819f11dce91b89e6c9ac17402a119f20aBrian King * actual depth set 1608742d25b819f11dce91b89e6c9ac17402a119f20aBrian King **/ 1609e881a172dac4d9ea3b2a1540041d872963c269bdMike Christiestatic int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth, 1610e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie int reason) 1611742d25b819f11dce91b89e6c9ac17402a119f20aBrian King{ 1612e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie if (reason != SCSI_QDEPTH_DEFAULT) 1613e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie return -EOPNOTSUPP; 1614e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie 1615742d25b819f11dce91b89e6c9ac17402a119f20aBrian King if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN) 1616742d25b819f11dce91b89e6c9ac17402a119f20aBrian King qdepth = IBMVSCSI_MAX_CMDS_PER_LUN; 1617742d25b819f11dce91b89e6c9ac17402a119f20aBrian King 1618742d25b819f11dce91b89e6c9ac17402a119f20aBrian King scsi_adjust_queue_depth(sdev, 0, qdepth); 1619742d25b819f11dce91b89e6c9ac17402a119f20aBrian King return sdev->queue_depth; 1620742d25b819f11dce91b89e6c9ac17402a119f20aBrian King} 1621742d25b819f11dce91b89e6c9ac17402a119f20aBrian King 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysfs attributes 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1625126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic ssize_t show_host_vhost_loc(struct device *dev, 1626126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct device_attribute *attr, char *buf) 1627126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 1628126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct Scsi_Host *shost = class_to_shost(dev); 1629126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct ibmvscsi_host_data *hostdata = shost_priv(shost); 1630126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King int len; 1631126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1632126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King len = snprintf(buf, sizeof(hostdata->caps.loc), "%s\n", 1633126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.loc); 1634126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return len; 1635126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 1636126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1637126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic struct device_attribute ibmvscsi_host_vhost_loc = { 1638126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .attr = { 1639126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .name = "vhost_loc", 1640126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .mode = S_IRUGO, 1641126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King }, 1642126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .show = show_host_vhost_loc, 1643126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King}; 1644126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1645126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic ssize_t show_host_vhost_name(struct device *dev, 1646126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct device_attribute *attr, char *buf) 1647126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King{ 1648126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct Scsi_Host *shost = class_to_shost(dev); 1649126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King struct ibmvscsi_host_data *hostdata = shost_priv(shost); 1650126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King int len; 1651126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1652126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King len = snprintf(buf, sizeof(hostdata->caps.name), "%s\n", 1653126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King hostdata->caps.name); 1654126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King return len; 1655126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King} 1656126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1657126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian Kingstatic struct device_attribute ibmvscsi_host_vhost_name = { 1658126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .attr = { 1659126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .name = "vhost_name", 1660126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .mode = S_IRUGO, 1661126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King }, 1662126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King .show = show_host_vhost_name, 1663126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King}; 1664126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 1665ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_srp_version(struct device *dev, 1666ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1668ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 16697603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%s\n", 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.srp_version); 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1677ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_srp_version = { 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "srp_version", 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_srp_version, 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1685ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_partition_name(struct device *dev, 1686ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf) 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1689ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 16907603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%s\n", 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.partition_name); 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1698ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_partition_name = { 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "partition_name", 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_partition_name, 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1706ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_partition_number(struct device *dev, 1707ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf) 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1710ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 17117603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%d\n", 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.partition_number); 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1719ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_partition_number = { 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "partition_number", 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_partition_number, 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1727ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_mad_version(struct device *dev, 1728ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1730ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 17317603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%d\n", 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->madapter_info.mad_version); 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1739ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_mad_version = { 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "mad_version", 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_mad_version, 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1747ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_os_type(struct device *dev, 1748ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1750ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 17517603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = snprintf(buf, PAGE_SIZE, "%d\n", hostdata->madapter_info.os_type); 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1758ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_os_type = { 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "os_type", 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_os_type, 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1766ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t show_host_config(struct device *dev, 1767ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1769ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct Scsi_Host *shost = class_to_shost(dev); 17707603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori struct ibmvscsi_host_data *hostdata = shost_priv(shost); 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* returns null-terminated host config data */ 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ibmvscsi_do_host_config(hostdata, buf, PAGE_SIZE) == 0) 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return strlen(buf); 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1779ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute ibmvscsi_host_config = { 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attr = { 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "config", 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mode = S_IRUGO, 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = show_host_config, 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1787ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute *ibmvscsi_attrs[] = { 1788126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King &ibmvscsi_host_vhost_loc, 1789126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King &ibmvscsi_host_vhost_name, 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_srp_version, 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_partition_name, 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_partition_number, 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_mad_version, 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_os_type, 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ibmvscsi_host_config, 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ------------------------------------------------------------ 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCSI driver registration 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct scsi_host_template driver_template = { 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .module = THIS_MODULE, 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "IBM POWER Virtual SCSI Adapter " IBMVSCSI_VERSION, 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .proc_name = "ibmvscsi", 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .queuecommand = ibmvscsi_queuecommand, 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_abort_handler = ibmvscsi_eh_abort_handler, 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, 18093d0e91f7ace12499c4b00088e9a6b1361e1bb0caBrian King .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler, 18100979c84b4affaf924a894380dd0069638b64de03Robert Jennings .slave_configure = ibmvscsi_slave_configure, 1811742d25b819f11dce91b89e6c9ac17402a119f20aBrian King .change_queue_depth = ibmvscsi_change_queue_depth, 18127912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings .cmd_per_lun = IBMVSCSI_CMDS_PER_LUN_DEFAULT, 1813a897ff2a6386ac4368ba41db18b626afd903f9d8Robert Jennings .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .this_id = -1, 18154dddbc26c3895ecdab1f4b16435685b47f96f599James Bottomley .sg_tablesize = SG_ALL, 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .use_clustering = ENABLE_CLUSTERING, 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .shost_attrs = ibmvscsi_attrs, 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 18217912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * ibmvscsi_get_desired_dma - Calculate IO memory desired by the driver 18227912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * 18237912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * @vdev: struct vio_dev for the device whose desired IO mem is to be returned 18247912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * 18257912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * Return value: 18267912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings * Number of bytes of IO data the driver will need to perform well. 18277912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings */ 18287912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jenningsstatic unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev) 18297912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings{ 18307912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings /* iu_storage data allocated in initialize_event_pool */ 18314f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King unsigned long desired_io = max_events * sizeof(union viosrp_iu); 18327912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings 18337912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings /* add io space for sg data */ 1834004dd5e88673516a408f0e8e43edbe6a4424be2fBrian King desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * 512 * 18357912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings IBMVSCSI_CMDS_PER_LUN_DEFAULT); 18367912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings 18377912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings return desired_io; 18387912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings} 18397912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings 18400f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian Kingstatic void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata) 18410f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King{ 18420f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King int rc; 18430f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King char *action = "reset"; 18440f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18450f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (hostdata->reset_crq) { 18460f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King smp_rmb(); 18470f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->reset_crq = 0; 18480f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18490f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata); 18500f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (!rc) 18510f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0); 1852201aed678482f247aa96bd8fcd9e960fefd82d59Brian King vio_enable_interrupts(to_vio_dev(hostdata->dev)); 18530f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } else if (hostdata->reenable_crq) { 18540f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King smp_rmb(); 18550f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King action = "enable"; 18560f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = ibmvscsi_ops->reenable_crq_queue(&hostdata->queue, hostdata); 18570f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->reenable_crq = 0; 18580f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (!rc) 18590f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0); 18600f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } else 18610f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return; 18620f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18630f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (rc) { 18640f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King atomic_set(&hostdata->request_limit, -1); 18650f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King dev_err(hostdata->dev, "error after %s\n", action); 18660f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } 18670f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18680f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King scsi_unblock_requests(hostdata->host); 18690f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King} 18700f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18710f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian Kingstatic int ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata) 18720f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King{ 18730f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (kthread_should_stop()) 18740f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 1; 18750f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King else if (hostdata->reset_crq) { 18760f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King smp_rmb(); 18770f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 1; 18780f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } else if (hostdata->reenable_crq) { 18790f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King smp_rmb(); 18800f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 1; 18810f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } 18820f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18830f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 0; 18840f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King} 18850f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18860f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian Kingstatic int ibmvscsi_work(void *data) 18870f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King{ 18880f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King struct ibmvscsi_host_data *hostdata = data; 18890f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King int rc; 18900f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18910f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King set_user_nice(current, -20); 18920f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18930f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King while (1) { 18940f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King rc = wait_event_interruptible(hostdata->work_wait_q, 18950f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King ibmvscsi_work_to_do(hostdata)); 18960f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18970f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King BUG_ON(rc); 18980f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 18990f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (kthread_should_stop()) 19000f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King break; 19010f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 19020f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King ibmvscsi_do_work(hostdata); 19030f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } 19040f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 19050f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King return 0; 19060f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King} 19070f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 19087912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings/** 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by bus code for each adapter 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmvscsi_host_data *hostdata; 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *host; 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev = &vdev->dev; 19164d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori struct srp_rport_identifiers ids; 19174d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori struct srp_rport *rport; 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long wait_switch = 0; 1919cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher int rc; 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921559fde706873256903155b3a62b05d0f52d62ab9Greg Kroah-Hartman dev_set_drvdata(&vdev->dev, NULL); 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host = scsi_host_alloc(&driver_template, sizeof(*hostdata)); 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!host) { 19256c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(&vdev->dev, "couldn't allocate host data\n"); 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto scsi_host_alloc_failed; 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19294d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori host->transportt = ibmvscsi_transport_template; 19307603e02eac309626c0153ebddf277253ea7fe0e0FUJITA Tomonori hostdata = shost_priv(host); 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(hostdata, 0x00, sizeof(*hostdata)); 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&hostdata->sent); 19330f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King init_waitqueue_head(&hostdata->work_wait_q); 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->host = host; 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hostdata->dev = dev; 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&hostdata->request_limit, -1); 19377912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT; 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1939126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King if (map_persist_bufs(hostdata)) { 1940126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King dev_err(&vdev->dev, "couldn't map persistent buffers\n"); 1941126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King goto persist_bufs_failed; 1942126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King } 1943126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King 19440f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King hostdata->work_thread = kthread_run(ibmvscsi_work, hostdata, "%s_%d", 19450f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King "ibmvscsi", host->host_no); 19460f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 19470f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King if (IS_ERR(hostdata->work_thread)) { 19480f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King dev_err(&vdev->dev, "couldn't initialize kthread. rc=%ld\n", 19490f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King PTR_ERR(hostdata->work_thread)); 19500f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King goto init_crq_failed; 19510f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King } 19520f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King 19534f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_events); 1954cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher if (rc != 0 && rc != H_RESOURCE) { 19556c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc); 19560f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King goto kill_kthread; 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19584f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King if (initialize_event_pool(&hostdata->pool, max_events, hostdata) != 0) { 19596c0a60ec52042ece8bf4904c91ac497188e8d70bBrian King dev_err(&vdev->dev, "couldn't initialize event pool\n"); 19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto init_pool_failed; 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->max_lun = 8; 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->max_id = max_id; 19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->max_channel = max_channel; 1966fbc56f0801f58041a4372a030933bac076b46aadBrian King host->max_cmd_len = 16; 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (scsi_add_host(hostdata->host, hostdata->dev)) 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto add_host_failed; 19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19714d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori /* we don't have a proper target_port_id so let's use the fake one */ 19724d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori memcpy(ids.port_id, hostdata->madapter_info.partition_name, 19734d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori sizeof(ids.port_id)); 1974aebd5e476ecc8ceb53577b20f2a352ff4ceffd8dFUJITA Tomonori ids.roles = SRP_RPORT_ROLE_TARGET; 19754d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori rport = srp_rport_add(host, &ids); 19764d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori if (IS_ERR(rport)) 19774d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori goto add_srp_port_failed; 19784d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try to send an initialization message. Note that this is allowed 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to fail if the other end is not acive. In that case we don't 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * want to scan 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1983d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0 1984cefbda2d6cd9bf78a93768130729a6d142588d67Dave C Boutcher || rc == H_RESOURCE) { 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait around max init_timeout secs for the adapter to finish 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initializing. When we are done initializing, we will have a 19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * valid request_limit. We don't want Linux scanning before 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we are ready. 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (wait_switch = jiffies + (init_timeout * HZ); 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds time_before(jiffies, wait_switch) && 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&hostdata->request_limit) < 2;) { 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if we now have a valid request_limit, initiate a scan */ 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&hostdata->request_limit) > 0) 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_scan_host(host); 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2003559fde706873256903155b3a62b05d0f52d62ab9Greg Kroah-Hartman dev_set_drvdata(&vdev->dev, hostdata); 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20064d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori add_srp_port_failed: 20074d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori scsi_remove_host(hostdata->host); 20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_host_failed: 20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_event_pool(&hostdata->pool, hostdata); 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_pool_failed: 20114f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_events); 20120f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King kill_kthread: 20130f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King kthread_stop(hostdata->work_thread); 20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_crq_failed: 2015126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King unmap_persist_bufs(hostdata); 2016126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King persist_bufs_failed: 20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_host_put(host); 20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_host_alloc_failed: 20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ibmvscsi_remove(struct vio_dev *vdev) 20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2024559fde706873256903155b3a62b05d0f52d62ab9Greg Kroah-Hartman struct ibmvscsi_host_data *hostdata = dev_get_drvdata(&vdev->dev); 2025126c5cc37e682e7c5ae96754994b1cb50c2d0cb5Brian King unmap_persist_bufs(hostdata); 20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_event_pool(&hostdata->pool, hostdata); 2027d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, 20284f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King max_events); 20294d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 20300f33ece5bc3d5a9567b65cfbc736e8f206ecfc7bBrian King kthread_stop(hostdata->work_thread); 20314d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori srp_remove_host(hostdata->host); 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_remove_host(hostdata->host); 20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_host_put(hostdata->host); 20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 203964355b929dec0cb6271e4ac7834c9cf262961e40Brian King * ibmvscsi_resume: Resume from suspend 204064355b929dec0cb6271e4ac7834c9cf262961e40Brian King * @dev: device struct 204164355b929dec0cb6271e4ac7834c9cf262961e40Brian King * 204264355b929dec0cb6271e4ac7834c9cf262961e40Brian King * We may have lost an interrupt across suspend/resume, so kick the 204364355b929dec0cb6271e4ac7834c9cf262961e40Brian King * interrupt handler 204464355b929dec0cb6271e4ac7834c9cf262961e40Brian King */ 204564355b929dec0cb6271e4ac7834c9cf262961e40Brian Kingstatic int ibmvscsi_resume(struct device *dev) 204664355b929dec0cb6271e4ac7834c9cf262961e40Brian King{ 204764355b929dec0cb6271e4ac7834c9cf262961e40Brian King struct ibmvscsi_host_data *hostdata = dev_get_drvdata(dev); 204864355b929dec0cb6271e4ac7834c9cf262961e40Brian King return ibmvscsi_ops->resume(hostdata); 204964355b929dec0cb6271e4ac7834c9cf262961e40Brian King} 205064355b929dec0cb6271e4ac7834c9cf262961e40Brian King 205164355b929dec0cb6271e4ac7834c9cf262961e40Brian King/** 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * support. 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct vio_device_id ibmvscsi_device_table[] __devinitdata = { 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"vscsi", "IBM,v-scsi"}, 2057fb120da678c517f72d4b39932062c2191827b331Stephen Rothwell { "", "" } 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(vio, ibmvscsi_device_table); 2060915124d8114ec8c3825b10a39151bf9e851593bbStephen Rothwell 206164355b929dec0cb6271e4ac7834c9cf262961e40Brian Kingstatic struct dev_pm_ops ibmvscsi_pm_ops = { 206264355b929dec0cb6271e4ac7834c9cf262961e40Brian King .resume = ibmvscsi_resume 206364355b929dec0cb6271e4ac7834c9cf262961e40Brian King}; 206464355b929dec0cb6271e4ac7834c9cf262961e40Brian King 20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct vio_driver ibmvscsi_driver = { 20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = ibmvscsi_device_table, 20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = ibmvscsi_probe, 20686fdf5392caa4c3cba65add0a4beec9f5eb96b723Stephen Rothwell .remove = ibmvscsi_remove, 20697912a0ac5907df1f8b214b3ca15ccf96129daae0Robert Jennings .get_desired_dma = ibmvscsi_get_desired_dma, 20706fdf5392caa4c3cba65add0a4beec9f5eb96b723Stephen Rothwell .driver = { 20716fdf5392caa4c3cba65add0a4beec9f5eb96b723Stephen Rothwell .name = "ibmvscsi", 2072915124d8114ec8c3825b10a39151bf9e851593bbStephen Rothwell .owner = THIS_MODULE, 207364355b929dec0cb6271e4ac7834c9cf262961e40Brian King .pm = &ibmvscsi_pm_ops, 20746fdf5392caa4c3cba65add0a4beec9f5eb96b723Stephen Rothwell } 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20774d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonoristatic struct srp_function_template ibmvscsi_transport_functions = { 20784d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori}; 20794d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init ibmvscsi_module_init(void) 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20824d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori int ret; 20834d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 20844f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King /* Ensure we have two requests to do error recovery */ 20854f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King driver_template.can_queue = max_requests; 20864f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King max_events = max_requests + 2; 20874f10aae0d1a285df6b16bf6ca5abd366140fd371Brian King 2088d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse if (firmware_has_feature(FW_FEATURE_ISERIES)) 2089d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse ibmvscsi_ops = &iseriesvscsi_ops; 2090d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse else if (firmware_has_feature(FW_FEATURE_VIO)) 2091d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse ibmvscsi_ops = &rpavscsi_ops; 2092d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse else 2093d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse return -ENODEV; 2094d3849d512fb0ca1e369e3efcaec910a949f55f62David Woodhouse 20954d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori ibmvscsi_transport_template = 20964d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori srp_attach_transport(&ibmvscsi_transport_functions); 20974d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori if (!ibmvscsi_transport_template) 20984d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori return -ENOMEM; 20994d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori 21004d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori ret = vio_register_driver(&ibmvscsi_driver); 21014d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori if (ret) 21024d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori srp_release_transport(ibmvscsi_transport_template); 21034d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori return ret; 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __exit ibmvscsi_module_exit(void) 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vio_unregister_driver(&ibmvscsi_driver); 21094d68041907b150b07640b607c6c626391cf3fe8bFUJITA Tomonori srp_release_transport(ibmvscsi_transport_template); 21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(ibmvscsi_module_init); 21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(ibmvscsi_module_exit); 2114