blob: a18de9d727b096cac76b14c64cb6991608d02c30 [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
Arun Sharma600634972011-07-26 16:09:06 -070036#include <linux/atomic.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080037
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
Al Viroe88b7bb2013-03-31 02:00:06 -040057static int cciss_scsi_write_info(struct Scsi_Host *sh,
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 char *buffer, /* data buffer */
Al Viroe88b7bb2013-03-31 02:00:06 -040059 int length); /* length of data in buffer */
60static int cciss_scsi_show_info(struct seq_file *m,
61 struct Scsi_Host *sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Jeff Garzikf2812332010-11-16 02:10:29 -050063static int cciss_scsi_queue_command (struct Scsi_Host *h,
64 struct scsi_cmnd *cmd);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060065static int cciss_eh_device_reset_handler(struct scsi_cmnd *);
66static int cciss_eh_abort_handler(struct scsi_cmnd *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
68static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = {
69 { .name = "cciss0", .ndevices = 0 },
70 { .name = "cciss1", .ndevices = 0 },
71 { .name = "cciss2", .ndevices = 0 },
72 { .name = "cciss3", .ndevices = 0 },
73 { .name = "cciss4", .ndevices = 0 },
74 { .name = "cciss5", .ndevices = 0 },
75 { .name = "cciss6", .ndevices = 0 },
76 { .name = "cciss7", .ndevices = 0 },
77};
78
79static struct scsi_host_template cciss_driver_template = {
80 .module = THIS_MODULE,
81 .name = "cciss",
82 .proc_name = "cciss",
Al Viroe88b7bb2013-03-31 02:00:06 -040083 .write_info = cciss_scsi_write_info,
84 .show_info = cciss_scsi_show_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 .queuecommand = cciss_scsi_queue_command,
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 .this_id = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 .use_clustering = DISABLE_CLUSTERING,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060088 /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */
89 .eh_device_reset_handler= cciss_eh_device_reset_handler,
90 .eh_abort_handler = cciss_eh_abort_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -070091};
92
93#pragma pack(1)
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -060094
Mike Miller5e216152010-06-02 12:58:06 -070095#define SCSI_PAD_32 8
96#define SCSI_PAD_64 8
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -060097
Linus Torvalds1da177e2005-04-16 15:20:36 -070098struct cciss_scsi_cmd_stack_elem_t {
99 CommandList_struct cmd;
100 ErrorInfo_struct Err;
101 __u32 busaddr;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600102 int cmdindex;
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600103 u8 pad[IS_32_BIT * SCSI_PAD_32 + IS_64_BIT * SCSI_PAD_64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104};
105
106#pragma pack()
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108#pragma pack(1)
109struct cciss_scsi_cmd_stack_t {
110 struct cciss_scsi_cmd_stack_elem_t *pool;
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500111 struct cciss_scsi_cmd_stack_elem_t **elem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 dma_addr_t cmd_pool_handle;
113 int top;
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500114 int nelems;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115};
116#pragma pack()
117
118struct cciss_scsi_adapter_data_t {
119 struct Scsi_Host *scsi_host;
120 struct cciss_scsi_cmd_stack_t cmd_stack;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600121 SGDescriptor_struct **cmd_sg_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 int registered;
123 spinlock_t lock; // to protect ccissscsi[ctlr];
124};
125
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500126#define CPQ_TAPE_LOCK(h, flags) spin_lock_irqsave( \
127 &h->scsi_ctlr->lock, flags);
128#define CPQ_TAPE_UNLOCK(h, flags) spin_unlock_irqrestore( \
129 &h->scsi_ctlr->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
131static CommandList_struct *
132scsi_cmd_alloc(ctlr_info_t *h)
133{
134 /* assume only one process in here at a time, locking done by caller. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500135 /* use h->lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 /* might be better to rewrite how we allocate scsi commands in a way that */
137 /* needs no locking at all. */
138
139 /* take the top memory chunk off the stack and return it, if any. */
140 struct cciss_scsi_cmd_stack_elem_t *c;
141 struct cciss_scsi_adapter_data_t *sa;
142 struct cciss_scsi_cmd_stack_t *stk;
143 u64bit temp64;
144
Stephen M. Cameronaad9fb62010-02-26 16:01:42 -0600145 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 stk = &sa->cmd_stack;
147
148 if (stk->top < 0)
149 return NULL;
150 c = stk->elem[stk->top];
151 /* memset(c, 0, sizeof(*c)); */
152 memset(&c->cmd, 0, sizeof(c->cmd));
153 memset(&c->Err, 0, sizeof(c->Err));
154 /* set physical addr of cmd and addr of scsi parameters */
155 c->cmd.busaddr = c->busaddr;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600156 c->cmd.cmdindex = c->cmdindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 /* (__u32) (stk->cmd_pool_handle +
158 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top)); */
159
160 temp64.val = (__u64) (c->busaddr + sizeof(CommandList_struct));
161 /* (__u64) (stk->cmd_pool_handle +
162 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top) +
163 sizeof(CommandList_struct)); */
164 stk->top--;
165 c->cmd.ErrDesc.Addr.lower = temp64.val32.lower;
166 c->cmd.ErrDesc.Addr.upper = temp64.val32.upper;
167 c->cmd.ErrDesc.Len = sizeof(ErrorInfo_struct);
168
169 c->cmd.ctlr = h->ctlr;
170 c->cmd.err_info = &c->Err;
171
172 return (CommandList_struct *) c;
173}
174
175static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500176scsi_cmd_free(ctlr_info_t *h, CommandList_struct *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177{
178 /* assume only one process in here at a time, locking done by caller. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500179 /* use h->lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 /* drop the free memory chunk on top of the stack. */
181
182 struct cciss_scsi_adapter_data_t *sa;
183 struct cciss_scsi_cmd_stack_t *stk;
184
Stephen M. Cameronaad9fb62010-02-26 16:01:42 -0600185 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 stk = &sa->cmd_stack;
Dan Carpenter713b6862010-06-01 12:17:48 +0200187 stk->top++;
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500188 if (stk->top >= stk->nelems) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500189 dev_err(&h->pdev->dev,
190 "scsi_cmd_free called too many times.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 BUG();
192 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500193 stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194}
195
196static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500197scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198{
199 int i;
200 struct cciss_scsi_cmd_stack_t *stk;
201 size_t size;
202
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500203 stk = &sa->cmd_stack;
204 stk->nelems = cciss_tape_cmds + 2;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500205 sa->cmd_sg_list = cciss_allocate_sg_chain_blocks(h,
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500206 h->chainsize, stk->nelems);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500207 if (!sa->cmd_sg_list && h->chainsize > 0)
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600208 return -ENOMEM;
209
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500210 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * stk->nelems;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600212 /* Check alignment, see cciss_cmd.h near CommandList_struct def. */
213 BUILD_BUG_ON((sizeof(*stk->pool) % COMMANDLIST_ALIGNMENT) != 0);
214 /* pci_alloc_consistent guarantees 32-bit DMA address will be used */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 stk->pool = (struct cciss_scsi_cmd_stack_elem_t *)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500216 pci_alloc_consistent(h->pdev, size, &stk->cmd_pool_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
218 if (stk->pool == NULL) {
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500219 cciss_free_sg_chain_blocks(sa->cmd_sg_list, stk->nelems);
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600220 sa->cmd_sg_list = NULL;
221 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 }
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500223 stk->elem = kmalloc(sizeof(stk->elem[0]) * stk->nelems, GFP_KERNEL);
224 if (!stk->elem) {
225 pci_free_consistent(h->pdev, size, stk->pool,
226 stk->cmd_pool_handle);
227 return -1;
228 }
229 for (i = 0; i < stk->nelems; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 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 }
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500235 stk->top = stk->nelems-1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 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;
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500248 if (stk->top != stk->nelems-1) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500249 dev_warn(&h->pdev->dev,
250 "bug: %d scsi commands are still outstanding.\n",
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500251 stk->nelems - stk->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 }
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500253 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * stk->nelems;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
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. Cameron8a4ec672011-05-03 14:54:12 -0500257 cciss_free_sg_chain_blocks(sa->cmd_sg_list, stk->nelems);
258 kfree(stk->elem);
259 stk->elem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260}
261
Grant Coady400bb232005-11-15 00:09:20 -0800262#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263static void
264print_cmd(CommandList_struct *cp)
265{
266 printk("queue:%d\n", cp->Header.ReplyQueue);
267 printk("sglist:%d\n", cp->Header.SGList);
268 printk("sgtot:%d\n", cp->Header.SGTotal);
269 printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper,
270 cp->Header.Tag.lower);
Andy Shevchenko8d9c1f82016-10-22 20:32:31 +0300271 printk("LUN:0x%8phN\n", cp->Header.LUN.LunAddrBytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 printk("CDBLen:%d\n", cp->Request.CDBLen);
273 printk("Type:%d\n",cp->Request.Type.Type);
274 printk("Attr:%d\n",cp->Request.Type.Attribute);
275 printk(" Dir:%d\n",cp->Request.Type.Direction);
276 printk("Timeout:%d\n",cp->Request.Timeout);
Andy Shevchenko8d9c1f82016-10-22 20:32:31 +0300277 printk("CDB: %16ph\n", cp->Request.CDB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 printk("edesc.Addr: 0x%08x/0%08x, Len = %d\n",
279 cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower,
280 cp->ErrDesc.Len);
281 printk("sgs..........Errorinfo:\n");
282 printk("scsistatus:%d\n", cp->err_info->ScsiStatus);
283 printk("senselen:%d\n", cp->err_info->SenseLen);
284 printk("cmd status:%d\n", cp->err_info->CommandStatus);
285 printk("resid cnt:%d\n", cp->err_info->ResidualCnt);
286 printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size);
287 printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num);
288 printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290#endif
291
292static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500293find_bus_target_lun(ctlr_info_t *h, int *bus, int *target, int *lun)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294{
295 /* finds an unused bus, target, lun for a new device */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500296 /* assumes h->scsi_ctlr->lock is held */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 int i, found=0;
298 unsigned char target_taken[CCISS_MAX_SCSI_DEVS_PER_HBA];
299
300 memset(&target_taken[0], 0, CCISS_MAX_SCSI_DEVS_PER_HBA);
301
302 target_taken[SELF_SCSI_ID] = 1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500303 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++)
304 target_taken[ccissscsi[h->ctlr].dev[i].target] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500306 for (i = 0; i < CCISS_MAX_SCSI_DEVS_PER_HBA; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 if (!target_taken[i]) {
308 *bus = 0; *target=i; *lun = 0; found=1;
309 break;
310 }
311 }
312 return (!found);
313}
Mike Millerf4a93bc2008-08-04 11:54:53 +0200314struct scsi2map {
315 char scsi3addr[8];
316 int bus, target, lun;
317};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
319static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500320cciss_scsi_add_entry(ctlr_info_t *h, int hostno,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700321 struct cciss_scsi_dev_t *device,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200322 struct scsi2map *added, int *nadded)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500324 /* assumes h->scsi_ctlr->lock is held */
325 int n = ccissscsi[h->ctlr].ndevices;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 struct cciss_scsi_dev_t *sd;
Mike Miller935dc8d2008-08-04 11:54:54 +0200327 int i, bus, target, lun;
328 unsigned char addr1[8], addr2[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330 if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500331 dev_warn(&h->pdev->dev, "Too many devices, "
332 "some will be inaccessible.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 return -1;
334 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200335
Mike Miller935dc8d2008-08-04 11:54:54 +0200336 bus = target = -1;
337 lun = 0;
338 /* Is this device a non-zero lun of a multi-lun device */
339 /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700340 if (device->scsi3addr[4] != 0) {
Mike Miller935dc8d2008-08-04 11:54:54 +0200341 /* Search through our list and find the device which */
342 /* has the same 8 byte LUN address, excepting byte 4. */
343 /* Assign the same bus and target for this new LUN. */
344 /* Use the logical unit number from the firmware. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700345 memcpy(addr1, device->scsi3addr, 8);
Mike Miller935dc8d2008-08-04 11:54:54 +0200346 addr1[4] = 0;
347 for (i = 0; i < n; i++) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500348 sd = &ccissscsi[h->ctlr].dev[i];
Mike Miller935dc8d2008-08-04 11:54:54 +0200349 memcpy(addr2, sd->scsi3addr, 8);
350 addr2[4] = 0;
351 /* differ only in byte 4? */
352 if (memcmp(addr1, addr2, 8) == 0) {
353 bus = sd->bus;
354 target = sd->target;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700355 lun = device->scsi3addr[4];
Mike Miller935dc8d2008-08-04 11:54:54 +0200356 break;
357 }
358 }
359 }
360
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500361 sd = &ccissscsi[h->ctlr].dev[n];
Mike Miller935dc8d2008-08-04 11:54:54 +0200362 if (lun == 0) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500363 if (find_bus_target_lun(h,
Mike Miller935dc8d2008-08-04 11:54:54 +0200364 &sd->bus, &sd->target, &sd->lun) != 0)
365 return -1;
366 } else {
367 sd->bus = bus;
368 sd->target = target;
369 sd->lun = lun;
370 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200371 added[*nadded].bus = sd->bus;
372 added[*nadded].target = sd->target;
373 added[*nadded].lun = sd->lun;
374 (*nadded)++;
375
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700376 memcpy(sd->scsi3addr, device->scsi3addr, 8);
377 memcpy(sd->vendor, device->vendor, sizeof(sd->vendor));
378 memcpy(sd->revision, device->revision, sizeof(sd->revision));
379 memcpy(sd->device_id, device->device_id, sizeof(sd->device_id));
380 sd->devtype = device->devtype;
381
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500382 ccissscsi[h->ctlr].ndevices++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
384 /* initially, (before registering with scsi layer) we don't
385 know our hostno and we don't want to print anything first
386 time anyway (the scsi layer's inquiries will show that info) */
387 if (hostno != -1)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500388 dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d added.\n",
389 scsi_device_type(sd->devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 sd->bus, sd->target, sd->lun);
391 return 0;
392}
393
394static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500395cciss_scsi_remove_entry(ctlr_info_t *h, int hostno, int entry,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200396 struct scsi2map *removed, int *nremoved)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500398 /* assumes h->ctlr]->scsi_ctlr->lock is held */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 int i;
400 struct cciss_scsi_dev_t sd;
401
402 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500403 sd = ccissscsi[h->ctlr].dev[entry];
Mike Millerf4a93bc2008-08-04 11:54:53 +0200404 removed[*nremoved].bus = sd.bus;
405 removed[*nremoved].target = sd.target;
406 removed[*nremoved].lun = sd.lun;
407 (*nremoved)++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500408 for (i = entry; i < ccissscsi[h->ctlr].ndevices-1; i++)
409 ccissscsi[h->ctlr].dev[i] = ccissscsi[h->ctlr].dev[i+1];
410 ccissscsi[h->ctlr].ndevices--;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500411 dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d removed.\n",
412 scsi_device_type(sd.devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 sd.bus, sd.target, sd.lun);
414}
415
416
417#define SCSI3ADDR_EQ(a,b) ( \
418 (a)[7] == (b)[7] && \
419 (a)[6] == (b)[6] && \
420 (a)[5] == (b)[5] && \
421 (a)[4] == (b)[4] && \
422 (a)[3] == (b)[3] && \
423 (a)[2] == (b)[2] && \
424 (a)[1] == (b)[1] && \
425 (a)[0] == (b)[0])
426
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500427static void fixup_botched_add(ctlr_info_t *h, char *scsi3addr)
Mike Millerf4a93bc2008-08-04 11:54:53 +0200428{
429 /* called when scsi_add_device fails in order to re-adjust */
430 /* ccissscsi[] to match the mid layer's view. */
431 unsigned long flags;
432 int i, j;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500433 CPQ_TAPE_LOCK(h, flags);
434 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
Mike Millerf4a93bc2008-08-04 11:54:53 +0200435 if (memcmp(scsi3addr,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500436 ccissscsi[h->ctlr].dev[i].scsi3addr, 8) == 0) {
437 for (j = i; j < ccissscsi[h->ctlr].ndevices-1; j++)
438 ccissscsi[h->ctlr].dev[j] =
439 ccissscsi[h->ctlr].dev[j+1];
440 ccissscsi[h->ctlr].ndevices--;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200441 break;
442 }
443 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500444 CPQ_TAPE_UNLOCK(h, flags);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200445}
446
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700447static int device_is_the_same(struct cciss_scsi_dev_t *dev1,
448 struct cciss_scsi_dev_t *dev2)
449{
450 return dev1->devtype == dev2->devtype &&
451 memcmp(dev1->scsi3addr, dev2->scsi3addr,
452 sizeof(dev1->scsi3addr)) == 0 &&
453 memcmp(dev1->device_id, dev2->device_id,
454 sizeof(dev1->device_id)) == 0 &&
455 memcmp(dev1->vendor, dev2->vendor,
456 sizeof(dev1->vendor)) == 0 &&
457 memcmp(dev1->model, dev2->model,
458 sizeof(dev1->model)) == 0 &&
459 memcmp(dev1->revision, dev2->revision,
460 sizeof(dev1->revision)) == 0;
461}
462
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500464adjust_cciss_scsi_table(ctlr_info_t *h, int hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 struct cciss_scsi_dev_t sd[], int nsds)
466{
467 /* sd contains scsi3 addresses and devtypes, but
468 bus target and lun are not filled in. This funciton
469 takes what's in sd to be the current and adjusts
470 ccissscsi[] to be in line with what's in sd. */
471
472 int i,j, found, changes=0;
473 struct cciss_scsi_dev_t *csd;
474 unsigned long flags;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200475 struct scsi2map *added, *removed;
476 int nadded, nremoved;
477 struct Scsi_Host *sh = NULL;
478
479 added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA,
480 GFP_KERNEL);
481 removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA,
482 GFP_KERNEL);
483
484 if (!added || !removed) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500485 dev_warn(&h->pdev->dev,
486 "Out of memory in adjust_cciss_scsi_table\n");
Mike Millerf4a93bc2008-08-04 11:54:53 +0200487 goto free_and_out;
488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500490 CPQ_TAPE_LOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
Mike Millerf4a93bc2008-08-04 11:54:53 +0200492 if (hostno != -1) /* if it's not the first time... */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500493 sh = h->scsi_ctlr->scsi_host;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 /* find any devices in ccissscsi[] that are not in
496 sd[] and remove them from ccissscsi[] */
497
498 i = 0;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200499 nremoved = 0;
500 nadded = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500501 while (i < ccissscsi[h->ctlr].ndevices) {
502 csd = &ccissscsi[h->ctlr].dev[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 found=0;
504 for (j=0;j<nsds;j++) {
505 if (SCSI3ADDR_EQ(sd[j].scsi3addr,
506 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700507 if (device_is_the_same(&sd[j], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 found=2;
509 else
510 found=1;
511 break;
512 }
513 }
514
515 if (found == 0) { /* device no longer present. */
516 changes++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500517 cciss_scsi_remove_entry(h, hostno, i,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200518 removed, &nremoved);
519 /* remove ^^^, hence i not incremented */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700520 } else if (found == 1) { /* device is different in some way */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 changes++;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500522 dev_info(&h->pdev->dev,
523 "device c%db%dt%dl%d has changed.\n",
524 hostno, csd->bus, csd->target, csd->lun);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500525 cciss_scsi_remove_entry(h, hostno, i,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200526 removed, &nremoved);
527 /* remove ^^^, hence i not incremented */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500528 if (cciss_scsi_add_entry(h, hostno, &sd[j],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200529 added, &nadded) != 0)
530 /* we just removed one, so add can't fail. */
531 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 csd->devtype = sd[j].devtype;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700533 memcpy(csd->device_id, sd[j].device_id,
534 sizeof(csd->device_id));
535 memcpy(csd->vendor, sd[j].vendor,
536 sizeof(csd->vendor));
537 memcpy(csd->model, sd[j].model,
538 sizeof(csd->model));
539 memcpy(csd->revision, sd[j].revision,
540 sizeof(csd->revision));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 } else /* device is same as it ever was, */
542 i++; /* so just move along. */
543 }
544
545 /* Now, make sure every device listed in sd[] is also
546 listed in ccissscsi[], adding them if they aren't found */
547
548 for (i=0;i<nsds;i++) {
549 found=0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500550 for (j = 0; j < ccissscsi[h->ctlr].ndevices; j++) {
551 csd = &ccissscsi[h->ctlr].dev[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 if (SCSI3ADDR_EQ(sd[i].scsi3addr,
553 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700554 if (device_is_the_same(&sd[i], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 found=2; /* found device */
556 else
557 found=1; /* found a bug. */
558 break;
559 }
560 }
561 if (!found) {
562 changes++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500563 if (cciss_scsi_add_entry(h, hostno, &sd[i],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200564 added, &nadded) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 break;
566 } else if (found == 1) {
567 /* should never happen... */
568 changes++;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500569 dev_warn(&h->pdev->dev,
570 "device unexpectedly changed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 /* but if it does happen, we just ignore that device */
572 }
573 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500574 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Mike Millerf4a93bc2008-08-04 11:54:53 +0200576 /* Don't notify scsi mid layer of any changes the first time through */
577 /* (or if there are no changes) scsi_scan_host will do it later the */
578 /* first time through. */
579 if (hostno == -1 || !changes)
580 goto free_and_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Mike Millerf4a93bc2008-08-04 11:54:53 +0200582 /* Notify scsi mid layer of any removed devices */
583 for (i = 0; i < nremoved; i++) {
584 struct scsi_device *sdev =
585 scsi_device_lookup(sh, removed[i].bus,
586 removed[i].target, removed[i].lun);
587 if (sdev != NULL) {
588 scsi_remove_device(sdev);
589 scsi_device_put(sdev);
590 } else {
591 /* We don't expect to get here. */
592 /* future cmds to this device will get selection */
593 /* timeout as if the device was gone. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500594 dev_warn(&h->pdev->dev, "didn't find "
Mike Millerf4a93bc2008-08-04 11:54:53 +0200595 "c%db%dt%dl%d\n for removal.",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500596 hostno, removed[i].bus,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200597 removed[i].target, removed[i].lun);
598 }
599 }
600
601 /* Notify scsi mid layer of any added devices */
602 for (i = 0; i < nadded; i++) {
603 int rc;
604 rc = scsi_add_device(sh, added[i].bus,
605 added[i].target, added[i].lun);
606 if (rc == 0)
607 continue;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500608 dev_warn(&h->pdev->dev, "scsi_add_device "
Mike Millerf4a93bc2008-08-04 11:54:53 +0200609 "c%db%dt%dl%d failed, device not added.\n",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500610 hostno, added[i].bus, added[i].target, added[i].lun);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200611 /* now we have to remove it from ccissscsi, */
612 /* since it didn't get added to scsi mid layer */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500613 fixup_botched_add(h, added[i].scsi3addr);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200614 }
615
616free_and_out:
617 kfree(added);
618 kfree(removed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 return 0;
620}
621
622static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500623lookup_scsi3addr(ctlr_info_t *h, int bus, int target, int lun, char *scsi3addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624{
625 int i;
626 struct cciss_scsi_dev_t *sd;
627 unsigned long flags;
628
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500629 CPQ_TAPE_LOCK(h, flags);
630 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
631 sd = &ccissscsi[h->ctlr].dev[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 if (sd->bus == bus &&
633 sd->target == target &&
634 sd->lun == lun) {
635 memcpy(scsi3addr, &sd->scsi3addr[0], 8);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500636 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 return 0;
638 }
639 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500640 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 return -1;
642}
643
644static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500645cciss_scsi_setup(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646{
647 struct cciss_scsi_adapter_data_t * shba;
648
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500649 ccissscsi[h->ctlr].ndevices = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 shba = (struct cciss_scsi_adapter_data_t *)
651 kmalloc(sizeof(*shba), GFP_KERNEL);
652 if (shba == NULL)
653 return;
654 shba->scsi_host = NULL;
655 spin_lock_init(&shba->lock);
656 shba->registered = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500657 if (scsi_cmd_stack_setup(h, shba) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 kfree(shba);
659 shba = NULL;
660 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500661 h->scsi_ctlr = shba;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 return;
663}
664
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500665static void complete_scsi_command(CommandList_struct *c, int timeout,
666 __u32 tag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667{
668 struct scsi_cmnd *cmd;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500669 ctlr_info_t *h;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 ErrorInfo_struct *ei;
671
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500672 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
674 /* First, see if it was a message rather than a command */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500675 if (c->Request.Type.Type == TYPE_MSG) {
676 c->cmd_type = CMD_MSG_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 return;
678 }
679
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500680 cmd = (struct scsi_cmnd *) c->scsi_cmd;
681 h = hba[c->ctlr];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900683 scsi_dma_unmap(cmd);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500684 if (c->Header.SGTotal > h->max_cmd_sgentries)
685 cciss_unmap_sg_chain_block(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
687 cmd->result = (DID_OK << 16); /* host byte */
688 cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
689 /* cmd->result |= (GOOD < 1); */ /* status byte */
690
691 cmd->result |= (ei->ScsiStatus);
692 /* printk("Scsistatus is 0x%02x\n", ei->ScsiStatus); */
693
694 /* copy the sense data whether we need to or not. */
695
696 memcpy(cmd->sense_buffer, ei->SenseInfo,
697 ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
698 SCSI_SENSE_BUFFERSIZE :
699 ei->SenseLen);
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900700 scsi_set_resid(cmd, ei->ResidualCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
702 if(ei->CommandStatus != 0)
703 { /* an error has occurred */
704 switch(ei->CommandStatus)
705 {
706 case CMD_TARGET_STATUS:
707 /* Pass it up to the upper layers... */
Stephen M. Cameronb0cf0b12012-08-21 16:15:49 -0700708 if (!ei->ScsiStatus) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710 /* Ordinarily, this case should never happen, but there is a bug
711 in some released firmware revisions that allows it to happen
712 if, for example, a 4100 backplane loses power and the tape
713 drive is in it. We assume that it's a fatal error of some
714 kind because we can't show that it wasn't. We will make it
715 look like selection timeout since that is the most common
716 reason for this to occur, and it's severe enough. */
717
718 cmd->result = DID_NO_CONNECT << 16;
719 }
720 break;
721 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
722 break;
723 case CMD_DATA_OVERRUN:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500724 dev_warn(&h->pdev->dev, "%p has"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 " completed with data overrun "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500726 "reported\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 break;
728 case CMD_INVALID: {
Andy Shevchenko8d9c1f82016-10-22 20:32:31 +0300729 /*
730 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, c, sizeof(*c), false);
731 print_cmd(c);
732 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 /* We get CMD_INVALID if you address a non-existent tape drive instead
734 of a selection timeout (no response). You will see this if you yank
735 out a tape drive, then try to access it. This is kind of a shame
736 because it means that any other CMD_INVALID (e.g. driver bug) will
737 get interpreted as a missing target. */
738 cmd->result = DID_NO_CONNECT << 16;
739 }
740 break;
741 case CMD_PROTOCOL_ERR:
Stephen M. Cameron2453f5f2012-09-14 16:35:10 -0500742 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500743 dev_warn(&h->pdev->dev,
744 "%p has protocol error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 break;
746 case CMD_HARDWARE_ERR:
747 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500748 dev_warn(&h->pdev->dev,
749 "%p had hardware error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 break;
751 case CMD_CONNECTION_LOST:
752 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500753 dev_warn(&h->pdev->dev,
754 "%p had connection lost\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 break;
756 case CMD_ABORTED:
757 cmd->result = DID_ABORT << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500758 dev_warn(&h->pdev->dev, "%p was aborted\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 break;
760 case CMD_ABORT_FAILED:
761 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500762 dev_warn(&h->pdev->dev,
763 "%p reports abort failed\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 break;
765 case CMD_UNSOLICITED_ABORT:
766 cmd->result = DID_ABORT << 16;
Stephen M. Cameron6d9a4f92011-03-12 10:02:30 +0100767 dev_warn(&h->pdev->dev, "%p aborted due to an "
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500768 "unsolicited abort\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 break;
770 case CMD_TIMEOUT:
771 cmd->result = DID_TIME_OUT << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500772 dev_warn(&h->pdev->dev, "%p timedout\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 break;
Stephen M. Cameron6d9a4f92011-03-12 10:02:30 +0100774 case CMD_UNABORTABLE:
775 cmd->result = DID_ERROR << 16;
776 dev_warn(&h->pdev->dev, "c %p command "
777 "unabortable\n", c);
778 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 default:
780 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500781 dev_warn(&h->pdev->dev,
782 "%p returned unknown status %x\n", c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 ei->CommandStatus);
784 }
785 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 cmd->scsi_done(cmd);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500787 scsi_cmd_free(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788}
789
790static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500791cciss_scsi_detect(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792{
793 struct Scsi_Host *sh;
794 int error;
795
796 sh = scsi_host_alloc(&cciss_driver_template, sizeof(struct ctlr_info *));
797 if (sh == NULL)
798 goto fail;
799 sh->io_port = 0; // good enough? FIXME,
800 sh->n_io_port = 0; // I don't think we use these two...
801 sh->this_id = SELF_SCSI_ID;
Stephen M. Cameron8a4ec672011-05-03 14:54:12 -0500802 sh->can_queue = cciss_tape_cmds;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500803 sh->sg_tablesize = h->maxsgentries;
Stephen M. Cameron79600aa2010-06-15 08:12:34 +0200804 sh->max_cmd_len = MAX_COMMAND_SIZE;
Stephen M. Cameron395d2872012-03-22 21:40:08 +0100805 sh->max_sectors = h->cciss_max_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
807 ((struct cciss_scsi_adapter_data_t *)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500808 h->scsi_ctlr)->scsi_host = sh;
809 sh->hostdata[0] = (unsigned long) h;
810 sh->irq = h->intr[SIMPLE_MODE_INT];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 sh->unique_id = sh->irq;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500812 error = scsi_add_host(sh, &h->pdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (error)
814 goto fail_host_put;
815 scsi_scan_host(sh);
816 return 1;
817
818 fail_host_put:
819 scsi_host_put(sh);
820 fail:
821 return 0;
822}
823
824static void
825cciss_unmap_one(struct pci_dev *pdev,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500826 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 size_t buflen,
828 int data_direction)
829{
830 u64bit addr64;
831
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500832 addr64.val32.lower = c->SG[0].Addr.lower;
833 addr64.val32.upper = c->SG[0].Addr.upper;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 pci_unmap_single(pdev, (dma_addr_t) addr64.val, buflen, data_direction);
835}
836
837static void
838cciss_map_one(struct pci_dev *pdev,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500839 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 unsigned char *buf,
841 size_t buflen,
842 int data_direction)
843{
844 __u64 addr64;
845
846 addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500847 c->SG[0].Addr.lower =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500849 c->SG[0].Addr.upper =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500851 c->SG[0].Len = buflen;
852 c->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */
853 c->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854}
855
856static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500857cciss_scsi_do_simple_cmd(ctlr_info_t *h,
858 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 unsigned char *scsi3addr,
860 unsigned char *cdb,
861 unsigned char cdblen,
862 unsigned char *buf, int bufsize,
863 int direction)
864{
Peter Zijlstra6e9a4732006-09-30 23:28:10 -0700865 DECLARE_COMPLETION_ONSTACK(wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500867 c->cmd_type = CMD_IOCTL_PEND; /* treat this like an ioctl */
868 c->scsi_cmd = NULL;
869 c->Header.ReplyQueue = 0; /* unused in simple mode */
870 memcpy(&c->Header.LUN, scsi3addr, sizeof(c->Header.LUN));
871 c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 // Fill in the request block...
873
874 /* printk("Using scsi3addr 0x%02x%0x2%0x2%0x2%0x2%0x2%0x2%0x2\n",
875 scsi3addr[0], scsi3addr[1], scsi3addr[2], scsi3addr[3],
876 scsi3addr[4], scsi3addr[5], scsi3addr[6], scsi3addr[7]); */
877
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500878 memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
879 memcpy(c->Request.CDB, cdb, cdblen);
880 c->Request.Timeout = 0;
881 c->Request.CDBLen = cdblen;
882 c->Request.Type.Type = TYPE_CMD;
883 c->Request.Type.Attribute = ATTR_SIMPLE;
884 c->Request.Type.Direction = direction;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 /* Fill in the SG list and do dma mapping */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500887 cciss_map_one(h->pdev, c, (unsigned char *) buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 bufsize, DMA_FROM_DEVICE);
889
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500890 c->waiting = &wait;
891 enqueue_cmd_and_start_io(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 wait_for_completion(&wait);
893
894 /* undo the dma mapping */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500895 cciss_unmap_one(h->pdev, c, bufsize, DMA_FROM_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 return(0);
897}
898
899static void
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500900cciss_scsi_interpret_error(ctlr_info_t *h, CommandList_struct *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901{
902 ErrorInfo_struct *ei;
903
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500904 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 switch(ei->CommandStatus)
906 {
907 case CMD_TARGET_STATUS:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500908 dev_warn(&h->pdev->dev,
909 "cmd %p has completed with errors\n", c);
910 dev_warn(&h->pdev->dev,
911 "cmd %p has SCSI Status = %x\n",
912 c, ei->ScsiStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 if (ei->ScsiStatus == 0)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500914 dev_warn(&h->pdev->dev,
915 "SCSI status is abnormally zero. "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 "(probably indicates selection timeout "
917 "reported incorrectly due to a known "
918 "firmware bug, circa July, 2001.)\n");
919 break;
920 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500921 dev_info(&h->pdev->dev, "UNDERRUN\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 break;
923 case CMD_DATA_OVERRUN:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500924 dev_warn(&h->pdev->dev, "%p has"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 " completed with data overrun "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500926 "reported\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 break;
928 case CMD_INVALID: {
929 /* controller unfortunately reports SCSI passthru's */
930 /* to non-existent targets as invalid commands. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500931 dev_warn(&h->pdev->dev,
932 "%p is reported invalid (probably means "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500933 "target device no longer present)\n", c);
Andy Shevchenko8d9c1f82016-10-22 20:32:31 +0300934 /*
935 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, c, sizeof(*c), false);
936 print_cmd(c);
937 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
939 break;
940 case CMD_PROTOCOL_ERR:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500941 dev_warn(&h->pdev->dev, "%p has protocol error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 break;
943 case CMD_HARDWARE_ERR:
944 /* cmd->result = DID_ERROR << 16; */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500945 dev_warn(&h->pdev->dev, "%p had hardware error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 break;
947 case CMD_CONNECTION_LOST:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500948 dev_warn(&h->pdev->dev, "%p had connection lost\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 break;
950 case CMD_ABORTED:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500951 dev_warn(&h->pdev->dev, "%p was aborted\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 break;
953 case CMD_ABORT_FAILED:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500954 dev_warn(&h->pdev->dev,
955 "%p reports abort failed\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 break;
957 case CMD_UNSOLICITED_ABORT:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500958 dev_warn(&h->pdev->dev,
Stephen M. Cameron6d9a4f92011-03-12 10:02:30 +0100959 "%p aborted due to an unsolicited abort\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 break;
961 case CMD_TIMEOUT:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500962 dev_warn(&h->pdev->dev, "%p timedout\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 break;
Stephen M. Cameron6d9a4f92011-03-12 10:02:30 +0100964 case CMD_UNABORTABLE:
965 dev_warn(&h->pdev->dev,
966 "%p unabortable\n", c);
967 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 default:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500969 dev_warn(&h->pdev->dev,
970 "%p returned unknown status %x\n",
971 c, ei->CommandStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 }
973}
974
975static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500976cciss_scsi_do_inquiry(ctlr_info_t *h, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700977 unsigned char page, unsigned char *buf,
978 unsigned char bufsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979{
980 int rc;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500981 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 char cdb[6];
983 ErrorInfo_struct *ei;
984 unsigned long flags;
985
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500986 spin_lock_irqsave(&h->lock, flags);
987 c = scsi_cmd_alloc(h);
988 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500990 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 printk("cmd_alloc returned NULL!\n");
992 return -1;
993 }
994
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500995 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 cdb[0] = CISS_INQUIRY;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700998 cdb[1] = (page != 0);
999 cdb[2] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 cdb[3] = 0;
Mike Miller47922d02005-09-13 01:25:25 -07001001 cdb[4] = bufsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 cdb[5] = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001003 rc = cciss_scsi_do_simple_cmd(h, c, scsi3addr, cdb,
Mike Miller47922d02005-09-13 01:25:25 -07001004 6, buf, bufsize, XFER_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006 if (rc != 0) return rc; /* something went wrong */
1007
1008 if (ei->CommandStatus != 0 &&
1009 ei->CommandStatus != CMD_DATA_UNDERRUN) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001010 cciss_scsi_interpret_error(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 rc = -1;
1012 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001013 spin_lock_irqsave(&h->lock, flags);
1014 scsi_cmd_free(h, c);
1015 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return rc;
1017}
1018
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001019/* Get the device id from inquiry page 0x83 */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001020static int cciss_scsi_get_device_id(ctlr_info_t *h, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001021 unsigned char *device_id, int buflen)
1022{
1023 int rc;
1024 unsigned char *buf;
1025
1026 if (buflen > 16)
1027 buflen = 16;
1028 buf = kzalloc(64, GFP_KERNEL);
1029 if (!buf)
1030 return -1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001031 rc = cciss_scsi_do_inquiry(h, scsi3addr, 0x83, buf, 64);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001032 if (rc == 0)
1033 memcpy(device_id, &buf[8], buflen);
1034 kfree(buf);
1035 return rc != 0;
1036}
1037
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001039cciss_scsi_do_report_phys_luns(ctlr_info_t *h,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 ReportLunData_struct *buf, int bufsize)
1041{
1042 int rc;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001043 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 unsigned char cdb[12];
1045 unsigned char scsi3addr[8];
1046 ErrorInfo_struct *ei;
1047 unsigned long flags;
1048
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001049 spin_lock_irqsave(&h->lock, flags);
1050 c = scsi_cmd_alloc(h);
1051 spin_unlock_irqrestore(&h->lock, flags);
1052 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 printk("cmd_alloc returned NULL!\n");
1054 return -1;
1055 }
1056
1057 memset(&scsi3addr[0], 0, 8); /* address the controller */
1058 cdb[0] = CISS_REPORT_PHYS;
1059 cdb[1] = 0;
1060 cdb[2] = 0;
1061 cdb[3] = 0;
1062 cdb[4] = 0;
1063 cdb[5] = 0;
1064 cdb[6] = (bufsize >> 24) & 0xFF; //MSB
1065 cdb[7] = (bufsize >> 16) & 0xFF;
1066 cdb[8] = (bufsize >> 8) & 0xFF;
1067 cdb[9] = bufsize & 0xFF;
1068 cdb[10] = 0;
1069 cdb[11] = 0;
1070
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001071 rc = cciss_scsi_do_simple_cmd(h, c, scsi3addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 cdb, 12,
1073 (unsigned char *) buf,
1074 bufsize, XFER_READ);
1075
1076 if (rc != 0) return rc; /* something went wrong */
1077
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001078 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 if (ei->CommandStatus != 0 &&
1080 ei->CommandStatus != CMD_DATA_UNDERRUN) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001081 cciss_scsi_interpret_error(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 rc = -1;
1083 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001084 spin_lock_irqsave(&h->lock, flags);
1085 scsi_cmd_free(h, c);
1086 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 return rc;
1088}
1089
1090static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001091cciss_update_non_disk_devices(ctlr_info_t *h, int hostno)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092{
1093 /* the idea here is we could get notified from /proc
1094 that some devices have changed, so we do a report
1095 physical luns cmd, and adjust our list of devices
1096 accordingly. (We can't rely on the scsi-mid layer just
1097 doing inquiries, because the "busses" that the scsi
1098 mid-layer probes are totally fabricated by this driver,
1099 so new devices wouldn't show up.
1100
1101 the scsi3addr's of devices won't change so long as the
1102 adapter is not reset. That means we can rescan and
1103 tell which devices we already know about, vs. new
1104 devices, vs. disappearing devices.
1105
1106 Also, if you yank out a tape drive, then put in a disk
1107 in it's place, (say, a configured volume from another
1108 array controller for instance) _don't_ poke this driver
1109 (so it thinks it's still a tape, but _do_ poke the scsi
1110 mid layer, so it does an inquiry... the scsi mid layer
1111 will see the physical disk. This would be bad. Need to
1112 think about how to prevent that. One idea would be to
1113 snoop all scsi responses and if an inquiry repsonse comes
1114 back that reports a disk, chuck it an return selection
1115 timeout instead and adjust our table... Not sure i like
1116 that though.
1117
1118 */
Mike Miller47922d02005-09-13 01:25:25 -07001119#define OBDR_TAPE_INQ_SIZE 49
1120#define OBDR_TAPE_SIG "$DR-10"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 ReportLunData_struct *ld_buff;
Mike Miller47922d02005-09-13 01:25:25 -07001122 unsigned char *inq_buff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 unsigned char scsi3addr[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 __u32 num_luns=0;
1125 unsigned char *ch;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001126 struct cciss_scsi_dev_t *currentsd, *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 int ncurrent=0;
1128 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
1129 int i;
1130
Eric Sesterhenn06ff37f2006-03-08 11:21:52 +01001131 ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
Mike Miller47922d02005-09-13 01:25:25 -07001132 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001133 currentsd = kzalloc(sizeof(*currentsd) *
1134 (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL);
1135 if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) {
1136 printk(KERN_ERR "cciss: out of memory\n");
1137 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001139 this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001140 if (cciss_scsi_do_report_phys_luns(h, ld_buff, reportlunsize) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 ch = &ld_buff->LUNListLength[0];
1142 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8;
1143 if (num_luns > CISS_MAX_PHYS_LUN) {
1144 printk(KERN_WARNING
1145 "cciss: Maximum physical LUNs (%d) exceeded. "
1146 "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN,
1147 num_luns - CISS_MAX_PHYS_LUN);
1148 num_luns = CISS_MAX_PHYS_LUN;
1149 }
1150 }
1151 else {
1152 printk(KERN_ERR "cciss: Report physical LUNs failed.\n");
1153 goto out;
1154 }
1155
1156
1157 /* adjust our table of devices */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001158 for (i = 0; i < num_luns; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 /* for each physical lun, do an inquiry */
1160 if (ld_buff->LUN[i][3] & 0xC0) continue;
Mike Miller47922d02005-09-13 01:25:25 -07001161 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
1163
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001164 if (cciss_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001165 (unsigned char) OBDR_TAPE_INQ_SIZE) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 /* Inquiry failed (msg printed already) */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001167 continue; /* so we will skip this device. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001169 this_device->devtype = (inq_buff[0] & 0x1f);
1170 this_device->bus = -1;
1171 this_device->target = -1;
1172 this_device->lun = -1;
1173 memcpy(this_device->scsi3addr, scsi3addr, 8);
1174 memcpy(this_device->vendor, &inq_buff[8],
1175 sizeof(this_device->vendor));
1176 memcpy(this_device->model, &inq_buff[16],
1177 sizeof(this_device->model));
1178 memcpy(this_device->revision, &inq_buff[32],
1179 sizeof(this_device->revision));
1180 memset(this_device->device_id, 0,
1181 sizeof(this_device->device_id));
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001182 cciss_scsi_get_device_id(h, scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001183 this_device->device_id, sizeof(this_device->device_id));
1184
1185 switch (this_device->devtype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 {
Mike Miller47922d02005-09-13 01:25:25 -07001187 case 0x05: /* CD-ROM */ {
1188
1189 /* We don't *really* support actual CD-ROM devices,
1190 * just this "One Button Disaster Recovery" tape drive
1191 * which temporarily pretends to be a CD-ROM drive.
1192 * So we check that the device is really an OBDR tape
1193 * device by checking for "$DR-10" in bytes 43-48 of
1194 * the inquiry data.
1195 */
1196 char obdr_sig[7];
1197
1198 strncpy(obdr_sig, &inq_buff[43], 6);
1199 obdr_sig[6] = '\0';
1200 if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
1201 /* Not OBDR device, ignore it. */
1202 break;
1203 }
1204 /* fall through . . . */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 case 0x01: /* sequential access, (tape) */
1206 case 0x08: /* medium changer */
1207 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
1208 printk(KERN_INFO "cciss%d: %s ignored, "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001209 "too many devices.\n", h->ctlr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001210 scsi_device_type(this_device->devtype));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 break;
1212 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001213 currentsd[ncurrent] = *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 ncurrent++;
1215 break;
1216 default:
1217 break;
1218 }
1219 }
1220
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001221 adjust_cciss_scsi_table(h, hostno, currentsd, ncurrent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222out:
1223 kfree(inq_buff);
1224 kfree(ld_buff);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001225 kfree(currentsd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 return;
1227}
1228
1229static int
1230is_keyword(char *ptr, int len, char *verb) // Thanks to ncr53c8xx.c
1231{
1232 int verb_len = strlen(verb);
1233 if (len >= verb_len && !memcmp(verb,ptr,verb_len))
1234 return verb_len;
1235 else
1236 return 0;
1237}
1238
1239static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001240cciss_scsi_user_command(ctlr_info_t *h, int hostno, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241{
1242 int arg_len;
1243
1244 if ((arg_len = is_keyword(buffer, length, "rescan")) != 0)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001245 cciss_update_non_disk_devices(h, hostno);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 else
1247 return -EINVAL;
1248 return length;
1249}
1250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251static int
Al Viroe88b7bb2013-03-31 02:00:06 -04001252cciss_scsi_write_info(struct Scsi_Host *sh,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 char *buffer, /* data buffer */
Al Viroe88b7bb2013-03-31 02:00:06 -04001254 int length) /* length of data in buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255{
Al Viroe88b7bb2013-03-31 02:00:06 -04001256 ctlr_info_t *h = (ctlr_info_t *) sh->hostdata[0];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001257 if (h == NULL) /* This really shouldn't ever happen. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 return -EINVAL;
1259
Al Viroe88b7bb2013-03-31 02:00:06 -04001260 return cciss_scsi_user_command(h, sh->host_no,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 buffer, length);
1262}
1263
Al Viroe88b7bb2013-03-31 02:00:06 -04001264static int
1265cciss_scsi_show_info(struct seq_file *m, struct Scsi_Host *sh)
1266{
1267
1268 ctlr_info_t *h = (ctlr_info_t *) sh->hostdata[0];
1269 int i;
1270
1271 if (h == NULL) /* This really shouldn't ever happen. */
1272 return -EINVAL;
1273
1274 seq_printf(m, "cciss%d: SCSI host: %d\n",
1275 h->ctlr, sh->host_no);
1276
1277 /* this information is needed by apps to know which cciss
1278 device corresponds to which scsi host number without
1279 having to open a scsi target device node. The device
1280 information is not a duplicate of /proc/scsi/scsi because
1281 the two may be out of sync due to scsi hotplug, rather
1282 this info is for an app to be able to use to know how to
1283 get them back in sync. */
1284
1285 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
1286 struct cciss_scsi_dev_t *sd =
1287 &ccissscsi[h->ctlr].dev[i];
1288 seq_printf(m, "c%db%dt%dl%d %02d "
1289 "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
1290 sh->host_no, sd->bus, sd->target, sd->lun,
1291 sd->devtype,
1292 sd->scsi3addr[0], sd->scsi3addr[1],
1293 sd->scsi3addr[2], sd->scsi3addr[3],
1294 sd->scsi3addr[4], sd->scsi3addr[5],
1295 sd->scsi3addr[6], sd->scsi3addr[7]);
1296 }
1297 return 0;
1298}
1299
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300/* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
1301 dma mapping and fills in the scatter gather entries of the
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001302 cciss command, c. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001304static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c,
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001305 struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306{
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001307 unsigned int len;
1308 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 __u64 addr64;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001310 int request_nsgs, i, chained, sg_index;
1311 struct cciss_scsi_adapter_data_t *sa = h->scsi_ctlr;
1312 SGDescriptor_struct *curr_sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001314 BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001316 chained = 0;
1317 sg_index = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001318 curr_sg = c->SG;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001319 request_nsgs = scsi_dma_map(cmd);
1320 if (request_nsgs) {
1321 scsi_for_each_sg(cmd, sg, request_nsgs, i) {
1322 if (sg_index + 1 == h->max_cmd_sgentries &&
1323 !chained && request_nsgs - i > 1) {
1324 chained = 1;
1325 sg_index = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001326 curr_sg = sa->cmd_sg_list[c->cmdindex];
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001327 }
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001328 addr64 = (__u64) sg_dma_address(sg);
1329 len = sg_dma_len(sg);
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001330 curr_sg[sg_index].Addr.lower =
1331 (__u32) (addr64 & 0x0FFFFFFFFULL);
1332 curr_sg[sg_index].Addr.upper =
1333 (__u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
1334 curr_sg[sg_index].Len = len;
1335 curr_sg[sg_index].Ext = 0;
1336 ++sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 }
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001338 if (chained)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001339 cciss_map_sg_chain_block(h, c,
1340 sa->cmd_sg_list[c->cmdindex],
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001341 (request_nsgs - (h->max_cmd_sgentries - 1)) *
1342 sizeof(SGDescriptor_struct));
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001343 }
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001344 /* track how many SG entries we are using */
1345 if (request_nsgs > h->maxSG)
1346 h->maxSG = request_nsgs;
Stephen M. Cameronbc67f632012-03-22 21:40:09 +01001347 c->Header.SGTotal = (u16) request_nsgs + chained;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001348 if (request_nsgs > h->max_cmd_sgentries)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001349 c->Header.SGList = h->max_cmd_sgentries;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001350 else
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001351 c->Header.SGList = c->Header.SGTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 return;
1353}
1354
1355
1356static int
Jeff Garzikf2812332010-11-16 02:10:29 -05001357cciss_scsi_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001359 ctlr_info_t *h;
1360 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 unsigned char scsi3addr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001362 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 unsigned long flags;
1364
1365 // Get the ptr to our adapter structure (hba[i]) out of cmd->host.
1366 // We violate cmd->host privacy here. (Is there another way?)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001367 h = (ctlr_info_t *) cmd->device->host->hostdata[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001369 rc = lookup_scsi3addr(h, cmd->device->channel, cmd->device->id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 cmd->device->lun, scsi3addr);
1371 if (rc != 0) {
1372 /* the scsi nexus does not match any that we presented... */
1373 /* pretend to mid layer that we got selection timeout */
1374 cmd->result = DID_NO_CONNECT << 16;
1375 done(cmd);
1376 /* we might want to think about registering controller itself
1377 as a processor device on the bus so sg binds to it. */
1378 return 0;
1379 }
1380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 /* Ok, we have a reasonable scsi nexus, so send the cmd down, and
1382 see what the device thinks of it. */
1383
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001384 spin_lock_irqsave(&h->lock, flags);
1385 c = scsi_cmd_alloc(h);
1386 spin_unlock_irqrestore(&h->lock, flags);
1387 if (c == NULL) { /* trouble... */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001388 dev_warn(&h->pdev->dev, "scsi_cmd_alloc returned NULL!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 /* FIXME: next 3 lines are -> BAD! <- */
1390 cmd->result = DID_NO_CONNECT << 16;
1391 done(cmd);
1392 return 0;
1393 }
1394
1395 // Fill in the command list header
1396
1397 cmd->scsi_done = done; // save this for use by completion code
1398
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001399 /* save c in case we have to abort it */
1400 cmd->host_scribble = (unsigned char *) c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001402 c->cmd_type = CMD_SCSI;
1403 c->scsi_cmd = cmd;
1404 c->Header.ReplyQueue = 0; /* unused in simple mode */
1405 memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
1406 c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
1408 // Fill in the request block...
1409
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001410 c->Request.Timeout = 0;
1411 memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
1412 BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
1413 c->Request.CDBLen = cmd->cmd_len;
1414 memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len);
1415 c->Request.Type.Type = TYPE_CMD;
1416 c->Request.Type.Attribute = ATTR_SIMPLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 switch(cmd->sc_data_direction)
1418 {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001419 case DMA_TO_DEVICE:
1420 c->Request.Type.Direction = XFER_WRITE;
1421 break;
1422 case DMA_FROM_DEVICE:
1423 c->Request.Type.Direction = XFER_READ;
1424 break;
1425 case DMA_NONE:
1426 c->Request.Type.Direction = XFER_NONE;
1427 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 case DMA_BIDIRECTIONAL:
1429 // This can happen if a buggy application does a scsi passthru
1430 // and sets both inlen and outlen to non-zero. ( see
1431 // ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
1432
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001433 c->Request.Type.Direction = XFER_RSVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 // This is technically wrong, and cciss controllers should
1435 // reject it with CMD_INVALID, which is the most correct
1436 // response, but non-fibre backends appear to let it
1437 // slide by, and give the same results as if this field
1438 // were set correctly. Either way is acceptable for
1439 // our purposes here.
1440
1441 break;
1442
1443 default:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001444 dev_warn(&h->pdev->dev, "unknown data direction: %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 cmd->sc_data_direction);
1446 BUG();
1447 break;
1448 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001449 cciss_scatter_gather(h, c, cmd);
1450 enqueue_cmd_and_start_io(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 /* the cmd'll come back via intr handler in complete_scsi_command() */
1452 return 0;
1453}
1454
Jeff Garzikf2812332010-11-16 02:10:29 -05001455static DEF_SCSI_QCMD(cciss_scsi_queue_command)
1456
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001457static void cciss_unregister_scsi(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458{
1459 struct cciss_scsi_adapter_data_t *sa;
1460 struct cciss_scsi_cmd_stack_t *stk;
1461 unsigned long flags;
1462
1463 /* we are being forcibly unloaded, and may not refuse. */
1464
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001465 spin_lock_irqsave(&h->lock, flags);
1466 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 stk = &sa->cmd_stack;
1468
1469 /* if we weren't ever actually registered, don't unregister */
1470 if (sa->registered) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001471 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 scsi_remove_host(sa->scsi_host);
1473 scsi_host_put(sa->scsi_host);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001474 spin_lock_irqsave(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 }
1476
1477 /* set scsi_host to NULL so our detect routine will
1478 find us on register */
1479 sa->scsi_host = NULL;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001480 spin_unlock_irqrestore(&h->lock, flags);
1481 scsi_cmd_stack_free(h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 kfree(sa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483}
1484
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001485static int cciss_engage_scsi(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486{
1487 struct cciss_scsi_adapter_data_t *sa;
1488 struct cciss_scsi_cmd_stack_t *stk;
1489 unsigned long flags;
1490
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001491 spin_lock_irqsave(&h->lock, flags);
1492 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 stk = &sa->cmd_stack;
1494
Mike Millerf4a93bc2008-08-04 11:54:53 +02001495 if (sa->registered) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001496 dev_info(&h->pdev->dev, "SCSI subsystem already engaged.\n");
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001497 spin_unlock_irqrestore(&h->lock, flags);
Stephen M. Cameron8721c812009-11-12 12:50:06 -06001498 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 }
Mike Millerf4a93bc2008-08-04 11:54:53 +02001500 sa->registered = 1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001501 spin_unlock_irqrestore(&h->lock, flags);
1502 cciss_update_non_disk_devices(h, -1);
1503 cciss_scsi_detect(h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 return 0;
1505}
1506
1507static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001508cciss_seq_tape_report(struct seq_file *seq, ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509{
1510 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001512 CPQ_TAPE_LOCK(h, flags);
Mike Miller89b6e742008-02-21 08:54:03 +01001513 seq_printf(seq,
Mike Millerb9f0bd02005-09-13 01:25:26 -07001514 "Sequential access devices: %d\n\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001515 ccissscsi[h->ctlr].ndevices);
1516 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517}
1518
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001519static int wait_for_device_to_become_ready(ctlr_info_t *h,
1520 unsigned char lunaddr[])
1521{
1522 int rc;
1523 int count = 0;
1524 int waittime = HZ;
1525 CommandList_struct *c;
1526
Stephen M. Cameron6b4d96b2010-07-19 13:46:43 -05001527 c = cmd_alloc(h);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001528 if (!c) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001529 dev_warn(&h->pdev->dev, "out of memory in "
1530 "wait_for_device_to_become_ready.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001531 return IO_ERROR;
1532 }
1533
1534 /* Send test unit ready until device ready, or give up. */
1535 while (count < 20) {
1536
1537 /* Wait for a bit. do this first, because if we send
1538 * the TUR right away, the reset will just abort it.
1539 */
scameron@beardog.cca.cpqcorp.net40df6ae2009-06-08 15:59:38 -05001540 schedule_timeout_uninterruptible(waittime);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001541 count++;
1542
1543 /* Increase wait time with each try, up to a point. */
1544 if (waittime < (HZ * 30))
1545 waittime = waittime * 2;
1546
1547 /* Send the Test Unit Ready */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001548 rc = fill_cmd(h, c, TEST_UNIT_READY, NULL, 0, 0,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001549 lunaddr, TYPE_CMD);
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001550 if (rc == 0)
1551 rc = sendcmd_withirq_core(h, c, 0);
1552
1553 (void) process_sendcmd_error(h, c);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001554
scameron@beardog.cca.cpqcorp.net39692512009-06-08 16:10:57 -05001555 if (rc != 0)
1556 goto retry_tur;
1557
1558 if (c->err_info->CommandStatus == CMD_SUCCESS)
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001559 break;
1560
scameron@beardog.cca.cpqcorp.net39692512009-06-08 16:10:57 -05001561 if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
1562 c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
1563 if (c->err_info->SenseInfo[2] == NO_SENSE)
1564 break;
1565 if (c->err_info->SenseInfo[2] == UNIT_ATTENTION) {
1566 unsigned char asc;
1567 asc = c->err_info->SenseInfo[12];
1568 check_for_unit_attention(h, c);
1569 if (asc == POWER_OR_RESET)
1570 break;
1571 }
1572 }
1573retry_tur:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001574 dev_warn(&h->pdev->dev, "Waiting %d secs "
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001575 "for device to become ready.\n",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001576 waittime / HZ);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001577 rc = 1; /* device not ready. */
1578 }
1579
1580 if (rc)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001581 dev_warn(&h->pdev->dev, "giving up on device.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001582 else
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001583 dev_warn(&h->pdev->dev, "device is ready.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001584
Stephen M. Cameron6b4d96b2010-07-19 13:46:43 -05001585 cmd_free(h, c);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001586 return rc;
1587}
Mike Miller89b6e742008-02-21 08:54:03 +01001588
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001589/* Need at least one of these error handlers to keep ../scsi/hosts.c from
1590 * complaining. Doing a host- or bus-reset can't do anything good here.
1591 * Despite what it might say in scsi_error.c, there may well be commands
1592 * on the controller, as the cciss driver registers twice, once as a block
1593 * device for the logical drives, and once as a scsi device, for any tape
1594 * drives. So we know there are no commands out on the tape drives, but we
1595 * don't know there are no commands on the controller, and it is likely
1596 * that there probably are, as the cciss block device is most commonly used
1597 * as a boot device (embedded controller on HP/Compaq systems.)
1598*/
1599
1600static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
1601{
1602 int rc;
1603 CommandList_struct *cmd_in_trouble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001604 unsigned char lunaddr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001605 ctlr_info_t *h;
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001606
1607 /* find the controller to which the command to be aborted was sent */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001608 h = (ctlr_info_t *) scsicmd->device->host->hostdata[0];
1609 if (h == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001610 return FAILED;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001611 dev_warn(&h->pdev->dev, "resetting tape drive or medium changer.\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001612 /* find the command that's giving us trouble */
1613 cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001614 if (cmd_in_trouble == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001615 return FAILED;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001616 memcpy(lunaddr, &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 8);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001617 /* send a reset to the SCSI LUN which the command was sent to */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001618 rc = sendcmd_withirq(h, CCISS_RESET_MSG, NULL, 0, 0, lunaddr,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001619 TYPE_MSG);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001620 if (rc == 0 && wait_for_device_to_become_ready(h, lunaddr) == 0)
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001621 return SUCCESS;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001622 dev_warn(&h->pdev->dev, "resetting device failed.\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001623 return FAILED;
1624}
1625
1626static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
1627{
1628 int rc;
1629 CommandList_struct *cmd_to_abort;
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001630 unsigned char lunaddr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001631 ctlr_info_t *h;
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001632
1633 /* find the controller to which the command to be aborted was sent */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001634 h = (ctlr_info_t *) scsicmd->device->host->hostdata[0];
1635 if (h == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001636 return FAILED;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001637 dev_warn(&h->pdev->dev, "aborting tardy SCSI cmd\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001638
1639 /* find the command to be aborted */
1640 cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble;
1641 if (cmd_to_abort == NULL) /* paranoia */
1642 return FAILED;
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001643 memcpy(lunaddr, &cmd_to_abort->Header.LUN.LunAddrBytes[0], 8);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001644 rc = sendcmd_withirq(h, CCISS_ABORT_MSG, &cmd_to_abort->Header.Tag,
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001645 0, 0, lunaddr, TYPE_MSG);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001646 if (rc == 0)
1647 return SUCCESS;
1648 return FAILED;
1649
1650}
1651
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652#else /* no CONFIG_CISS_SCSI_TAPE */
1653
1654/* If no tape support, then these become defined out of existence */
1655
1656#define cciss_scsi_setup(cntl_num)
Stephen M. Cameron0007a4c2011-11-16 09:21:49 +01001657#define cciss_engage_scsi(h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658
1659#endif /* CONFIG_CISS_SCSI_TAPE */