blob: 727d0225b7d049e9f529655c081c513267d248bc [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Mike Millerbd4f36d2007-10-24 10:30:34 +02002 * Disk Array driver for HP Smart Array controllers, SCSI Tape module.
3 * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
Mike Millerbd4f36d2007-10-24 10:30:34 +02007 * the Free Software Foundation; version 2 of the License.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Mike Millerbd4f36d2007-10-24 10:30:34 +020011 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
Mike Millerbd4f36d2007-10-24 10:30:34 +020016 * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA
17 * 02111-1307, USA.
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 *
19 * Questions/Comments/Bugfixes to iss_storagedev@hp.com
20 *
21 * Author: Stephen M. Cameron
22 */
23#ifdef CONFIG_CISS_SCSI_TAPE
24
25/* Here we have code to present the driver as a scsi driver
26 as it is simultaneously presented as a block driver. The
27 reason for doing this is to allow access to SCSI tape drives
28 through the array controller. Note in particular, neither
29 physical nor logical disks are presented through the scsi layer. */
30
Tim Schmielau4e57b682005-10-30 15:03:48 -080031#include <linux/timer.h>
32#include <linux/completion.h>
33#include <linux/slab.h>
34#include <linux/string.h>
35
36#include <asm/atomic.h>
37
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <scsi/scsi_cmnd.h>
39#include <scsi/scsi_device.h>
40#include <scsi/scsi_host.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#include "cciss_scsi.h"
43
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060044#define CCISS_ABORT_MSG 0x00
45#define CCISS_RESET_MSG 0x01
46
Stephen M. Cameronf70dba82010-07-19 13:46:38 -050047static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +020048 size_t size,
scameron@beardog.cca.cpqcorp.netb57695f2009-06-08 16:02:17 -050049 __u8 page_code, unsigned char *scsi3addr,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +020050 int cmd_type);
51
Stephen M. Cameron6b4d96b2010-07-19 13:46:43 -050052static CommandList_struct *cmd_alloc(ctlr_info_t *h);
53static CommandList_struct *cmd_special_alloc(ctlr_info_t *h);
54static void cmd_free(ctlr_info_t *h, CommandList_struct *c);
55static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57static int cciss_scsi_proc_info(
58 struct Scsi_Host *sh,
59 char *buffer, /* data buffer */
60 char **start, /* where data in buffer starts */
61 off_t offset, /* offset from start of imaginary file */
62 int length, /* length of data in buffer */
63 int func); /* 0 == read, 1 == write */
64
Jeff Garzikf2812332010-11-16 02:10:29 -050065static int cciss_scsi_queue_command (struct Scsi_Host *h,
66 struct scsi_cmnd *cmd);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060067static int cciss_eh_device_reset_handler(struct scsi_cmnd *);
68static int cciss_eh_abort_handler(struct scsi_cmnd *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
70static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = {
71 { .name = "cciss0", .ndevices = 0 },
72 { .name = "cciss1", .ndevices = 0 },
73 { .name = "cciss2", .ndevices = 0 },
74 { .name = "cciss3", .ndevices = 0 },
75 { .name = "cciss4", .ndevices = 0 },
76 { .name = "cciss5", .ndevices = 0 },
77 { .name = "cciss6", .ndevices = 0 },
78 { .name = "cciss7", .ndevices = 0 },
79};
80
81static struct scsi_host_template cciss_driver_template = {
82 .module = THIS_MODULE,
83 .name = "cciss",
84 .proc_name = "cciss",
85 .proc_info = cciss_scsi_proc_info,
86 .queuecommand = cciss_scsi_queue_command,
87 .can_queue = SCSI_CCISS_CAN_QUEUE,
88 .this_id = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 .cmd_per_lun = 1,
90 .use_clustering = DISABLE_CLUSTERING,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060091 /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */
92 .eh_device_reset_handler= cciss_eh_device_reset_handler,
93 .eh_abort_handler = cciss_eh_abort_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -070094};
95
96#pragma pack(1)
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -060097
Mike Miller5e216152010-06-02 12:58:06 -070098#define SCSI_PAD_32 8
99#define SCSI_PAD_64 8
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101struct cciss_scsi_cmd_stack_elem_t {
102 CommandList_struct cmd;
103 ErrorInfo_struct Err;
104 __u32 busaddr;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600105 int cmdindex;
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600106 u8 pad[IS_32_BIT * SCSI_PAD_32 + IS_64_BIT * SCSI_PAD_64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107};
108
109#pragma pack()
110
111#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \
112 CCISS_MAX_SCSI_DEVS_PER_HBA + 2)
113 // plus two for init time usage
114
115#pragma pack(1)
116struct cciss_scsi_cmd_stack_t {
117 struct cciss_scsi_cmd_stack_elem_t *pool;
118 struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE];
119 dma_addr_t cmd_pool_handle;
120 int top;
121};
122#pragma pack()
123
124struct cciss_scsi_adapter_data_t {
125 struct Scsi_Host *scsi_host;
126 struct cciss_scsi_cmd_stack_t cmd_stack;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600127 SGDescriptor_struct **cmd_sg_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 int registered;
129 spinlock_t lock; // to protect ccissscsi[ctlr];
130};
131
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500132#define CPQ_TAPE_LOCK(h, flags) spin_lock_irqsave( \
133 &h->scsi_ctlr->lock, flags);
134#define CPQ_TAPE_UNLOCK(h, flags) spin_unlock_irqrestore( \
135 &h->scsi_ctlr->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
137static CommandList_struct *
138scsi_cmd_alloc(ctlr_info_t *h)
139{
140 /* assume only one process in here at a time, locking done by caller. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500141 /* use h->lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 /* might be better to rewrite how we allocate scsi commands in a way that */
143 /* needs no locking at all. */
144
145 /* take the top memory chunk off the stack and return it, if any. */
146 struct cciss_scsi_cmd_stack_elem_t *c;
147 struct cciss_scsi_adapter_data_t *sa;
148 struct cciss_scsi_cmd_stack_t *stk;
149 u64bit temp64;
150
Stephen M. Cameronaad9fb62010-02-26 16:01:42 -0600151 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 stk = &sa->cmd_stack;
153
154 if (stk->top < 0)
155 return NULL;
156 c = stk->elem[stk->top];
157 /* memset(c, 0, sizeof(*c)); */
158 memset(&c->cmd, 0, sizeof(c->cmd));
159 memset(&c->Err, 0, sizeof(c->Err));
160 /* set physical addr of cmd and addr of scsi parameters */
161 c->cmd.busaddr = c->busaddr;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600162 c->cmd.cmdindex = c->cmdindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 /* (__u32) (stk->cmd_pool_handle +
164 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top)); */
165
166 temp64.val = (__u64) (c->busaddr + sizeof(CommandList_struct));
167 /* (__u64) (stk->cmd_pool_handle +
168 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top) +
169 sizeof(CommandList_struct)); */
170 stk->top--;
171 c->cmd.ErrDesc.Addr.lower = temp64.val32.lower;
172 c->cmd.ErrDesc.Addr.upper = temp64.val32.upper;
173 c->cmd.ErrDesc.Len = sizeof(ErrorInfo_struct);
174
175 c->cmd.ctlr = h->ctlr;
176 c->cmd.err_info = &c->Err;
177
178 return (CommandList_struct *) c;
179}
180
181static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500182scsi_cmd_free(ctlr_info_t *h, CommandList_struct *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183{
184 /* assume only one process in here at a time, locking done by caller. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500185 /* use h->lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 /* drop the free memory chunk on top of the stack. */
187
188 struct cciss_scsi_adapter_data_t *sa;
189 struct cciss_scsi_cmd_stack_t *stk;
190
Stephen M. Cameronaad9fb62010-02-26 16:01:42 -0600191 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 stk = &sa->cmd_stack;
Dan Carpenter713b6862010-06-01 12:17:48 +0200193 stk->top++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 if (stk->top >= CMD_STACK_SIZE) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500195 dev_err(&h->pdev->dev,
196 "scsi_cmd_free called too many times.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 BUG();
198 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500199 stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200}
201
202static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500203scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204{
205 int i;
206 struct cciss_scsi_cmd_stack_t *stk;
207 size_t size;
208
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500209 sa->cmd_sg_list = cciss_allocate_sg_chain_blocks(h,
210 h->chainsize, CMD_STACK_SIZE);
211 if (!sa->cmd_sg_list && h->chainsize > 0)
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600212 return -ENOMEM;
213
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 stk = &sa->cmd_stack;
215 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
216
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600217 /* Check alignment, see cciss_cmd.h near CommandList_struct def. */
218 BUILD_BUG_ON((sizeof(*stk->pool) % COMMANDLIST_ALIGNMENT) != 0);
219 /* pci_alloc_consistent guarantees 32-bit DMA address will be used */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 stk->pool = (struct cciss_scsi_cmd_stack_elem_t *)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500221 pci_alloc_consistent(h->pdev, size, &stk->cmd_pool_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
223 if (stk->pool == NULL) {
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600224 cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE);
225 sa->cmd_sg_list = NULL;
226 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 }
228
229 for (i=0; i<CMD_STACK_SIZE; i++) {
230 stk->elem[i] = &stk->pool[i];
231 stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle +
232 (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i));
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600233 stk->elem[i]->cmdindex = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 }
235 stk->top = CMD_STACK_SIZE-1;
236 return 0;
237}
238
239static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500240scsi_cmd_stack_free(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241{
242 struct cciss_scsi_adapter_data_t *sa;
243 struct cciss_scsi_cmd_stack_t *stk;
244 size_t size;
245
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500246 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 stk = &sa->cmd_stack;
248 if (stk->top != CMD_STACK_SIZE-1) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500249 dev_warn(&h->pdev->dev,
250 "bug: %d scsi commands are still outstanding.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 CMD_STACK_SIZE - stk->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 }
253 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
254
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500255 pci_free_consistent(h->pdev, size, stk->pool, stk->cmd_pool_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 stk->pool = NULL;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600257 cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258}
259
Grant Coady400bb232005-11-15 00:09:20 -0800260#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261static int xmargin=8;
262static int amargin=60;
263
264static void
265print_bytes (unsigned char *c, int len, int hex, int ascii)
266{
267
268 int i;
269 unsigned char *x;
270
271 if (hex)
272 {
273 x = c;
274 for (i=0;i<len;i++)
275 {
276 if ((i % xmargin) == 0 && i>0) printk("\n");
277 if ((i % xmargin) == 0) printk("0x%04x:", i);
278 printk(" %02x", *x);
279 x++;
280 }
281 printk("\n");
282 }
283 if (ascii)
284 {
285 x = c;
286 for (i=0;i<len;i++)
287 {
288 if ((i % amargin) == 0 && i>0) printk("\n");
289 if ((i % amargin) == 0) printk("0x%04x:", i);
290 if (*x > 26 && *x < 128) printk("%c", *x);
291 else printk(".");
292 x++;
293 }
294 printk("\n");
295 }
296}
297
298static void
299print_cmd(CommandList_struct *cp)
300{
301 printk("queue:%d\n", cp->Header.ReplyQueue);
302 printk("sglist:%d\n", cp->Header.SGList);
303 printk("sgtot:%d\n", cp->Header.SGTotal);
304 printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper,
305 cp->Header.Tag.lower);
306 printk("LUN:0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
307 cp->Header.LUN.LunAddrBytes[0],
308 cp->Header.LUN.LunAddrBytes[1],
309 cp->Header.LUN.LunAddrBytes[2],
310 cp->Header.LUN.LunAddrBytes[3],
311 cp->Header.LUN.LunAddrBytes[4],
312 cp->Header.LUN.LunAddrBytes[5],
313 cp->Header.LUN.LunAddrBytes[6],
314 cp->Header.LUN.LunAddrBytes[7]);
315 printk("CDBLen:%d\n", cp->Request.CDBLen);
316 printk("Type:%d\n",cp->Request.Type.Type);
317 printk("Attr:%d\n",cp->Request.Type.Attribute);
318 printk(" Dir:%d\n",cp->Request.Type.Direction);
319 printk("Timeout:%d\n",cp->Request.Timeout);
320 printk( "CDB: %02x %02x %02x %02x %02x %02x %02x %02x"
321 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
322 cp->Request.CDB[0], cp->Request.CDB[1],
323 cp->Request.CDB[2], cp->Request.CDB[3],
324 cp->Request.CDB[4], cp->Request.CDB[5],
325 cp->Request.CDB[6], cp->Request.CDB[7],
326 cp->Request.CDB[8], cp->Request.CDB[9],
327 cp->Request.CDB[10], cp->Request.CDB[11],
328 cp->Request.CDB[12], cp->Request.CDB[13],
329 cp->Request.CDB[14], cp->Request.CDB[15]),
330 printk("edesc.Addr: 0x%08x/0%08x, Len = %d\n",
331 cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower,
332 cp->ErrDesc.Len);
333 printk("sgs..........Errorinfo:\n");
334 printk("scsistatus:%d\n", cp->err_info->ScsiStatus);
335 printk("senselen:%d\n", cp->err_info->SenseLen);
336 printk("cmd status:%d\n", cp->err_info->CommandStatus);
337 printk("resid cnt:%d\n", cp->err_info->ResidualCnt);
338 printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size);
339 printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num);
340 printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
341
342}
343
344#endif
345
346static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500347find_bus_target_lun(ctlr_info_t *h, int *bus, int *target, int *lun)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
349 /* finds an unused bus, target, lun for a new device */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500350 /* assumes h->scsi_ctlr->lock is held */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 int i, found=0;
352 unsigned char target_taken[CCISS_MAX_SCSI_DEVS_PER_HBA];
353
354 memset(&target_taken[0], 0, CCISS_MAX_SCSI_DEVS_PER_HBA);
355
356 target_taken[SELF_SCSI_ID] = 1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500357 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++)
358 target_taken[ccissscsi[h->ctlr].dev[i].target] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500360 for (i = 0; i < CCISS_MAX_SCSI_DEVS_PER_HBA; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 if (!target_taken[i]) {
362 *bus = 0; *target=i; *lun = 0; found=1;
363 break;
364 }
365 }
366 return (!found);
367}
Mike Millerf4a93bc2008-08-04 11:54:53 +0200368struct scsi2map {
369 char scsi3addr[8];
370 int bus, target, lun;
371};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
373static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500374cciss_scsi_add_entry(ctlr_info_t *h, int hostno,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700375 struct cciss_scsi_dev_t *device,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200376 struct scsi2map *added, int *nadded)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500378 /* assumes h->scsi_ctlr->lock is held */
379 int n = ccissscsi[h->ctlr].ndevices;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 struct cciss_scsi_dev_t *sd;
Mike Miller935dc8d2008-08-04 11:54:54 +0200381 int i, bus, target, lun;
382 unsigned char addr1[8], addr2[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
384 if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500385 dev_warn(&h->pdev->dev, "Too many devices, "
386 "some will be inaccessible.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 return -1;
388 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200389
Mike Miller935dc8d2008-08-04 11:54:54 +0200390 bus = target = -1;
391 lun = 0;
392 /* Is this device a non-zero lun of a multi-lun device */
393 /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700394 if (device->scsi3addr[4] != 0) {
Mike Miller935dc8d2008-08-04 11:54:54 +0200395 /* Search through our list and find the device which */
396 /* has the same 8 byte LUN address, excepting byte 4. */
397 /* Assign the same bus and target for this new LUN. */
398 /* Use the logical unit number from the firmware. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700399 memcpy(addr1, device->scsi3addr, 8);
Mike Miller935dc8d2008-08-04 11:54:54 +0200400 addr1[4] = 0;
401 for (i = 0; i < n; i++) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500402 sd = &ccissscsi[h->ctlr].dev[i];
Mike Miller935dc8d2008-08-04 11:54:54 +0200403 memcpy(addr2, sd->scsi3addr, 8);
404 addr2[4] = 0;
405 /* differ only in byte 4? */
406 if (memcmp(addr1, addr2, 8) == 0) {
407 bus = sd->bus;
408 target = sd->target;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700409 lun = device->scsi3addr[4];
Mike Miller935dc8d2008-08-04 11:54:54 +0200410 break;
411 }
412 }
413 }
414
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500415 sd = &ccissscsi[h->ctlr].dev[n];
Mike Miller935dc8d2008-08-04 11:54:54 +0200416 if (lun == 0) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500417 if (find_bus_target_lun(h,
Mike Miller935dc8d2008-08-04 11:54:54 +0200418 &sd->bus, &sd->target, &sd->lun) != 0)
419 return -1;
420 } else {
421 sd->bus = bus;
422 sd->target = target;
423 sd->lun = lun;
424 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200425 added[*nadded].bus = sd->bus;
426 added[*nadded].target = sd->target;
427 added[*nadded].lun = sd->lun;
428 (*nadded)++;
429
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700430 memcpy(sd->scsi3addr, device->scsi3addr, 8);
431 memcpy(sd->vendor, device->vendor, sizeof(sd->vendor));
432 memcpy(sd->revision, device->revision, sizeof(sd->revision));
433 memcpy(sd->device_id, device->device_id, sizeof(sd->device_id));
434 sd->devtype = device->devtype;
435
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500436 ccissscsi[h->ctlr].ndevices++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
438 /* initially, (before registering with scsi layer) we don't
439 know our hostno and we don't want to print anything first
440 time anyway (the scsi layer's inquiries will show that info) */
441 if (hostno != -1)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500442 dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d added.\n",
443 scsi_device_type(sd->devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 sd->bus, sd->target, sd->lun);
445 return 0;
446}
447
448static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500449cciss_scsi_remove_entry(ctlr_info_t *h, int hostno, int entry,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200450 struct scsi2map *removed, int *nremoved)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500452 /* assumes h->ctlr]->scsi_ctlr->lock is held */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 int i;
454 struct cciss_scsi_dev_t sd;
455
456 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500457 sd = ccissscsi[h->ctlr].dev[entry];
Mike Millerf4a93bc2008-08-04 11:54:53 +0200458 removed[*nremoved].bus = sd.bus;
459 removed[*nremoved].target = sd.target;
460 removed[*nremoved].lun = sd.lun;
461 (*nremoved)++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500462 for (i = entry; i < ccissscsi[h->ctlr].ndevices-1; i++)
463 ccissscsi[h->ctlr].dev[i] = ccissscsi[h->ctlr].dev[i+1];
464 ccissscsi[h->ctlr].ndevices--;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500465 dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d removed.\n",
466 scsi_device_type(sd.devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 sd.bus, sd.target, sd.lun);
468}
469
470
471#define SCSI3ADDR_EQ(a,b) ( \
472 (a)[7] == (b)[7] && \
473 (a)[6] == (b)[6] && \
474 (a)[5] == (b)[5] && \
475 (a)[4] == (b)[4] && \
476 (a)[3] == (b)[3] && \
477 (a)[2] == (b)[2] && \
478 (a)[1] == (b)[1] && \
479 (a)[0] == (b)[0])
480
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500481static void fixup_botched_add(ctlr_info_t *h, char *scsi3addr)
Mike Millerf4a93bc2008-08-04 11:54:53 +0200482{
483 /* called when scsi_add_device fails in order to re-adjust */
484 /* ccissscsi[] to match the mid layer's view. */
485 unsigned long flags;
486 int i, j;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500487 CPQ_TAPE_LOCK(h, flags);
488 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
Mike Millerf4a93bc2008-08-04 11:54:53 +0200489 if (memcmp(scsi3addr,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500490 ccissscsi[h->ctlr].dev[i].scsi3addr, 8) == 0) {
491 for (j = i; j < ccissscsi[h->ctlr].ndevices-1; j++)
492 ccissscsi[h->ctlr].dev[j] =
493 ccissscsi[h->ctlr].dev[j+1];
494 ccissscsi[h->ctlr].ndevices--;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200495 break;
496 }
497 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500498 CPQ_TAPE_UNLOCK(h, flags);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200499}
500
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700501static int device_is_the_same(struct cciss_scsi_dev_t *dev1,
502 struct cciss_scsi_dev_t *dev2)
503{
504 return dev1->devtype == dev2->devtype &&
505 memcmp(dev1->scsi3addr, dev2->scsi3addr,
506 sizeof(dev1->scsi3addr)) == 0 &&
507 memcmp(dev1->device_id, dev2->device_id,
508 sizeof(dev1->device_id)) == 0 &&
509 memcmp(dev1->vendor, dev2->vendor,
510 sizeof(dev1->vendor)) == 0 &&
511 memcmp(dev1->model, dev2->model,
512 sizeof(dev1->model)) == 0 &&
513 memcmp(dev1->revision, dev2->revision,
514 sizeof(dev1->revision)) == 0;
515}
516
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500518adjust_cciss_scsi_table(ctlr_info_t *h, int hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 struct cciss_scsi_dev_t sd[], int nsds)
520{
521 /* sd contains scsi3 addresses and devtypes, but
522 bus target and lun are not filled in. This funciton
523 takes what's in sd to be the current and adjusts
524 ccissscsi[] to be in line with what's in sd. */
525
526 int i,j, found, changes=0;
527 struct cciss_scsi_dev_t *csd;
528 unsigned long flags;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200529 struct scsi2map *added, *removed;
530 int nadded, nremoved;
531 struct Scsi_Host *sh = NULL;
532
533 added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA,
534 GFP_KERNEL);
535 removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA,
536 GFP_KERNEL);
537
538 if (!added || !removed) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500539 dev_warn(&h->pdev->dev,
540 "Out of memory in adjust_cciss_scsi_table\n");
Mike Millerf4a93bc2008-08-04 11:54:53 +0200541 goto free_and_out;
542 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500544 CPQ_TAPE_LOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
Mike Millerf4a93bc2008-08-04 11:54:53 +0200546 if (hostno != -1) /* if it's not the first time... */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500547 sh = h->scsi_ctlr->scsi_host;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200548
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 /* find any devices in ccissscsi[] that are not in
550 sd[] and remove them from ccissscsi[] */
551
552 i = 0;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200553 nremoved = 0;
554 nadded = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500555 while (i < ccissscsi[h->ctlr].ndevices) {
556 csd = &ccissscsi[h->ctlr].dev[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 found=0;
558 for (j=0;j<nsds;j++) {
559 if (SCSI3ADDR_EQ(sd[j].scsi3addr,
560 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700561 if (device_is_the_same(&sd[j], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 found=2;
563 else
564 found=1;
565 break;
566 }
567 }
568
569 if (found == 0) { /* device no longer present. */
570 changes++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500571 cciss_scsi_remove_entry(h, hostno, i,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200572 removed, &nremoved);
573 /* remove ^^^, hence i not incremented */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700574 } else if (found == 1) { /* device is different in some way */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 changes++;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500576 dev_info(&h->pdev->dev,
577 "device c%db%dt%dl%d has changed.\n",
578 hostno, csd->bus, csd->target, csd->lun);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500579 cciss_scsi_remove_entry(h, hostno, i,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200580 removed, &nremoved);
581 /* remove ^^^, hence i not incremented */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500582 if (cciss_scsi_add_entry(h, hostno, &sd[j],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200583 added, &nadded) != 0)
584 /* we just removed one, so add can't fail. */
585 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 csd->devtype = sd[j].devtype;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700587 memcpy(csd->device_id, sd[j].device_id,
588 sizeof(csd->device_id));
589 memcpy(csd->vendor, sd[j].vendor,
590 sizeof(csd->vendor));
591 memcpy(csd->model, sd[j].model,
592 sizeof(csd->model));
593 memcpy(csd->revision, sd[j].revision,
594 sizeof(csd->revision));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 } else /* device is same as it ever was, */
596 i++; /* so just move along. */
597 }
598
599 /* Now, make sure every device listed in sd[] is also
600 listed in ccissscsi[], adding them if they aren't found */
601
602 for (i=0;i<nsds;i++) {
603 found=0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500604 for (j = 0; j < ccissscsi[h->ctlr].ndevices; j++) {
605 csd = &ccissscsi[h->ctlr].dev[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 if (SCSI3ADDR_EQ(sd[i].scsi3addr,
607 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700608 if (device_is_the_same(&sd[i], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 found=2; /* found device */
610 else
611 found=1; /* found a bug. */
612 break;
613 }
614 }
615 if (!found) {
616 changes++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500617 if (cciss_scsi_add_entry(h, hostno, &sd[i],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200618 added, &nadded) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 break;
620 } else if (found == 1) {
621 /* should never happen... */
622 changes++;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500623 dev_warn(&h->pdev->dev,
624 "device unexpectedly changed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 /* but if it does happen, we just ignore that device */
626 }
627 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500628 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
Mike Millerf4a93bc2008-08-04 11:54:53 +0200630 /* Don't notify scsi mid layer of any changes the first time through */
631 /* (or if there are no changes) scsi_scan_host will do it later the */
632 /* first time through. */
633 if (hostno == -1 || !changes)
634 goto free_and_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Mike Millerf4a93bc2008-08-04 11:54:53 +0200636 /* Notify scsi mid layer of any removed devices */
637 for (i = 0; i < nremoved; i++) {
638 struct scsi_device *sdev =
639 scsi_device_lookup(sh, removed[i].bus,
640 removed[i].target, removed[i].lun);
641 if (sdev != NULL) {
642 scsi_remove_device(sdev);
643 scsi_device_put(sdev);
644 } else {
645 /* We don't expect to get here. */
646 /* future cmds to this device will get selection */
647 /* timeout as if the device was gone. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500648 dev_warn(&h->pdev->dev, "didn't find "
Mike Millerf4a93bc2008-08-04 11:54:53 +0200649 "c%db%dt%dl%d\n for removal.",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500650 hostno, removed[i].bus,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200651 removed[i].target, removed[i].lun);
652 }
653 }
654
655 /* Notify scsi mid layer of any added devices */
656 for (i = 0; i < nadded; i++) {
657 int rc;
658 rc = scsi_add_device(sh, added[i].bus,
659 added[i].target, added[i].lun);
660 if (rc == 0)
661 continue;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500662 dev_warn(&h->pdev->dev, "scsi_add_device "
Mike Millerf4a93bc2008-08-04 11:54:53 +0200663 "c%db%dt%dl%d failed, device not added.\n",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500664 hostno, added[i].bus, added[i].target, added[i].lun);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200665 /* now we have to remove it from ccissscsi, */
666 /* since it didn't get added to scsi mid layer */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500667 fixup_botched_add(h, added[i].scsi3addr);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200668 }
669
670free_and_out:
671 kfree(added);
672 kfree(removed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 return 0;
674}
675
676static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500677lookup_scsi3addr(ctlr_info_t *h, int bus, int target, int lun, char *scsi3addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678{
679 int i;
680 struct cciss_scsi_dev_t *sd;
681 unsigned long flags;
682
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500683 CPQ_TAPE_LOCK(h, flags);
684 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
685 sd = &ccissscsi[h->ctlr].dev[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 if (sd->bus == bus &&
687 sd->target == target &&
688 sd->lun == lun) {
689 memcpy(scsi3addr, &sd->scsi3addr[0], 8);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500690 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 return 0;
692 }
693 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500694 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 return -1;
696}
697
698static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500699cciss_scsi_setup(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
701 struct cciss_scsi_adapter_data_t * shba;
702
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500703 ccissscsi[h->ctlr].ndevices = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 shba = (struct cciss_scsi_adapter_data_t *)
705 kmalloc(sizeof(*shba), GFP_KERNEL);
706 if (shba == NULL)
707 return;
708 shba->scsi_host = NULL;
709 spin_lock_init(&shba->lock);
710 shba->registered = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500711 if (scsi_cmd_stack_setup(h, shba) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 kfree(shba);
713 shba = NULL;
714 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500715 h->scsi_ctlr = shba;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 return;
717}
718
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500719static void complete_scsi_command(CommandList_struct *c, int timeout,
720 __u32 tag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721{
722 struct scsi_cmnd *cmd;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500723 ctlr_info_t *h;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 ErrorInfo_struct *ei;
725
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500726 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727
728 /* First, see if it was a message rather than a command */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500729 if (c->Request.Type.Type == TYPE_MSG) {
730 c->cmd_type = CMD_MSG_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 return;
732 }
733
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500734 cmd = (struct scsi_cmnd *) c->scsi_cmd;
735 h = hba[c->ctlr];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900737 scsi_dma_unmap(cmd);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500738 if (c->Header.SGTotal > h->max_cmd_sgentries)
739 cciss_unmap_sg_chain_block(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
741 cmd->result = (DID_OK << 16); /* host byte */
742 cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
743 /* cmd->result |= (GOOD < 1); */ /* status byte */
744
745 cmd->result |= (ei->ScsiStatus);
746 /* printk("Scsistatus is 0x%02x\n", ei->ScsiStatus); */
747
748 /* copy the sense data whether we need to or not. */
749
750 memcpy(cmd->sense_buffer, ei->SenseInfo,
751 ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
752 SCSI_SENSE_BUFFERSIZE :
753 ei->SenseLen);
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900754 scsi_set_resid(cmd, ei->ResidualCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
756 if(ei->CommandStatus != 0)
757 { /* an error has occurred */
758 switch(ei->CommandStatus)
759 {
760 case CMD_TARGET_STATUS:
761 /* Pass it up to the upper layers... */
762 if( ei->ScsiStatus)
763 {
764#if 0
765 printk(KERN_WARNING "cciss: cmd %p "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500766 "has SCSI Status = %x\n",
767 c, ei->ScsiStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768#endif
Stephen M. Cameronb0e15f62009-11-12 12:49:45 -0600769 cmd->result |= (ei->ScsiStatus << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 }
771 else { /* scsi status is zero??? How??? */
772
773 /* Ordinarily, this case should never happen, but there is a bug
774 in some released firmware revisions that allows it to happen
775 if, for example, a 4100 backplane loses power and the tape
776 drive is in it. We assume that it's a fatal error of some
777 kind because we can't show that it wasn't. We will make it
778 look like selection timeout since that is the most common
779 reason for this to occur, and it's severe enough. */
780
781 cmd->result = DID_NO_CONNECT << 16;
782 }
783 break;
784 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
785 break;
786 case CMD_DATA_OVERRUN:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500787 dev_warn(&h->pdev->dev, "%p has"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 " completed with data overrun "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500789 "reported\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 break;
791 case CMD_INVALID: {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500792 /* print_bytes(c, sizeof(*c), 1, 0);
793 print_cmd(c); */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 /* We get CMD_INVALID if you address a non-existent tape drive instead
795 of a selection timeout (no response). You will see this if you yank
796 out a tape drive, then try to access it. This is kind of a shame
797 because it means that any other CMD_INVALID (e.g. driver bug) will
798 get interpreted as a missing target. */
799 cmd->result = DID_NO_CONNECT << 16;
800 }
801 break;
802 case CMD_PROTOCOL_ERR:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500803 dev_warn(&h->pdev->dev,
804 "%p has protocol error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 break;
806 case CMD_HARDWARE_ERR:
807 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500808 dev_warn(&h->pdev->dev,
809 "%p had hardware error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 break;
811 case CMD_CONNECTION_LOST:
812 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500813 dev_warn(&h->pdev->dev,
814 "%p had connection lost\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 break;
816 case CMD_ABORTED:
817 cmd->result = DID_ABORT << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500818 dev_warn(&h->pdev->dev, "%p was aborted\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 break;
820 case CMD_ABORT_FAILED:
821 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500822 dev_warn(&h->pdev->dev,
823 "%p reports abort failed\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 break;
825 case CMD_UNSOLICITED_ABORT:
826 cmd->result = DID_ABORT << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500827 dev_warn(&h->pdev->dev, "%p aborted do to an "
828 "unsolicited abort\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 break;
830 case CMD_TIMEOUT:
831 cmd->result = DID_TIME_OUT << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500832 dev_warn(&h->pdev->dev, "%p timedout\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 break;
834 default:
835 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500836 dev_warn(&h->pdev->dev,
837 "%p returned unknown status %x\n", c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 ei->CommandStatus);
839 }
840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 cmd->scsi_done(cmd);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500842 scsi_cmd_free(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843}
844
845static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500846cciss_scsi_detect(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847{
848 struct Scsi_Host *sh;
849 int error;
850
851 sh = scsi_host_alloc(&cciss_driver_template, sizeof(struct ctlr_info *));
852 if (sh == NULL)
853 goto fail;
854 sh->io_port = 0; // good enough? FIXME,
855 sh->n_io_port = 0; // I don't think we use these two...
856 sh->this_id = SELF_SCSI_ID;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500857 sh->sg_tablesize = h->maxsgentries;
Stephen M. Cameron79600aa2010-06-15 08:12:34 +0200858 sh->max_cmd_len = MAX_COMMAND_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
860 ((struct cciss_scsi_adapter_data_t *)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500861 h->scsi_ctlr)->scsi_host = sh;
862 sh->hostdata[0] = (unsigned long) h;
863 sh->irq = h->intr[SIMPLE_MODE_INT];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 sh->unique_id = sh->irq;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500865 error = scsi_add_host(sh, &h->pdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 if (error)
867 goto fail_host_put;
868 scsi_scan_host(sh);
869 return 1;
870
871 fail_host_put:
872 scsi_host_put(sh);
873 fail:
874 return 0;
875}
876
877static void
878cciss_unmap_one(struct pci_dev *pdev,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500879 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 size_t buflen,
881 int data_direction)
882{
883 u64bit addr64;
884
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500885 addr64.val32.lower = c->SG[0].Addr.lower;
886 addr64.val32.upper = c->SG[0].Addr.upper;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 pci_unmap_single(pdev, (dma_addr_t) addr64.val, buflen, data_direction);
888}
889
890static void
891cciss_map_one(struct pci_dev *pdev,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500892 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 unsigned char *buf,
894 size_t buflen,
895 int data_direction)
896{
897 __u64 addr64;
898
899 addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500900 c->SG[0].Addr.lower =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500902 c->SG[0].Addr.upper =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500904 c->SG[0].Len = buflen;
905 c->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */
906 c->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907}
908
909static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500910cciss_scsi_do_simple_cmd(ctlr_info_t *h,
911 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 unsigned char *scsi3addr,
913 unsigned char *cdb,
914 unsigned char cdblen,
915 unsigned char *buf, int bufsize,
916 int direction)
917{
Peter Zijlstra6e9a4732006-09-30 23:28:10 -0700918 DECLARE_COMPLETION_ONSTACK(wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500920 c->cmd_type = CMD_IOCTL_PEND; /* treat this like an ioctl */
921 c->scsi_cmd = NULL;
922 c->Header.ReplyQueue = 0; /* unused in simple mode */
923 memcpy(&c->Header.LUN, scsi3addr, sizeof(c->Header.LUN));
924 c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 // Fill in the request block...
926
927 /* printk("Using scsi3addr 0x%02x%0x2%0x2%0x2%0x2%0x2%0x2%0x2\n",
928 scsi3addr[0], scsi3addr[1], scsi3addr[2], scsi3addr[3],
929 scsi3addr[4], scsi3addr[5], scsi3addr[6], scsi3addr[7]); */
930
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500931 memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
932 memcpy(c->Request.CDB, cdb, cdblen);
933 c->Request.Timeout = 0;
934 c->Request.CDBLen = cdblen;
935 c->Request.Type.Type = TYPE_CMD;
936 c->Request.Type.Attribute = ATTR_SIMPLE;
937 c->Request.Type.Direction = direction;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
939 /* Fill in the SG list and do dma mapping */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500940 cciss_map_one(h->pdev, c, (unsigned char *) buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 bufsize, DMA_FROM_DEVICE);
942
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500943 c->waiting = &wait;
944 enqueue_cmd_and_start_io(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 wait_for_completion(&wait);
946
947 /* undo the dma mapping */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500948 cciss_unmap_one(h->pdev, c, bufsize, DMA_FROM_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 return(0);
950}
951
952static void
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500953cciss_scsi_interpret_error(ctlr_info_t *h, CommandList_struct *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954{
955 ErrorInfo_struct *ei;
956
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500957 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 switch(ei->CommandStatus)
959 {
960 case CMD_TARGET_STATUS:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500961 dev_warn(&h->pdev->dev,
962 "cmd %p has completed with errors\n", c);
963 dev_warn(&h->pdev->dev,
964 "cmd %p has SCSI Status = %x\n",
965 c, ei->ScsiStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 if (ei->ScsiStatus == 0)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500967 dev_warn(&h->pdev->dev,
968 "SCSI status is abnormally zero. "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 "(probably indicates selection timeout "
970 "reported incorrectly due to a known "
971 "firmware bug, circa July, 2001.)\n");
972 break;
973 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500974 dev_info(&h->pdev->dev, "UNDERRUN\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 break;
976 case CMD_DATA_OVERRUN:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500977 dev_warn(&h->pdev->dev, "%p has"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 " completed with data overrun "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500979 "reported\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 break;
981 case CMD_INVALID: {
982 /* controller unfortunately reports SCSI passthru's */
983 /* to non-existent targets as invalid commands. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500984 dev_warn(&h->pdev->dev,
985 "%p is reported invalid (probably means "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500986 "target device no longer present)\n", c);
987 /* print_bytes((unsigned char *) c, sizeof(*c), 1, 0);
988 print_cmd(c); */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990 break;
991 case CMD_PROTOCOL_ERR:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500992 dev_warn(&h->pdev->dev, "%p has protocol error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 break;
994 case CMD_HARDWARE_ERR:
995 /* cmd->result = DID_ERROR << 16; */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500996 dev_warn(&h->pdev->dev, "%p had hardware error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 break;
998 case CMD_CONNECTION_LOST:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500999 dev_warn(&h->pdev->dev, "%p had connection lost\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 break;
1001 case CMD_ABORTED:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001002 dev_warn(&h->pdev->dev, "%p was aborted\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 break;
1004 case CMD_ABORT_FAILED:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001005 dev_warn(&h->pdev->dev,
1006 "%p reports abort failed\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 break;
1008 case CMD_UNSOLICITED_ABORT:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001009 dev_warn(&h->pdev->dev,
1010 "%p aborted do to an unsolicited abort\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 break;
1012 case CMD_TIMEOUT:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001013 dev_warn(&h->pdev->dev, "%p timedout\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 break;
1015 default:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001016 dev_warn(&h->pdev->dev,
1017 "%p returned unknown status %x\n",
1018 c, ei->CommandStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 }
1020}
1021
1022static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001023cciss_scsi_do_inquiry(ctlr_info_t *h, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001024 unsigned char page, unsigned char *buf,
1025 unsigned char bufsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026{
1027 int rc;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001028 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 char cdb[6];
1030 ErrorInfo_struct *ei;
1031 unsigned long flags;
1032
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001033 spin_lock_irqsave(&h->lock, flags);
1034 c = scsi_cmd_alloc(h);
1035 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001037 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 printk("cmd_alloc returned NULL!\n");
1039 return -1;
1040 }
1041
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001042 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
1044 cdb[0] = CISS_INQUIRY;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001045 cdb[1] = (page != 0);
1046 cdb[2] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 cdb[3] = 0;
Mike Miller47922d02005-09-13 01:25:25 -07001048 cdb[4] = bufsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 cdb[5] = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001050 rc = cciss_scsi_do_simple_cmd(h, c, scsi3addr, cdb,
Mike Miller47922d02005-09-13 01:25:25 -07001051 6, buf, bufsize, XFER_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 if (rc != 0) return rc; /* something went wrong */
1054
1055 if (ei->CommandStatus != 0 &&
1056 ei->CommandStatus != CMD_DATA_UNDERRUN) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001057 cciss_scsi_interpret_error(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 rc = -1;
1059 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001060 spin_lock_irqsave(&h->lock, flags);
1061 scsi_cmd_free(h, c);
1062 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 return rc;
1064}
1065
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001066/* Get the device id from inquiry page 0x83 */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001067static int cciss_scsi_get_device_id(ctlr_info_t *h, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001068 unsigned char *device_id, int buflen)
1069{
1070 int rc;
1071 unsigned char *buf;
1072
1073 if (buflen > 16)
1074 buflen = 16;
1075 buf = kzalloc(64, GFP_KERNEL);
1076 if (!buf)
1077 return -1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001078 rc = cciss_scsi_do_inquiry(h, scsi3addr, 0x83, buf, 64);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001079 if (rc == 0)
1080 memcpy(device_id, &buf[8], buflen);
1081 kfree(buf);
1082 return rc != 0;
1083}
1084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001086cciss_scsi_do_report_phys_luns(ctlr_info_t *h,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 ReportLunData_struct *buf, int bufsize)
1088{
1089 int rc;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001090 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 unsigned char cdb[12];
1092 unsigned char scsi3addr[8];
1093 ErrorInfo_struct *ei;
1094 unsigned long flags;
1095
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001096 spin_lock_irqsave(&h->lock, flags);
1097 c = scsi_cmd_alloc(h);
1098 spin_unlock_irqrestore(&h->lock, flags);
1099 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 printk("cmd_alloc returned NULL!\n");
1101 return -1;
1102 }
1103
1104 memset(&scsi3addr[0], 0, 8); /* address the controller */
1105 cdb[0] = CISS_REPORT_PHYS;
1106 cdb[1] = 0;
1107 cdb[2] = 0;
1108 cdb[3] = 0;
1109 cdb[4] = 0;
1110 cdb[5] = 0;
1111 cdb[6] = (bufsize >> 24) & 0xFF; //MSB
1112 cdb[7] = (bufsize >> 16) & 0xFF;
1113 cdb[8] = (bufsize >> 8) & 0xFF;
1114 cdb[9] = bufsize & 0xFF;
1115 cdb[10] = 0;
1116 cdb[11] = 0;
1117
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001118 rc = cciss_scsi_do_simple_cmd(h, c, scsi3addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 cdb, 12,
1120 (unsigned char *) buf,
1121 bufsize, XFER_READ);
1122
1123 if (rc != 0) return rc; /* something went wrong */
1124
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001125 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 if (ei->CommandStatus != 0 &&
1127 ei->CommandStatus != CMD_DATA_UNDERRUN) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001128 cciss_scsi_interpret_error(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 rc = -1;
1130 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001131 spin_lock_irqsave(&h->lock, flags);
1132 scsi_cmd_free(h, c);
1133 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return rc;
1135}
1136
1137static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001138cciss_update_non_disk_devices(ctlr_info_t *h, int hostno)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139{
1140 /* the idea here is we could get notified from /proc
1141 that some devices have changed, so we do a report
1142 physical luns cmd, and adjust our list of devices
1143 accordingly. (We can't rely on the scsi-mid layer just
1144 doing inquiries, because the "busses" that the scsi
1145 mid-layer probes are totally fabricated by this driver,
1146 so new devices wouldn't show up.
1147
1148 the scsi3addr's of devices won't change so long as the
1149 adapter is not reset. That means we can rescan and
1150 tell which devices we already know about, vs. new
1151 devices, vs. disappearing devices.
1152
1153 Also, if you yank out a tape drive, then put in a disk
1154 in it's place, (say, a configured volume from another
1155 array controller for instance) _don't_ poke this driver
1156 (so it thinks it's still a tape, but _do_ poke the scsi
1157 mid layer, so it does an inquiry... the scsi mid layer
1158 will see the physical disk. This would be bad. Need to
1159 think about how to prevent that. One idea would be to
1160 snoop all scsi responses and if an inquiry repsonse comes
1161 back that reports a disk, chuck it an return selection
1162 timeout instead and adjust our table... Not sure i like
1163 that though.
1164
1165 */
Mike Miller47922d02005-09-13 01:25:25 -07001166#define OBDR_TAPE_INQ_SIZE 49
1167#define OBDR_TAPE_SIG "$DR-10"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 ReportLunData_struct *ld_buff;
Mike Miller47922d02005-09-13 01:25:25 -07001169 unsigned char *inq_buff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 unsigned char scsi3addr[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 __u32 num_luns=0;
1172 unsigned char *ch;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001173 struct cciss_scsi_dev_t *currentsd, *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 int ncurrent=0;
1175 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
1176 int i;
1177
Eric Sesterhenn06ff37f2006-03-08 11:21:52 +01001178 ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
Mike Miller47922d02005-09-13 01:25:25 -07001179 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001180 currentsd = kzalloc(sizeof(*currentsd) *
1181 (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL);
1182 if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) {
1183 printk(KERN_ERR "cciss: out of memory\n");
1184 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001186 this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001187 if (cciss_scsi_do_report_phys_luns(h, ld_buff, reportlunsize) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 ch = &ld_buff->LUNListLength[0];
1189 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8;
1190 if (num_luns > CISS_MAX_PHYS_LUN) {
1191 printk(KERN_WARNING
1192 "cciss: Maximum physical LUNs (%d) exceeded. "
1193 "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN,
1194 num_luns - CISS_MAX_PHYS_LUN);
1195 num_luns = CISS_MAX_PHYS_LUN;
1196 }
1197 }
1198 else {
1199 printk(KERN_ERR "cciss: Report physical LUNs failed.\n");
1200 goto out;
1201 }
1202
1203
1204 /* adjust our table of devices */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001205 for (i = 0; i < num_luns; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 /* for each physical lun, do an inquiry */
1207 if (ld_buff->LUN[i][3] & 0xC0) continue;
Mike Miller47922d02005-09-13 01:25:25 -07001208 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
1210
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001211 if (cciss_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001212 (unsigned char) OBDR_TAPE_INQ_SIZE) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 /* Inquiry failed (msg printed already) */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001214 continue; /* so we will skip this device. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001216 this_device->devtype = (inq_buff[0] & 0x1f);
1217 this_device->bus = -1;
1218 this_device->target = -1;
1219 this_device->lun = -1;
1220 memcpy(this_device->scsi3addr, scsi3addr, 8);
1221 memcpy(this_device->vendor, &inq_buff[8],
1222 sizeof(this_device->vendor));
1223 memcpy(this_device->model, &inq_buff[16],
1224 sizeof(this_device->model));
1225 memcpy(this_device->revision, &inq_buff[32],
1226 sizeof(this_device->revision));
1227 memset(this_device->device_id, 0,
1228 sizeof(this_device->device_id));
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001229 cciss_scsi_get_device_id(h, scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001230 this_device->device_id, sizeof(this_device->device_id));
1231
1232 switch (this_device->devtype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 {
Mike Miller47922d02005-09-13 01:25:25 -07001234 case 0x05: /* CD-ROM */ {
1235
1236 /* We don't *really* support actual CD-ROM devices,
1237 * just this "One Button Disaster Recovery" tape drive
1238 * which temporarily pretends to be a CD-ROM drive.
1239 * So we check that the device is really an OBDR tape
1240 * device by checking for "$DR-10" in bytes 43-48 of
1241 * the inquiry data.
1242 */
1243 char obdr_sig[7];
1244
1245 strncpy(obdr_sig, &inq_buff[43], 6);
1246 obdr_sig[6] = '\0';
1247 if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
1248 /* Not OBDR device, ignore it. */
1249 break;
1250 }
1251 /* fall through . . . */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 case 0x01: /* sequential access, (tape) */
1253 case 0x08: /* medium changer */
1254 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
1255 printk(KERN_INFO "cciss%d: %s ignored, "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001256 "too many devices.\n", h->ctlr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001257 scsi_device_type(this_device->devtype));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 break;
1259 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001260 currentsd[ncurrent] = *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 ncurrent++;
1262 break;
1263 default:
1264 break;
1265 }
1266 }
1267
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001268 adjust_cciss_scsi_table(h, hostno, currentsd, ncurrent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269out:
1270 kfree(inq_buff);
1271 kfree(ld_buff);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001272 kfree(currentsd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 return;
1274}
1275
1276static int
1277is_keyword(char *ptr, int len, char *verb) // Thanks to ncr53c8xx.c
1278{
1279 int verb_len = strlen(verb);
1280 if (len >= verb_len && !memcmp(verb,ptr,verb_len))
1281 return verb_len;
1282 else
1283 return 0;
1284}
1285
1286static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001287cciss_scsi_user_command(ctlr_info_t *h, int hostno, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288{
1289 int arg_len;
1290
1291 if ((arg_len = is_keyword(buffer, length, "rescan")) != 0)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001292 cciss_update_non_disk_devices(h, hostno);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 else
1294 return -EINVAL;
1295 return length;
1296}
1297
1298
1299static int
1300cciss_scsi_proc_info(struct Scsi_Host *sh,
1301 char *buffer, /* data buffer */
1302 char **start, /* where data in buffer starts */
1303 off_t offset, /* offset from start of imaginary file */
1304 int length, /* length of data in buffer */
1305 int func) /* 0 == read, 1 == write */
1306{
1307
1308 int buflen, datalen;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001309 ctlr_info_t *h;
Mike Millerb9f0bd02005-09-13 01:25:26 -07001310 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001312 h = (ctlr_info_t *) sh->hostdata[0];
1313 if (h == NULL) /* This really shouldn't ever happen. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 return -EINVAL;
1315
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
Mike Millerb9f0bd02005-09-13 01:25:26 -07001317 buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001318 h->ctlr, sh->host_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Mike Millerb9f0bd02005-09-13 01:25:26 -07001320 /* this information is needed by apps to know which cciss
1321 device corresponds to which scsi host number without
1322 having to open a scsi target device node. The device
1323 information is not a duplicate of /proc/scsi/scsi because
1324 the two may be out of sync due to scsi hotplug, rather
1325 this info is for an app to be able to use to know how to
1326 get them back in sync. */
1327
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001328 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
1329 struct cciss_scsi_dev_t *sd =
1330 &ccissscsi[h->ctlr].dev[i];
Mike Millerb9f0bd02005-09-13 01:25:26 -07001331 buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
1332 "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
1333 sh->host_no, sd->bus, sd->target, sd->lun,
1334 sd->devtype,
1335 sd->scsi3addr[0], sd->scsi3addr[1],
1336 sd->scsi3addr[2], sd->scsi3addr[3],
1337 sd->scsi3addr[4], sd->scsi3addr[5],
1338 sd->scsi3addr[6], sd->scsi3addr[7]);
1339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 datalen = buflen - offset;
1341 if (datalen < 0) { /* they're reading past EOF. */
1342 datalen = 0;
1343 *start = buffer+buflen;
1344 } else
1345 *start = buffer + offset;
1346 return(datalen);
1347 } else /* User is writing to /proc/scsi/cciss*?/?* ... */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001348 return cciss_scsi_user_command(h, sh->host_no,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 buffer, length);
1350}
1351
1352/* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
1353 dma mapping and fills in the scatter gather entries of the
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001354 cciss command, c. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001356static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c,
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001357 struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001359 unsigned int len;
1360 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 __u64 addr64;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001362 int request_nsgs, i, chained, sg_index;
1363 struct cciss_scsi_adapter_data_t *sa = h->scsi_ctlr;
1364 SGDescriptor_struct *curr_sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001366 BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001368 chained = 0;
1369 sg_index = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001370 curr_sg = c->SG;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001371 request_nsgs = scsi_dma_map(cmd);
1372 if (request_nsgs) {
1373 scsi_for_each_sg(cmd, sg, request_nsgs, i) {
1374 if (sg_index + 1 == h->max_cmd_sgentries &&
1375 !chained && request_nsgs - i > 1) {
1376 chained = 1;
1377 sg_index = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001378 curr_sg = sa->cmd_sg_list[c->cmdindex];
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001379 }
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001380 addr64 = (__u64) sg_dma_address(sg);
1381 len = sg_dma_len(sg);
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001382 curr_sg[sg_index].Addr.lower =
1383 (__u32) (addr64 & 0x0FFFFFFFFULL);
1384 curr_sg[sg_index].Addr.upper =
1385 (__u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
1386 curr_sg[sg_index].Len = len;
1387 curr_sg[sg_index].Ext = 0;
1388 ++sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 }
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001390 if (chained)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001391 cciss_map_sg_chain_block(h, c,
1392 sa->cmd_sg_list[c->cmdindex],
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001393 (request_nsgs - (h->max_cmd_sgentries - 1)) *
1394 sizeof(SGDescriptor_struct));
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001395 }
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001396 /* track how many SG entries we are using */
1397 if (request_nsgs > h->maxSG)
1398 h->maxSG = request_nsgs;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001399 c->Header.SGTotal = (__u8) request_nsgs + chained;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001400 if (request_nsgs > h->max_cmd_sgentries)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001401 c->Header.SGList = h->max_cmd_sgentries;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001402 else
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001403 c->Header.SGList = c->Header.SGTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 return;
1405}
1406
1407
1408static int
Jeff Garzikf2812332010-11-16 02:10:29 -05001409cciss_scsi_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001411 ctlr_info_t *h;
1412 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 unsigned char scsi3addr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001414 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 unsigned long flags;
1416
1417 // Get the ptr to our adapter structure (hba[i]) out of cmd->host.
1418 // We violate cmd->host privacy here. (Is there another way?)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001419 h = (ctlr_info_t *) cmd->device->host->hostdata[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001421 rc = lookup_scsi3addr(h, cmd->device->channel, cmd->device->id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 cmd->device->lun, scsi3addr);
1423 if (rc != 0) {
1424 /* the scsi nexus does not match any that we presented... */
1425 /* pretend to mid layer that we got selection timeout */
1426 cmd->result = DID_NO_CONNECT << 16;
1427 done(cmd);
1428 /* we might want to think about registering controller itself
1429 as a processor device on the bus so sg binds to it. */
1430 return 0;
1431 }
1432
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 /* Ok, we have a reasonable scsi nexus, so send the cmd down, and
1434 see what the device thinks of it. */
1435
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001436 spin_lock_irqsave(&h->lock, flags);
1437 c = scsi_cmd_alloc(h);
1438 spin_unlock_irqrestore(&h->lock, flags);
1439 if (c == NULL) { /* trouble... */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001440 dev_warn(&h->pdev->dev, "scsi_cmd_alloc returned NULL!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 /* FIXME: next 3 lines are -> BAD! <- */
1442 cmd->result = DID_NO_CONNECT << 16;
1443 done(cmd);
1444 return 0;
1445 }
1446
1447 // Fill in the command list header
1448
1449 cmd->scsi_done = done; // save this for use by completion code
1450
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001451 /* save c in case we have to abort it */
1452 cmd->host_scribble = (unsigned char *) c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001454 c->cmd_type = CMD_SCSI;
1455 c->scsi_cmd = cmd;
1456 c->Header.ReplyQueue = 0; /* unused in simple mode */
1457 memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
1458 c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
1460 // Fill in the request block...
1461
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001462 c->Request.Timeout = 0;
1463 memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
1464 BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
1465 c->Request.CDBLen = cmd->cmd_len;
1466 memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len);
1467 c->Request.Type.Type = TYPE_CMD;
1468 c->Request.Type.Attribute = ATTR_SIMPLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 switch(cmd->sc_data_direction)
1470 {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001471 case DMA_TO_DEVICE:
1472 c->Request.Type.Direction = XFER_WRITE;
1473 break;
1474 case DMA_FROM_DEVICE:
1475 c->Request.Type.Direction = XFER_READ;
1476 break;
1477 case DMA_NONE:
1478 c->Request.Type.Direction = XFER_NONE;
1479 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 case DMA_BIDIRECTIONAL:
1481 // This can happen if a buggy application does a scsi passthru
1482 // and sets both inlen and outlen to non-zero. ( see
1483 // ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
1484
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001485 c->Request.Type.Direction = XFER_RSVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 // This is technically wrong, and cciss controllers should
1487 // reject it with CMD_INVALID, which is the most correct
1488 // response, but non-fibre backends appear to let it
1489 // slide by, and give the same results as if this field
1490 // were set correctly. Either way is acceptable for
1491 // our purposes here.
1492
1493 break;
1494
1495 default:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001496 dev_warn(&h->pdev->dev, "unknown data direction: %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 cmd->sc_data_direction);
1498 BUG();
1499 break;
1500 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001501 cciss_scatter_gather(h, c, cmd);
1502 enqueue_cmd_and_start_io(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 /* the cmd'll come back via intr handler in complete_scsi_command() */
1504 return 0;
1505}
1506
Jeff Garzikf2812332010-11-16 02:10:29 -05001507static DEF_SCSI_QCMD(cciss_scsi_queue_command)
1508
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001509static void cciss_unregister_scsi(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510{
1511 struct cciss_scsi_adapter_data_t *sa;
1512 struct cciss_scsi_cmd_stack_t *stk;
1513 unsigned long flags;
1514
1515 /* we are being forcibly unloaded, and may not refuse. */
1516
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001517 spin_lock_irqsave(&h->lock, flags);
1518 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 stk = &sa->cmd_stack;
1520
1521 /* if we weren't ever actually registered, don't unregister */
1522 if (sa->registered) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001523 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 scsi_remove_host(sa->scsi_host);
1525 scsi_host_put(sa->scsi_host);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001526 spin_lock_irqsave(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 }
1528
1529 /* set scsi_host to NULL so our detect routine will
1530 find us on register */
1531 sa->scsi_host = NULL;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001532 spin_unlock_irqrestore(&h->lock, flags);
1533 scsi_cmd_stack_free(h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 kfree(sa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535}
1536
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001537static int cciss_engage_scsi(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538{
1539 struct cciss_scsi_adapter_data_t *sa;
1540 struct cciss_scsi_cmd_stack_t *stk;
1541 unsigned long flags;
1542
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001543 spin_lock_irqsave(&h->lock, flags);
1544 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 stk = &sa->cmd_stack;
1546
Mike Millerf4a93bc2008-08-04 11:54:53 +02001547 if (sa->registered) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001548 dev_info(&h->pdev->dev, "SCSI subsystem already engaged.\n");
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001549 spin_unlock_irqrestore(&h->lock, flags);
Stephen M. Cameron8721c812009-11-12 12:50:06 -06001550 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 }
Mike Millerf4a93bc2008-08-04 11:54:53 +02001552 sa->registered = 1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001553 spin_unlock_irqrestore(&h->lock, flags);
1554 cciss_update_non_disk_devices(h, -1);
1555 cciss_scsi_detect(h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 return 0;
1557}
1558
1559static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001560cciss_seq_tape_report(struct seq_file *seq, ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561{
1562 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001564 CPQ_TAPE_LOCK(h, flags);
Mike Miller89b6e742008-02-21 08:54:03 +01001565 seq_printf(seq,
Mike Millerb9f0bd02005-09-13 01:25:26 -07001566 "Sequential access devices: %d\n\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001567 ccissscsi[h->ctlr].ndevices);
1568 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569}
1570
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001571static int wait_for_device_to_become_ready(ctlr_info_t *h,
1572 unsigned char lunaddr[])
1573{
1574 int rc;
1575 int count = 0;
1576 int waittime = HZ;
1577 CommandList_struct *c;
1578
Stephen M. Cameron6b4d96b2010-07-19 13:46:43 -05001579 c = cmd_alloc(h);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001580 if (!c) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001581 dev_warn(&h->pdev->dev, "out of memory in "
1582 "wait_for_device_to_become_ready.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001583 return IO_ERROR;
1584 }
1585
1586 /* Send test unit ready until device ready, or give up. */
1587 while (count < 20) {
1588
1589 /* Wait for a bit. do this first, because if we send
1590 * the TUR right away, the reset will just abort it.
1591 */
scameron@beardog.cca.cpqcorp.net40df6ae2009-06-08 15:59:38 -05001592 schedule_timeout_uninterruptible(waittime);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001593 count++;
1594
1595 /* Increase wait time with each try, up to a point. */
1596 if (waittime < (HZ * 30))
1597 waittime = waittime * 2;
1598
1599 /* Send the Test Unit Ready */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001600 rc = fill_cmd(h, c, TEST_UNIT_READY, NULL, 0, 0,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001601 lunaddr, TYPE_CMD);
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001602 if (rc == 0)
1603 rc = sendcmd_withirq_core(h, c, 0);
1604
1605 (void) process_sendcmd_error(h, c);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001606
scameron@beardog.cca.cpqcorp.net39692512009-06-08 16:10:57 -05001607 if (rc != 0)
1608 goto retry_tur;
1609
1610 if (c->err_info->CommandStatus == CMD_SUCCESS)
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001611 break;
1612
scameron@beardog.cca.cpqcorp.net39692512009-06-08 16:10:57 -05001613 if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
1614 c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
1615 if (c->err_info->SenseInfo[2] == NO_SENSE)
1616 break;
1617 if (c->err_info->SenseInfo[2] == UNIT_ATTENTION) {
1618 unsigned char asc;
1619 asc = c->err_info->SenseInfo[12];
1620 check_for_unit_attention(h, c);
1621 if (asc == POWER_OR_RESET)
1622 break;
1623 }
1624 }
1625retry_tur:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001626 dev_warn(&h->pdev->dev, "Waiting %d secs "
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001627 "for device to become ready.\n",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001628 waittime / HZ);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001629 rc = 1; /* device not ready. */
1630 }
1631
1632 if (rc)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001633 dev_warn(&h->pdev->dev, "giving up on device.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001634 else
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001635 dev_warn(&h->pdev->dev, "device is ready.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001636
Stephen M. Cameron6b4d96b2010-07-19 13:46:43 -05001637 cmd_free(h, c);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001638 return rc;
1639}
Mike Miller89b6e742008-02-21 08:54:03 +01001640
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001641/* Need at least one of these error handlers to keep ../scsi/hosts.c from
1642 * complaining. Doing a host- or bus-reset can't do anything good here.
1643 * Despite what it might say in scsi_error.c, there may well be commands
1644 * on the controller, as the cciss driver registers twice, once as a block
1645 * device for the logical drives, and once as a scsi device, for any tape
1646 * drives. So we know there are no commands out on the tape drives, but we
1647 * don't know there are no commands on the controller, and it is likely
1648 * that there probably are, as the cciss block device is most commonly used
1649 * as a boot device (embedded controller on HP/Compaq systems.)
1650*/
1651
1652static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
1653{
1654 int rc;
1655 CommandList_struct *cmd_in_trouble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001656 unsigned char lunaddr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001657 ctlr_info_t *h;
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001658
1659 /* find the controller to which the command to be aborted was sent */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001660 h = (ctlr_info_t *) scsicmd->device->host->hostdata[0];
1661 if (h == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001662 return FAILED;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001663 dev_warn(&h->pdev->dev, "resetting tape drive or medium changer.\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001664 /* find the command that's giving us trouble */
1665 cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001666 if (cmd_in_trouble == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001667 return FAILED;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001668 memcpy(lunaddr, &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 8);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001669 /* send a reset to the SCSI LUN which the command was sent to */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001670 rc = sendcmd_withirq(h, CCISS_RESET_MSG, NULL, 0, 0, lunaddr,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001671 TYPE_MSG);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001672 if (rc == 0 && wait_for_device_to_become_ready(h, lunaddr) == 0)
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001673 return SUCCESS;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001674 dev_warn(&h->pdev->dev, "resetting device failed.\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001675 return FAILED;
1676}
1677
1678static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
1679{
1680 int rc;
1681 CommandList_struct *cmd_to_abort;
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001682 unsigned char lunaddr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001683 ctlr_info_t *h;
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001684
1685 /* find the controller to which the command to be aborted was sent */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001686 h = (ctlr_info_t *) scsicmd->device->host->hostdata[0];
1687 if (h == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001688 return FAILED;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001689 dev_warn(&h->pdev->dev, "aborting tardy SCSI cmd\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001690
1691 /* find the command to be aborted */
1692 cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble;
1693 if (cmd_to_abort == NULL) /* paranoia */
1694 return FAILED;
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001695 memcpy(lunaddr, &cmd_to_abort->Header.LUN.LunAddrBytes[0], 8);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001696 rc = sendcmd_withirq(h, CCISS_ABORT_MSG, &cmd_to_abort->Header.Tag,
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001697 0, 0, lunaddr, TYPE_MSG);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001698 if (rc == 0)
1699 return SUCCESS;
1700 return FAILED;
1701
1702}
1703
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704#else /* no CONFIG_CISS_SCSI_TAPE */
1705
1706/* If no tape support, then these become defined out of existence */
1707
1708#define cciss_scsi_setup(cntl_num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
1710#endif /* CONFIG_CISS_SCSI_TAPE */