blob: 9e9144860fa50416bfdb9690408926888b7835fd [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Adaptec AAC series RAID controller driver
Alan Coxfa195af2008-10-27 15:16:36 +00003 * (c) Copyright 2001 Red Hat Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * based on the old aacraid driver that is..
6 * Adaptec aacraid device driver for Linux.
7 *
Mahesh Rajashekharae8b12f02011-03-17 02:10:32 -07008 * Copyright (c) 2000-2010 Adaptec, Inc.
9 * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27#include <linux/kernel.h>
28#include <linux/init.h>
29#include <linux/types.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/pci.h>
31#include <linux/spinlock.h>
32#include <linux/slab.h>
33#include <linux/completion.h>
34#include <linux/blkdev.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080035#include <linux/uaccess.h>
Salyzyn, Mark3a0086a2008-01-11 11:46:44 -080036#include <linux/highmem.h> /* For flush_kernel_dcache_page */
Paul Gortmakeracf3368f2011-05-27 09:47:43 -040037#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
39#include <scsi/scsi.h>
40#include <scsi/scsi_cmnd.h>
41#include <scsi/scsi_device.h>
42#include <scsi/scsi_host.h>
43
44#include "aacraid.h"
45
46/* values for inqd_pdt: Peripheral device type in plain English */
47#define INQD_PDT_DA 0x00 /* Direct-access (DISK) device */
48#define INQD_PDT_PROC 0x03 /* Processor device */
49#define INQD_PDT_CHNGR 0x08 /* Changer (jukebox, scsi2) */
50#define INQD_PDT_COMM 0x09 /* Communication device (scsi2) */
51#define INQD_PDT_NOLUN2 0x1f /* Unknown Device (scsi2) */
52#define INQD_PDT_NOLUN 0x7f /* Logical Unit Not Present */
53
54#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */
55#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */
56
Linus Torvalds1da177e2005-04-16 15:20:36 -070057/*
58 * Sense codes
59 */
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -080060
61#define SENCODE_NO_SENSE 0x00
62#define SENCODE_END_OF_DATA 0x00
63#define SENCODE_BECOMING_READY 0x04
64#define SENCODE_INIT_CMD_REQUIRED 0x04
Raghava Aditya Renukuntaf956a662017-02-02 15:53:23 -080065#define SENCODE_UNRECOVERED_READ_ERROR 0x11
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -080066#define SENCODE_PARAM_LIST_LENGTH_ERROR 0x1A
67#define SENCODE_INVALID_COMMAND 0x20
68#define SENCODE_LBA_OUT_OF_RANGE 0x21
69#define SENCODE_INVALID_CDB_FIELD 0x24
70#define SENCODE_LUN_NOT_SUPPORTED 0x25
71#define SENCODE_INVALID_PARAM_FIELD 0x26
72#define SENCODE_PARAM_NOT_SUPPORTED 0x26
73#define SENCODE_PARAM_VALUE_INVALID 0x26
74#define SENCODE_RESET_OCCURRED 0x29
75#define SENCODE_LUN_NOT_SELF_CONFIGURED_YET 0x3E
76#define SENCODE_INQUIRY_DATA_CHANGED 0x3F
77#define SENCODE_SAVING_PARAMS_NOT_SUPPORTED 0x39
78#define SENCODE_DIAGNOSTIC_FAILURE 0x40
79#define SENCODE_INTERNAL_TARGET_FAILURE 0x44
80#define SENCODE_INVALID_MESSAGE_ERROR 0x49
81#define SENCODE_LUN_FAILED_SELF_CONFIG 0x4c
82#define SENCODE_OVERLAPPED_COMMAND 0x4E
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
84/*
85 * Additional sense codes
86 */
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -080087
88#define ASENCODE_NO_SENSE 0x00
89#define ASENCODE_END_OF_DATA 0x05
90#define ASENCODE_BECOMING_READY 0x01
91#define ASENCODE_INIT_CMD_REQUIRED 0x02
92#define ASENCODE_PARAM_LIST_LENGTH_ERROR 0x00
93#define ASENCODE_INVALID_COMMAND 0x00
94#define ASENCODE_LBA_OUT_OF_RANGE 0x00
95#define ASENCODE_INVALID_CDB_FIELD 0x00
96#define ASENCODE_LUN_NOT_SUPPORTED 0x00
97#define ASENCODE_INVALID_PARAM_FIELD 0x00
98#define ASENCODE_PARAM_NOT_SUPPORTED 0x01
99#define ASENCODE_PARAM_VALUE_INVALID 0x02
100#define ASENCODE_RESET_OCCURRED 0x00
101#define ASENCODE_LUN_NOT_SELF_CONFIGURED_YET 0x00
102#define ASENCODE_INQUIRY_DATA_CHANGED 0x03
103#define ASENCODE_SAVING_PARAMS_NOT_SUPPORTED 0x00
104#define ASENCODE_DIAGNOSTIC_FAILURE 0x80
105#define ASENCODE_INTERNAL_TARGET_FAILURE 0x00
106#define ASENCODE_INVALID_MESSAGE_ERROR 0x00
107#define ASENCODE_LUN_FAILED_SELF_CONFIG 0x00
108#define ASENCODE_OVERLAPPED_COMMAND 0x00
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -0800110#define AAC_STAT_GOOD (DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD)
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112#define BYTE0(x) (unsigned char)(x)
113#define BYTE1(x) (unsigned char)((x) >> 8)
114#define BYTE2(x) (unsigned char)((x) >> 16)
115#define BYTE3(x) (unsigned char)((x) >> 24)
116
Mahesh Rajashekharab8364392015-03-26 10:41:24 -0400117/* MODE_SENSE data format */
118typedef struct {
119 struct {
120 u8 data_length;
121 u8 med_type;
122 u8 dev_par;
123 u8 bd_length;
124 } __attribute__((packed)) hd;
125 struct {
126 u8 dens_code;
127 u8 block_count[3];
128 u8 reserved;
129 u8 block_length[3];
130 } __attribute__((packed)) bd;
131 u8 mpc_buf[3];
132} __attribute__((packed)) aac_modep_data;
133
134/* MODE_SENSE_10 data format */
135typedef struct {
136 struct {
137 u8 data_length[2];
138 u8 med_type;
139 u8 dev_par;
140 u8 rsrvd[2];
141 u8 bd_length[2];
142 } __attribute__((packed)) hd;
143 struct {
144 u8 dens_code;
145 u8 block_count[3];
146 u8 reserved;
147 u8 block_length[3];
148 } __attribute__((packed)) bd;
149 u8 mpc_buf[3];
150} __attribute__((packed)) aac_modep10_data;
151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152/*------------------------------------------------------------------------------
153 * S T R U C T S / T Y P E D E F S
154 *----------------------------------------------------------------------------*/
155/* SCSI inquiry data */
156struct inquiry_data {
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800157 u8 inqd_pdt; /* Peripheral qualifier | Peripheral Device Type */
158 u8 inqd_dtq; /* RMB | Device Type Qualifier */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 u8 inqd_ver; /* ISO version | ECMA version | ANSI-approved version */
160 u8 inqd_rdf; /* AENC | TrmIOP | Response data format */
161 u8 inqd_len; /* Additional length (n-4) */
162 u8 inqd_pad1[2];/* Reserved - must be zero */
163 u8 inqd_pad2; /* RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */
164 u8 inqd_vid[8]; /* Vendor ID */
165 u8 inqd_pid[16];/* Product ID */
166 u8 inqd_prl[4]; /* Product Revision Level */
167};
168
Mahesh Rajashekhara5d910642015-03-26 10:41:26 -0400169/* Added for VPD 0x83 */
170typedef struct {
171 u8 CodeSet:4; /* VPD_CODE_SET */
172 u8 Reserved:4;
173 u8 IdentifierType:4; /* VPD_IDENTIFIER_TYPE */
174 u8 Reserved2:4;
175 u8 Reserved3;
176 u8 IdentifierLength;
177 u8 VendId[8];
178 u8 ProductId[16];
179 u8 SerialNumber[8]; /* SN in ASCII */
180
181} TVPD_ID_Descriptor_Type_1;
182
183typedef struct {
184 u8 CodeSet:4; /* VPD_CODE_SET */
185 u8 Reserved:4;
186 u8 IdentifierType:4; /* VPD_IDENTIFIER_TYPE */
187 u8 Reserved2:4;
188 u8 Reserved3;
189 u8 IdentifierLength;
190 struct TEU64Id {
191 u32 Serial;
192 /* The serial number supposed to be 40 bits,
193 * bit we only support 32, so make the last byte zero. */
194 u8 Reserved;
195 u8 VendId[3];
196 } EU64Id;
197
198} TVPD_ID_Descriptor_Type_2;
199
200typedef struct {
201 u8 DeviceType:5;
202 u8 DeviceTypeQualifier:3;
203 u8 PageCode;
204 u8 Reserved;
205 u8 PageLength;
206 TVPD_ID_Descriptor_Type_1 IdDescriptorType1;
207 TVPD_ID_Descriptor_Type_2 IdDescriptorType2;
208
209} TVPD_Page83;
210
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211/*
212 * M O D U L E G L O B A L S
213 */
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800214
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +0530215static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *sgmap);
216static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg);
217static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg);
218static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
219 struct aac_raw_io2 *rio2, int sg_max);
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -0800220static long aac_build_sghba(struct scsi_cmnd *scsicmd,
221 struct aac_hba_cmd_req *hbacmd,
222 int sg_max, u64 sg_address);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +0530223static int aac_convert_sgraw2(struct aac_raw_io2 *rio2,
224 int pages, int nseg, int nseg_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -0800226static int aac_send_hba_fib(struct scsi_cmnd *scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227#ifdef AAC_DETAILED_STATUS_INFO
228static char *aac_get_status_string(u32 status);
229#endif
230
231/*
232 * Non dasd selection is handled entirely in aachba now
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800233 */
234
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235static int nondasd = -1;
Leubner, Achimd8e965072009-04-01 07:16:08 -0700236static int aac_cache = 2; /* WCE=0 to avoid performance problems */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237static int dacmode = -1;
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800238int aac_msi;
Salyzyn, Mark1208bab2007-05-22 09:32:29 -0400239int aac_commit = -1;
Mark Haverkamp404d9a92006-05-10 09:12:48 -0700240int startup_timeout = 180;
241int aif_timeout = 120;
Mahesh Rajashekhara11604612012-02-08 22:51:04 -0800242int aac_sync_mode; /* Only Sync. transfer - disabled */
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +0530243int aac_convert_sgl = 1; /* convert non-conformable s/g list - enabled */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
Mahesh Rajashekhara11604612012-02-08 22:51:04 -0800245module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR);
246MODULE_PARM_DESC(aac_sync_mode, "Force sync. transfer mode"
247 " 0=off, 1=on");
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +0530248module_param(aac_convert_sgl, int, S_IRUGO|S_IWUSR);
249MODULE_PARM_DESC(aac_convert_sgl, "Convert non-conformable s/g list"
250 " 0=off, 1=on");
Mark Haverkamp9a72f972006-03-27 09:44:37 -0800251module_param(nondasd, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800252MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices."
253 " 0=off, 1=on");
Salyzyn, Mark95e852e2008-01-08 12:01:07 -0800254module_param_named(cache, aac_cache, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800255MODULE_PARM_DESC(cache, "Disable Queue Flush commands:\n"
256 "\tbit 0 - Disable FUA in WRITE SCSI commands\n"
257 "\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command\n"
Leubner, Achimd8e965072009-04-01 07:16:08 -0700258 "\tbit 2 - Disable only if Battery is protecting Cache");
Mark Haverkamp9a72f972006-03-27 09:44:37 -0800259module_param(dacmode, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800260MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC."
261 " 0=off, 1=on");
Salyzyn, Mark1208bab2007-05-22 09:32:29 -0400262module_param_named(commit, aac_commit, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800263MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the"
264 " adapter for foreign arrays.\n"
265 "This is typically needed in systems that do not have a BIOS."
266 " 0=off, 1=on");
267module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
268MODULE_PARM_DESC(msi, "IRQ handling."
Mahesh Rajashekhara9022d372015-08-28 06:38:35 -0400269 " 0=PIC(default), 1=MSI, 2=MSI-X)");
Mark Haverkamp404d9a92006-05-10 09:12:48 -0700270module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800271MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for"
272 " adapter to have it's kernel up and\n"
273 "running. This is typically adjusted for large systems that do not"
274 " have a BIOS.");
Mark Haverkamp404d9a92006-05-10 09:12:48 -0700275module_param(aif_timeout, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800276MODULE_PARM_DESC(aif_timeout, "The duration of time in seconds to wait for"
277 " applications to pick up AIFs before\n"
278 "deregistering them. This is typically adjusted for heavily burdened"
279 " systems.");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -0700281int numacb = -1;
282module_param(numacb, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800283MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control"
284 " blocks (FIB) allocated. Valid values are 512 and down. Default is"
285 " to use suggestion from Firmware.");
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -0700286
287int acbsize = -1;
288module_param(acbsize, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800289MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB)"
290 " size. Valid values are 512, 2048, 4096 and 8192. Default is to use"
291 " suggestion from Firmware.");
Mark Haverkamp653ba582006-09-19 08:59:43 -0700292
Salyzyn, Mark29c97682007-06-12 09:33:54 -0400293int update_interval = 30 * 60;
294module_param(update_interval, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800295MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync"
296 " updates issued to adapter.");
Salyzyn, Mark29c97682007-06-12 09:33:54 -0400297
298int check_interval = 24 * 60 * 60;
299module_param(check_interval, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800300MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health"
301 " checks.");
Salyzyn, Mark29c97682007-06-12 09:33:54 -0400302
Andrew Morton87f3bda2007-08-10 14:50:30 -0700303int aac_check_reset = 1;
304module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
Paul Bolle95e7a8e2008-04-16 14:43:00 +0200305MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the"
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800306 " adapter. a value of -1 forces the reset to adapters programmed to"
307 " ignore it.");
Salyzyn, Mark29c97682007-06-12 09:33:54 -0400308
Mark Haverkampe37ee4b2007-01-26 09:23:32 -0800309int expose_physicals = -1;
Mark Haverkamp653ba582006-09-19 08:59:43 -0700310module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800311MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays."
312 " -1=protect 0=off, 1=on");
Mark Haverkamp03d44332007-03-15 10:27:45 -0700313
Salyzyn, Mark8ef22242008-02-08 05:48:22 -0800314int aac_reset_devices;
Salyzyn, Mark1208bab2007-05-22 09:32:29 -0400315module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
316MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
Mark Haverkamp03d44332007-03-15 10:27:45 -0700317
Leubner, Achimd8e965072009-04-01 07:16:08 -0700318int aac_wwn = 1;
319module_param_named(wwn, aac_wwn, int, S_IRUGO|S_IWUSR);
320MODULE_PARM_DESC(wwn, "Select a WWN type for the arrays:\n"
321 "\t0 - Disable\n"
322 "\t1 - Array Meta Data Signature (default)\n"
323 "\t2 - Adapter Serial Number");
324
325
Mark Haverkamp03d44332007-03-15 10:27:45 -0700326static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
327 struct fib *fibptr) {
328 struct scsi_device *device;
329
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800330 if (unlikely(!scsicmd || !scsicmd->scsi_done)) {
Salyzyn, Markc835e372007-07-26 14:20:02 -0400331 dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n"));
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800332 aac_fib_complete(fibptr);
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800333 return 0;
334 }
Mark Haverkamp03d44332007-03-15 10:27:45 -0700335 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
336 device = scsicmd->device;
Raghava Aditya Renukunta3ffd6c52017-02-02 15:53:22 -0800337 if (unlikely(!device)) {
Mark Haverkamp03d44332007-03-15 10:27:45 -0700338 dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n"));
339 aac_fib_complete(fibptr);
Mark Haverkamp03d44332007-03-15 10:27:45 -0700340 return 0;
341 }
342 return 1;
343}
344
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345/**
346 * aac_get_config_status - check the adapter configuration
347 * @common: adapter to query
348 *
349 * Query config status, and commit the configuration if needed.
350 */
Mark Haverkamp8c867b22006-08-03 08:03:30 -0700351int aac_get_config_status(struct aac_dev *dev, int commit_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352{
353 int status = 0;
354 struct fib * fibptr;
355
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800356 if (!(fibptr = aac_fib_alloc(dev)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 return -ENOMEM;
358
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800359 aac_fib_init(fibptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 {
361 struct aac_get_config_status *dinfo;
362 dinfo = (struct aac_get_config_status *) fib_data(fibptr);
363
364 dinfo->command = cpu_to_le32(VM_ContainerConfig);
365 dinfo->type = cpu_to_le32(CT_GET_CONFIG_STATUS);
366 dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data));
367 }
368
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800369 status = aac_fib_send(ContainerCommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 fibptr,
371 sizeof (struct aac_get_config_status),
372 FsaNormal,
373 1, 1,
374 NULL, NULL);
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800375 if (status < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 printk(KERN_WARNING "aac_get_config_status: SendFIB failed.\n");
377 } else {
378 struct aac_get_config_status_resp *reply
379 = (struct aac_get_config_status_resp *) fib_data(fibptr);
380 dprintk((KERN_WARNING
381 "aac_get_config_status: response=%d status=%d action=%d\n",
382 le32_to_cpu(reply->response),
383 le32_to_cpu(reply->status),
384 le32_to_cpu(reply->data.action)));
385 if ((le32_to_cpu(reply->response) != ST_OK) ||
386 (le32_to_cpu(reply->status) != CT_OK) ||
387 (le32_to_cpu(reply->data.action) > CFACT_PAUSE)) {
388 printk(KERN_WARNING "aac_get_config_status: Will not issue the Commit Configuration\n");
389 status = -EINVAL;
390 }
391 }
Penchala Narasimha Reddy Chilakala, ERS-HCLTechcacb6dc2009-12-21 18:39:27 +0530392 /* Do not set XferState to zero unless receives a response from F/W */
393 if (status >= 0)
394 aac_fib_complete(fibptr);
395
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 /* Send a CT_COMMIT_CONFIG to enable discovery of devices */
397 if (status >= 0) {
Salyzyn, Mark1208bab2007-05-22 09:32:29 -0400398 if ((aac_commit == 1) || commit_flag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 struct aac_commit_config * dinfo;
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800400 aac_fib_init(fibptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 dinfo = (struct aac_commit_config *) fib_data(fibptr);
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 dinfo->command = cpu_to_le32(VM_ContainerConfig);
404 dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG);
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800405
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800406 status = aac_fib_send(ContainerCommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 fibptr,
408 sizeof (struct aac_commit_config),
409 FsaNormal,
410 1, 1,
411 NULL, NULL);
Penchala Narasimha Reddy Chilakala, ERS-HCLTechcacb6dc2009-12-21 18:39:27 +0530412 /* Do not set XferState to zero unless
413 * receives a response from F/W */
414 if (status >= 0)
415 aac_fib_complete(fibptr);
Salyzyn, Mark1208bab2007-05-22 09:32:29 -0400416 } else if (aac_commit == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 printk(KERN_WARNING
418 "aac_get_config_status: Foreign device configurations are being ignored\n");
419 }
420 }
Penchala Narasimha Reddy Chilakala, ERS-HCLTechcacb6dc2009-12-21 18:39:27 +0530421 /* FIB should be freed only after getting the response from the F/W */
422 if (status != -ERESTARTSYS)
423 aac_fib_free(fibptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 return status;
425}
426
Rajashekhara, Maheshe3cc2682010-05-10 04:12:28 -0700427static void aac_expose_phy_device(struct scsi_cmnd *scsicmd)
428{
429 char inq_data;
430 scsi_sg_copy_to_buffer(scsicmd, &inq_data, sizeof(inq_data));
431 if ((inq_data & 0x20) && (inq_data & 0x1f) == TYPE_DISK) {
432 inq_data &= 0xdf;
433 scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
434 }
435}
436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437/**
438 * aac_get_containers - list containers
439 * @common: adapter to probe
440 *
441 * Make a list of all containers on this controller
442 */
443int aac_get_containers(struct aac_dev *dev)
444{
445 struct fsa_dev_info *fsa_dev_ptr;
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800446 u32 index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 int status = 0;
448 struct fib * fibptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 struct aac_get_container_count *dinfo;
450 struct aac_get_container_count_resp *dresp;
451 int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
452
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800453 if (!(fibptr = aac_fib_alloc(dev)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 return -ENOMEM;
455
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800456 aac_fib_init(fibptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 dinfo = (struct aac_get_container_count *) fib_data(fibptr);
458 dinfo->command = cpu_to_le32(VM_ContainerConfig);
459 dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT);
460
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800461 status = aac_fib_send(ContainerCommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 fibptr,
463 sizeof (struct aac_get_container_count),
464 FsaNormal,
465 1, 1,
466 NULL, NULL);
467 if (status >= 0) {
468 dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
469 maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
Mahesh Rajashekharaa7129a52015-03-26 10:41:27 -0400470 if (fibptr->dev->supplement_adapter_info.SupportedOptions2 &
471 AAC_OPTION_SUPPORTED_240_VOLUMES) {
472 maximum_num_containers =
473 le32_to_cpu(dresp->MaxSimpleVolumes);
474 }
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800475 aac_fib_complete(fibptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 }
Penchala Narasimha Reddy Chilakala, ERS-HCLTechcacb6dc2009-12-21 18:39:27 +0530477 /* FIB should be freed only after getting the response from the F/W */
478 if (status != -ERESTARTSYS)
479 aac_fib_free(fibptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
481 if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
482 maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
Raghava Aditya Renukunta3ffd6c52017-02-02 15:53:22 -0800483 if (dev->fsa_dev == NULL ||
484 dev->maximum_num_containers != maximum_num_containers) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Raghava Aditya Renukunta3ffd6c52017-02-02 15:53:22 -0800486 fsa_dev_ptr = dev->fsa_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Raghava Aditya Renukunta3ffd6c52017-02-02 15:53:22 -0800488 dev->fsa_dev = kcalloc(maximum_num_containers,
489 sizeof(*fsa_dev_ptr), GFP_KERNEL);
490
491 kfree(fsa_dev_ptr);
492 fsa_dev_ptr = NULL;
493
494
495 if (!dev->fsa_dev)
496 return -ENOMEM;
497
498 dev->maximum_num_containers = maximum_num_containers;
499 }
500 for (index = 0; index < dev->maximum_num_containers; index++) {
501 dev->fsa_dev[index].devname[0] = '\0';
502 dev->fsa_dev[index].valid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
Mark Haverkampfe76df42007-03-15 12:55:07 -0700504 status = aac_probe_container(dev, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
Mark Haverkampfe76df42007-03-15 12:55:07 -0700506 if (status < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n");
508 break;
509 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 return status;
512}
513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514static void get_container_name_callback(void *context, struct fib * fibptr)
515{
516 struct aac_get_name_resp * get_name_reply;
517 struct scsi_cmnd * scsicmd;
518
519 scsicmd = (struct scsi_cmnd *) context;
520
Mark Haverkamp03d44332007-03-15 10:27:45 -0700521 if (!aac_valid_context(scsicmd, fibptr))
522 return;
523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
Eric Sesterhenn125e1872006-06-23 02:06:06 -0700525 BUG_ON(fibptr == NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
527 get_name_reply = (struct aac_get_name_resp *) fib_data(fibptr);
528 /* Failure is irrelevant, using default value instead */
529 if ((le32_to_cpu(get_name_reply->status) == CT_OK)
530 && (get_name_reply->data[0] != '\0')) {
Mark Haverkamp3b2946c2005-08-15 10:50:24 -0700531 char *sp = get_name_reply->data;
Mahesh Rajashekharab8364392015-03-26 10:41:24 -0400532 sp[sizeof(((struct aac_get_name_resp *)NULL)->data)] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 while (*sp == ' ')
534 ++sp;
Mark Haverkamp3b2946c2005-08-15 10:50:24 -0700535 if (*sp) {
FUJITA Tomonorid4345022008-03-09 13:44:34 +0900536 struct inquiry_data inq;
Mark Haverkamp3b2946c2005-08-15 10:50:24 -0700537 char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
538 int count = sizeof(d);
539 char *dp = d;
540 do {
541 *dp++ = (*sp) ? *sp++ : ' ';
542 } while (--count > 0);
FUJITA Tomonorid4345022008-03-09 13:44:34 +0900543
544 scsi_sg_copy_to_buffer(scsicmd, &inq, sizeof(inq));
545 memcpy(inq.inqd_pid, d, sizeof(d));
546 scsi_sg_copy_from_buffer(scsicmd, &inq, sizeof(inq));
Mark Haverkamp3b2946c2005-08-15 10:50:24 -0700547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 }
Mark Haverkamp3b2946c2005-08-15 10:50:24 -0700549
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
551
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800552 aac_fib_complete(fibptr);
Mark Haverkamp8e0c5eb2005-10-24 10:52:22 -0700553 scsicmd->scsi_done(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554}
555
556/**
557 * aac_get_container_name - get container name, none blocking.
558 */
Mark Haverkamp9e7c3492007-03-15 10:26:55 -0700559static int aac_get_container_name(struct scsi_cmnd * scsicmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 int status;
562 struct aac_get_name *dinfo;
563 struct fib * cmd_fibcontext;
564 struct aac_dev * dev;
565
566 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
567
Raghava Aditya Renukunta6bf3b632016-02-03 15:05:59 -0800568 cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800570 aac_fib_init(cmd_fibcontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);
572
573 dinfo->command = cpu_to_le32(VM_ContainerConfig);
574 dinfo->type = cpu_to_le32(CT_READ_NAME);
Mark Haverkamp9e7c3492007-03-15 10:26:55 -0700575 dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
577
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800578 status = aac_fib_send(ContainerCommand,
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800579 cmd_fibcontext,
Mahesh Rajashekharafb5d40d2015-08-28 06:38:33 -0400580 sizeof(struct aac_get_name_resp),
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800581 FsaNormal,
582 0, 1,
583 (fib_callback)get_container_name_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 (void *) scsicmd);
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 /*
587 * Check that the command queued to the controller
588 */
Mark Haverkamp77d644d2006-03-27 09:43:40 -0800589 if (status == -EINPROGRESS) {
590 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 return 0;
Mark Haverkamp77d644d2006-03-27 09:43:40 -0800592 }
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800593
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800594 printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
595 aac_fib_complete(cmd_fibcontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return -1;
597}
598
Mark Haverkampfe76df42007-03-15 12:55:07 -0700599static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd)
600{
601 struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
602
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400603 if ((fsa_dev_ptr[scmd_id(scsicmd)].valid & 1))
Mark Haverkampfe76df42007-03-15 12:55:07 -0700604 return aac_scsi_cmd(scsicmd);
605
606 scsicmd->result = DID_NO_CONNECT << 16;
607 scsicmd->scsi_done(scsicmd);
608 return 0;
609}
610
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400611static void _aac_probe_container2(void * context, struct fib * fibptr)
Mark Haverkampfe76df42007-03-15 12:55:07 -0700612{
Mark Haverkamp03d44332007-03-15 10:27:45 -0700613 struct fsa_dev_info *fsa_dev_ptr;
Mark Haverkampfe76df42007-03-15 12:55:07 -0700614 int (*callback)(struct scsi_cmnd *);
Mark Haverkamp03d44332007-03-15 10:27:45 -0700615 struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
616
Mark Haverkamp03d44332007-03-15 10:27:45 -0700617
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400618 if (!aac_valid_context(scsicmd, fibptr))
619 return;
Mark Haverkampfe76df42007-03-15 12:55:07 -0700620
621 scsicmd->SCp.Status = 0;
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400622 fsa_dev_ptr = fibptr->dev->fsa_dev;
Mark Haverkampfe76df42007-03-15 12:55:07 -0700623 if (fsa_dev_ptr) {
624 struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
625 fsa_dev_ptr += scmd_id(scsicmd);
626
627 if ((le32_to_cpu(dresp->status) == ST_OK) &&
628 (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
629 (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
Mahesh Rajashekharab8364392015-03-26 10:41:24 -0400630 if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 &
631 AAC_OPTION_VARIABLE_BLOCK_SIZE)) {
632 dresp->mnt[0].fileinfo.bdevinfo.block_size = 0x200;
633 fsa_dev_ptr->block_size = 0x200;
634 } else {
635 fsa_dev_ptr->block_size =
636 le32_to_cpu(dresp->mnt[0].fileinfo.bdevinfo.block_size);
637 }
Mark Haverkampfe76df42007-03-15 12:55:07 -0700638 fsa_dev_ptr->valid = 1;
Mark Salyzyn655d7222008-04-30 16:03:42 -0400639 /* sense_key holds the current state of the spin-up */
640 if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY))
641 fsa_dev_ptr->sense_data.sense_key = NOT_READY;
642 else if (fsa_dev_ptr->sense_data.sense_key == NOT_READY)
643 fsa_dev_ptr->sense_data.sense_key = NO_SENSE;
Mark Haverkampfe76df42007-03-15 12:55:07 -0700644 fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol);
645 fsa_dev_ptr->size
646 = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
647 (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
648 fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0);
649 }
650 if ((fsa_dev_ptr->valid & 1) == 0)
651 fsa_dev_ptr->valid = 0;
652 scsicmd->SCp.Status = le32_to_cpu(dresp->count);
653 }
654 aac_fib_complete(fibptr);
655 aac_fib_free(fibptr);
656 callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
657 scsicmd->SCp.ptr = NULL;
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400658 (*callback)(scsicmd);
659 return;
Mark Haverkampfe76df42007-03-15 12:55:07 -0700660}
661
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400662static void _aac_probe_container1(void * context, struct fib * fibptr)
Mark Haverkampfe76df42007-03-15 12:55:07 -0700663{
664 struct scsi_cmnd * scsicmd;
665 struct aac_mount * dresp;
666 struct aac_query_mount *dinfo;
667 int status;
668
669 dresp = (struct aac_mount *) fib_data(fibptr);
Mahesh Rajashekharab8364392015-03-26 10:41:24 -0400670 if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 &
671 AAC_OPTION_VARIABLE_BLOCK_SIZE))
672 dresp->mnt[0].capacityhigh = 0;
Mark Haverkampfe76df42007-03-15 12:55:07 -0700673 if ((le32_to_cpu(dresp->status) != ST_OK) ||
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400674 (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
675 _aac_probe_container2(context, fibptr);
676 return;
677 }
Mark Haverkampfe76df42007-03-15 12:55:07 -0700678 scsicmd = (struct scsi_cmnd *) context;
Mark Haverkampfe76df42007-03-15 12:55:07 -0700679
Mark Haverkamp03d44332007-03-15 10:27:45 -0700680 if (!aac_valid_context(scsicmd, fibptr))
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400681 return;
Mark Haverkamp03d44332007-03-15 10:27:45 -0700682
Mark Haverkampfe76df42007-03-15 12:55:07 -0700683 aac_fib_init(fibptr);
684
685 dinfo = (struct aac_query_mount *)fib_data(fibptr);
686
Mahesh Rajashekharab8364392015-03-26 10:41:24 -0400687 if (fibptr->dev->supplement_adapter_info.SupportedOptions2 &
688 AAC_OPTION_VARIABLE_BLOCK_SIZE)
689 dinfo->command = cpu_to_le32(VM_NameServeAllBlk);
690 else
691 dinfo->command = cpu_to_le32(VM_NameServe64);
692
Mark Haverkampfe76df42007-03-15 12:55:07 -0700693 dinfo->count = cpu_to_le32(scmd_id(scsicmd));
694 dinfo->type = cpu_to_le32(FT_FILESYS);
695
696 status = aac_fib_send(ContainerCommand,
697 fibptr,
698 sizeof(struct aac_query_mount),
699 FsaNormal,
700 0, 1,
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400701 _aac_probe_container2,
Mark Haverkampfe76df42007-03-15 12:55:07 -0700702 (void *) scsicmd);
703 /*
704 * Check that the command queued to the controller
705 */
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400706 if (status == -EINPROGRESS)
Mark Haverkampfe76df42007-03-15 12:55:07 -0700707 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400708 else if (status < 0) {
Mark Haverkampfe76df42007-03-15 12:55:07 -0700709 /* Inherit results from VM_NameServe, if any */
710 dresp->status = cpu_to_le32(ST_OK);
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400711 _aac_probe_container2(context, fibptr);
Mark Haverkampfe76df42007-03-15 12:55:07 -0700712 }
Mark Haverkampfe76df42007-03-15 12:55:07 -0700713}
714
715static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
716{
717 struct fib * fibptr;
718 int status = -ENOMEM;
719
720 if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) {
721 struct aac_query_mount *dinfo;
722
723 aac_fib_init(fibptr);
724
725 dinfo = (struct aac_query_mount *)fib_data(fibptr);
726
Mahesh Rajashekharab8364392015-03-26 10:41:24 -0400727 if (fibptr->dev->supplement_adapter_info.SupportedOptions2 &
728 AAC_OPTION_VARIABLE_BLOCK_SIZE)
729 dinfo->command = cpu_to_le32(VM_NameServeAllBlk);
730 else
731 dinfo->command = cpu_to_le32(VM_NameServe);
732
Mark Haverkampfe76df42007-03-15 12:55:07 -0700733 dinfo->count = cpu_to_le32(scmd_id(scsicmd));
734 dinfo->type = cpu_to_le32(FT_FILESYS);
735 scsicmd->SCp.ptr = (char *)callback;
736
737 status = aac_fib_send(ContainerCommand,
738 fibptr,
739 sizeof(struct aac_query_mount),
740 FsaNormal,
741 0, 1,
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400742 _aac_probe_container1,
Mark Haverkampfe76df42007-03-15 12:55:07 -0700743 (void *) scsicmd);
744 /*
745 * Check that the command queued to the controller
746 */
747 if (status == -EINPROGRESS) {
748 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
749 return 0;
750 }
751 if (status < 0) {
752 scsicmd->SCp.ptr = NULL;
753 aac_fib_complete(fibptr);
754 aac_fib_free(fibptr);
755 }
756 }
757 if (status < 0) {
758 struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
759 if (fsa_dev_ptr) {
760 fsa_dev_ptr += scmd_id(scsicmd);
761 if ((fsa_dev_ptr->valid & 1) == 0) {
762 fsa_dev_ptr->valid = 0;
763 return (*callback)(scsicmd);
764 }
765 }
766 }
767 return status;
768}
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770/**
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800771 * aac_probe_container - query a logical volume
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 * @dev: device to query
773 * @cid: container identifier
774 *
775 * Queries the controller about the given volume. The volume information
776 * is updated in the struct fsa_dev_info structure rather than returned.
777 */
Mark Haverkampfe76df42007-03-15 12:55:07 -0700778static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
779{
780 scsicmd->device = NULL;
781 return 0;
782}
783
Mark Haverkampbfb35aa82006-02-01 09:30:55 -0800784int aac_probe_container(struct aac_dev *dev, int cid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Mark Haverkampfe76df42007-03-15 12:55:07 -0700786 struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
787 struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
Mark Haverkampfe76df42007-03-15 12:55:07 -0700790 if (!scsicmd || !scsidev) {
791 kfree(scsicmd);
792 kfree(scsidev);
Mark Haverkamp90ee3462006-08-03 08:03:07 -0700793 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 }
Mark Haverkampfe76df42007-03-15 12:55:07 -0700795 scsicmd->list.next = NULL;
Salyzyn, Mark1a655042007-06-11 16:17:55 -0400796 scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
Mark Haverkampfe76df42007-03-15 12:55:07 -0700798 scsicmd->device = scsidev;
799 scsidev->sdev_state = 0;
800 scsidev->id = cid;
801 scsidev->host = dev->scsi_host_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Mark Haverkampfe76df42007-03-15 12:55:07 -0700803 if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0)
804 while (scsicmd->device == scsidev)
805 schedule();
Salyzyn, Mark802ae2f2007-03-21 13:49:47 -0400806 kfree(scsidev);
Mark Haverkampfe76df42007-03-15 12:55:07 -0700807 status = scsicmd->SCp.Status;
808 kfree(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 return status;
810}
811
812/* Local Structure to set SCSI inquiry data strings */
813struct scsi_inq {
814 char vid[8]; /* Vendor ID */
815 char pid[16]; /* Product ID */
816 char prl[4]; /* Product Revision Level */
817};
818
819/**
820 * InqStrCopy - string merge
821 * @a: string to copy from
822 * @b: string to copy to
823 *
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800824 * Copy a String from one location to another
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 * without copying \0
826 */
827
828static void inqstrcpy(char *a, char *b)
829{
830
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800831 while (*a != (char)0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 *b++ = *a++;
833}
834
835static char *container_types[] = {
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800836 "None",
837 "Volume",
838 "Mirror",
839 "Stripe",
840 "RAID5",
841 "SSRW",
842 "SSRO",
843 "Morph",
844 "Legacy",
845 "RAID4",
846 "RAID10",
847 "RAID00",
848 "V-MIRRORS",
849 "PSEUDO R4",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 "RAID50",
Mark Haverkamp84971732005-06-20 11:55:24 -0700851 "RAID5D",
852 "RAID5D0",
853 "RAID1E",
854 "RAID6",
855 "RAID60",
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -0800856 "Unknown"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857};
858
Salyzyn, Mark17eaace2008-01-08 12:23:49 -0800859char * get_container_type(unsigned tindex)
860{
861 if (tindex >= ARRAY_SIZE(container_types))
862 tindex = ARRAY_SIZE(container_types) - 1;
863 return container_types[tindex];
864}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
866/* Function: setinqstr
867 *
868 * Arguments: [1] pointer to void [1] int
869 *
870 * Purpose: Sets SCSI inquiry data strings for vendor, product
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300871 * and revision level. Allows strings to be set in platform dependent
872 * files instead of in OS dependent driver source.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 */
874
Mark Haverkamp794d0602005-10-24 10:51:53 -0700875static void setinqstr(struct aac_dev *dev, void *data, int tindex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876{
877 struct scsi_inq *str;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 str = (struct scsi_inq *)(data); /* cast data to scsi inq block */
Mark Haverkamp794d0602005-10-24 10:51:53 -0700880 memset(str, ' ', sizeof(*str));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
Mark Haverkamp794d0602005-10-24 10:51:53 -0700882 if (dev->supplement_adapter_info.AdapterTypeText[0]) {
883 char * cp = dev->supplement_adapter_info.AdapterTypeText;
Salyzyn, Mark3bc80702008-01-11 13:46:24 -0800884 int c;
885 if ((cp[0] == 'A') && (cp[1] == 'O') && (cp[2] == 'C'))
886 inqstrcpy("SMC", str->vid);
887 else {
888 c = sizeof(str->vid);
889 while (*cp && *cp != ' ' && --c)
890 ++cp;
891 c = *cp;
892 *cp = '\0';
893 inqstrcpy (dev->supplement_adapter_info.AdapterTypeText,
894 str->vid);
895 *cp = c;
896 while (*cp && *cp != ' ')
897 ++cp;
898 }
Mark Haverkamp794d0602005-10-24 10:51:53 -0700899 while (*cp == ' ')
900 ++cp;
901 /* last six chars reserved for vol type */
902 c = 0;
903 if (strlen(cp) > sizeof(str->pid)) {
904 c = cp[sizeof(str->pid)];
905 cp[sizeof(str->pid)] = '\0';
906 }
907 inqstrcpy (cp, str->pid);
908 if (c)
909 cp[sizeof(str->pid)] = c;
910 } else {
911 struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype);
Tobias Klauser6391a112006-06-08 22:23:48 -0700912
913 inqstrcpy (mp->vname, str->vid);
Mark Haverkamp794d0602005-10-24 10:51:53 -0700914 /* last six chars reserved for vol type */
915 inqstrcpy (mp->model, str->pid);
916 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
Tobias Klauser6391a112006-06-08 22:23:48 -0700918 if (tindex < ARRAY_SIZE(container_types)){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 char *findit = str->pid;
920
921 for ( ; *findit != ' '; findit++); /* walk till we find a space */
922 /* RAID is superfluous in the context of a RAID device */
923 if (memcmp(findit-4, "RAID", 4) == 0)
924 *(findit -= 4) = ' ';
Mark Haverkamp794d0602005-10-24 10:51:53 -0700925 if (((findit - str->pid) + strlen(container_types[tindex]))
926 < (sizeof(str->pid) + sizeof(str->prl)))
927 inqstrcpy (container_types[tindex], findit + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 }
929 inqstrcpy ("V1.0", str->prl);
930}
931
Salyzyn, Mark88e2f982007-07-17 14:01:28 -0400932static void get_container_serial_callback(void *context, struct fib * fibptr)
933{
934 struct aac_get_serial_resp * get_serial_reply;
935 struct scsi_cmnd * scsicmd;
936
937 BUG_ON(fibptr == NULL);
938
939 scsicmd = (struct scsi_cmnd *) context;
940 if (!aac_valid_context(scsicmd, fibptr))
941 return;
942
943 get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr);
944 /* Failure is irrelevant, using default value instead */
945 if (le32_to_cpu(get_serial_reply->status) == CT_OK) {
Mahesh Rajashekhara5d910642015-03-26 10:41:26 -0400946 /*Check to see if it's for VPD 0x83 or 0x80 */
947 if (scsicmd->cmnd[2] == 0x83) {
948 /* vpd page 0x83 - Device Identification Page */
949 int i;
950 TVPD_Page83 VPDPage83Data;
951
952 memset(((u8 *)&VPDPage83Data), 0,
953 sizeof(VPDPage83Data));
954
955 /* DIRECT_ACCESS_DEVIC */
956 VPDPage83Data.DeviceType = 0;
957 /* DEVICE_CONNECTED */
958 VPDPage83Data.DeviceTypeQualifier = 0;
959 /* VPD_DEVICE_IDENTIFIERS */
960 VPDPage83Data.PageCode = 0x83;
961 VPDPage83Data.Reserved = 0;
962 VPDPage83Data.PageLength =
963 sizeof(VPDPage83Data.IdDescriptorType1) +
964 sizeof(VPDPage83Data.IdDescriptorType2);
965
966 /* T10 Vendor Identifier Field Format */
967 /* VpdCodeSetAscii */
968 VPDPage83Data.IdDescriptorType1.CodeSet = 2;
969 /* VpdIdentifierTypeVendorId */
970 VPDPage83Data.IdDescriptorType1.IdentifierType = 1;
971 VPDPage83Data.IdDescriptorType1.IdentifierLength =
972 sizeof(VPDPage83Data.IdDescriptorType1) - 4;
973
974 /* "ADAPTEC " for adaptec */
975 memcpy(VPDPage83Data.IdDescriptorType1.VendId,
976 "ADAPTEC ",
977 sizeof(VPDPage83Data.IdDescriptorType1.VendId));
978 memcpy(VPDPage83Data.IdDescriptorType1.ProductId,
979 "ARRAY ",
980 sizeof(
981 VPDPage83Data.IdDescriptorType1.ProductId));
982
983 /* Convert to ascii based serial number.
984 * The LSB is the the end.
985 */
986 for (i = 0; i < 8; i++) {
987 u8 temp =
988 (u8)((get_serial_reply->uid >> ((7 - i) * 4)) & 0xF);
989 if (temp > 0x9) {
990 VPDPage83Data.IdDescriptorType1.SerialNumber[i] =
991 'A' + (temp - 0xA);
992 } else {
993 VPDPage83Data.IdDescriptorType1.SerialNumber[i] =
994 '0' + temp;
995 }
996 }
997
998 /* VpdCodeSetBinary */
999 VPDPage83Data.IdDescriptorType2.CodeSet = 1;
1000 /* VpdIdentifierTypeEUI64 */
1001 VPDPage83Data.IdDescriptorType2.IdentifierType = 2;
1002 VPDPage83Data.IdDescriptorType2.IdentifierLength =
1003 sizeof(VPDPage83Data.IdDescriptorType2) - 4;
1004
1005 VPDPage83Data.IdDescriptorType2.EU64Id.VendId[0] = 0xD0;
1006 VPDPage83Data.IdDescriptorType2.EU64Id.VendId[1] = 0;
1007 VPDPage83Data.IdDescriptorType2.EU64Id.VendId[2] = 0;
1008
1009 VPDPage83Data.IdDescriptorType2.EU64Id.Serial =
1010 get_serial_reply->uid;
1011 VPDPage83Data.IdDescriptorType2.EU64Id.Reserved = 0;
1012
1013 /* Move the inquiry data to the response buffer. */
1014 scsi_sg_copy_from_buffer(scsicmd, &VPDPage83Data,
1015 sizeof(VPDPage83Data));
1016 } else {
1017 /* It must be for VPD 0x80 */
1018 char sp[13];
1019 /* EVPD bit set */
1020 sp[0] = INQD_PDT_DA;
1021 sp[1] = scsicmd->cmnd[2];
1022 sp[2] = 0;
1023 sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
1024 le32_to_cpu(get_serial_reply->uid));
1025 scsi_sg_copy_from_buffer(scsicmd, sp,
1026 sizeof(sp));
1027 }
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04001028 }
1029
1030 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
1031
1032 aac_fib_complete(fibptr);
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04001033 scsicmd->scsi_done(scsicmd);
1034}
1035
1036/**
1037 * aac_get_container_serial - get container serial, none blocking.
1038 */
1039static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
1040{
1041 int status;
1042 struct aac_get_serial *dinfo;
1043 struct fib * cmd_fibcontext;
1044 struct aac_dev * dev;
1045
1046 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
1047
Raghava Aditya Renukunta6bf3b632016-02-03 15:05:59 -08001048 cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04001049
1050 aac_fib_init(cmd_fibcontext);
1051 dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext);
1052
1053 dinfo->command = cpu_to_le32(VM_ContainerConfig);
1054 dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID);
1055 dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
1056
1057 status = aac_fib_send(ContainerCommand,
1058 cmd_fibcontext,
Mahesh Rajashekharafb5d40d2015-08-28 06:38:33 -04001059 sizeof(struct aac_get_serial_resp),
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04001060 FsaNormal,
1061 0, 1,
1062 (fib_callback) get_container_serial_callback,
1063 (void *) scsicmd);
1064
1065 /*
1066 * Check that the command queued to the controller
1067 */
1068 if (status == -EINPROGRESS) {
1069 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
1070 return 0;
1071 }
1072
1073 printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status);
1074 aac_fib_complete(cmd_fibcontext);
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04001075 return -1;
1076}
1077
1078/* Function: setinqserial
1079 *
1080 * Arguments: [1] pointer to void [1] int
1081 *
1082 * Purpose: Sets SCSI Unit Serial number.
1083 * This is a fake. We should read a proper
1084 * serial number from the container. <SuSE>But
1085 * without docs it's quite hard to do it :-)
1086 * So this will have to do in the meantime.</SuSE>
1087 */
1088
1089static int setinqserial(struct aac_dev *dev, void *data, int cid)
1090{
1091 /*
1092 * This breaks array migration.
1093 */
1094 return snprintf((char *)(data), sizeof(struct scsi_inq) - 4, "%08X%02X",
1095 le32_to_cpu(dev->adapter_info.serial[0]), cid);
1096}
1097
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001098static inline void set_sense(struct sense_data *sense_data, u8 sense_key,
1099 u8 sense_code, u8 a_sense_code, u8 bit_pointer, u16 field_pointer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100{
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001101 u8 *sense_buf = (u8 *)sense_data;
1102 /* Sense data valid, err code 70h */
1103 sense_buf[0] = 0x70; /* No info field */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 sense_buf[1] = 0; /* Segment number, always zero */
1105
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001106 sense_buf[2] = sense_key; /* Sense key */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108 sense_buf[12] = sense_code; /* Additional sense code */
1109 sense_buf[13] = a_sense_code; /* Additional sense code qualifier */
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 if (sense_key == ILLEGAL_REQUEST) {
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001112 sense_buf[7] = 10; /* Additional sense length */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001114 sense_buf[15] = bit_pointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 /* Illegal parameter is in the parameter block */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 if (sense_code == SENCODE_INVALID_CDB_FIELD)
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001117 sense_buf[15] |= 0xc0;/* Std sense key specific field */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 /* Illegal parameter is in the CDB block */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 sense_buf[16] = field_pointer >> 8; /* MSB */
1120 sense_buf[17] = field_pointer; /* LSB */
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001121 } else
1122 sense_buf[7] = 6; /* Additional sense length */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123}
1124
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001125static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
1126{
1127 if (lba & 0xffffffff00000000LL) {
1128 int cid = scmd_id(cmd);
1129 dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
1130 cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
1131 SAM_STAT_CHECK_CONDITION;
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08001132 set_sense(&dev->fsa_dev[cid].sense_data,
1133 HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
1134 ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001135 memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
Salyzyn, Mark3ace4262008-01-14 07:25:33 -08001136 min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
1137 SCSI_SENSE_BUFFERSIZE));
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001138 cmd->scsi_done(cmd);
1139 return 1;
1140 }
1141 return 0;
1142}
1143
1144static int aac_bounds_64(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
1145{
1146 return 0;
1147}
1148
1149static void io_callback(void *context, struct fib * fibptr);
1150
1151static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
1152{
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301153 struct aac_dev *dev = fib->dev;
1154 u16 fibsize, command;
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301155 long ret;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001156
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301157 aac_fib_init(fib);
Raghava Aditya Renukuntad1ef4da2017-02-02 15:53:17 -08001158 if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 ||
1159 dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) &&
1160 !dev->sync_mode) {
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301161 struct aac_raw_io2 *readcmd2;
1162 readcmd2 = (struct aac_raw_io2 *) fib_data(fib);
1163 memset(readcmd2, 0, sizeof(struct aac_raw_io2));
1164 readcmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff));
1165 readcmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04001166 readcmd2->byteCount = cpu_to_le32(count *
1167 dev->fsa_dev[scmd_id(cmd)].block_size);
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301168 readcmd2->cid = cpu_to_le16(scmd_id(cmd));
1169 readcmd2->flags = cpu_to_le16(RIO2_IO_TYPE_READ);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301170 ret = aac_build_sgraw2(cmd, readcmd2,
1171 dev->scsi_host_ptr->sg_tablesize);
1172 if (ret < 0)
1173 return ret;
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301174 command = ContainerRawIo2;
1175 fibsize = sizeof(struct aac_raw_io2) +
1176 ((le32_to_cpu(readcmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
1177 } else {
1178 struct aac_raw_io *readcmd;
1179 readcmd = (struct aac_raw_io *) fib_data(fib);
1180 readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
1181 readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04001182 readcmd->count = cpu_to_le32(count *
1183 dev->fsa_dev[scmd_id(cmd)].block_size);
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301184 readcmd->cid = cpu_to_le16(scmd_id(cmd));
1185 readcmd->flags = cpu_to_le16(RIO_TYPE_READ);
1186 readcmd->bpTotal = 0;
1187 readcmd->bpComplete = 0;
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301188 ret = aac_build_sgraw(cmd, &readcmd->sg);
1189 if (ret < 0)
1190 return ret;
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301191 command = ContainerRawIo;
1192 fibsize = sizeof(struct aac_raw_io) +
1193 ((le32_to_cpu(readcmd->sg.count)-1) * sizeof(struct sgentryraw));
1194 }
1195
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001196 BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
1197 /*
1198 * Now send the Fib to the adapter
1199 */
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301200 return aac_fib_send(command,
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001201 fib,
1202 fibsize,
1203 FsaNormal,
1204 0, 1,
1205 (fib_callback) io_callback,
1206 (void *) cmd);
1207}
1208
1209static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
1210{
1211 u16 fibsize;
1212 struct aac_read64 *readcmd;
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301213 long ret;
1214
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001215 aac_fib_init(fib);
1216 readcmd = (struct aac_read64 *) fib_data(fib);
1217 readcmd->command = cpu_to_le32(VM_CtHostRead64);
1218 readcmd->cid = cpu_to_le16(scmd_id(cmd));
1219 readcmd->sector_count = cpu_to_le16(count);
1220 readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
1221 readcmd->pad = 0;
1222 readcmd->flags = 0;
1223
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301224 ret = aac_build_sg64(cmd, &readcmd->sg);
1225 if (ret < 0)
1226 return ret;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001227 fibsize = sizeof(struct aac_read64) +
1228 ((le32_to_cpu(readcmd->sg.count) - 1) *
1229 sizeof (struct sgentry64));
1230 BUG_ON (fibsize > (fib->dev->max_fib_size -
1231 sizeof(struct aac_fibhdr)));
1232 /*
1233 * Now send the Fib to the adapter
1234 */
1235 return aac_fib_send(ContainerCommand64,
1236 fib,
1237 fibsize,
1238 FsaNormal,
1239 0, 1,
1240 (fib_callback) io_callback,
1241 (void *) cmd);
1242}
1243
1244static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
1245{
1246 u16 fibsize;
1247 struct aac_read *readcmd;
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04001248 struct aac_dev *dev = fib->dev;
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301249 long ret;
1250
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001251 aac_fib_init(fib);
1252 readcmd = (struct aac_read *) fib_data(fib);
1253 readcmd->command = cpu_to_le32(VM_CtBlockRead);
Christoph Hellwigf3307f72007-11-08 17:27:47 +00001254 readcmd->cid = cpu_to_le32(scmd_id(cmd));
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001255 readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04001256 readcmd->count = cpu_to_le32(count *
1257 dev->fsa_dev[scmd_id(cmd)].block_size);
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001258
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301259 ret = aac_build_sg(cmd, &readcmd->sg);
1260 if (ret < 0)
1261 return ret;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001262 fibsize = sizeof(struct aac_read) +
1263 ((le32_to_cpu(readcmd->sg.count) - 1) *
1264 sizeof (struct sgentry));
1265 BUG_ON (fibsize > (fib->dev->max_fib_size -
1266 sizeof(struct aac_fibhdr)));
1267 /*
1268 * Now send the Fib to the adapter
1269 */
1270 return aac_fib_send(ContainerCommand,
1271 fib,
1272 fibsize,
1273 FsaNormal,
1274 0, 1,
1275 (fib_callback) io_callback,
1276 (void *) cmd);
1277}
1278
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04001279static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001280{
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301281 struct aac_dev *dev = fib->dev;
1282 u16 fibsize, command;
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301283 long ret;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001284
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301285 aac_fib_init(fib);
Raghava Aditya Renukuntad1ef4da2017-02-02 15:53:17 -08001286 if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 ||
1287 dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) &&
1288 !dev->sync_mode) {
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301289 struct aac_raw_io2 *writecmd2;
1290 writecmd2 = (struct aac_raw_io2 *) fib_data(fib);
1291 memset(writecmd2, 0, sizeof(struct aac_raw_io2));
1292 writecmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff));
1293 writecmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04001294 writecmd2->byteCount = cpu_to_le32(count *
1295 dev->fsa_dev[scmd_id(cmd)].block_size);
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301296 writecmd2->cid = cpu_to_le16(scmd_id(cmd));
1297 writecmd2->flags = (fua && ((aac_cache & 5) != 1) &&
1298 (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
1299 cpu_to_le16(RIO2_IO_TYPE_WRITE|RIO2_IO_SUREWRITE) :
1300 cpu_to_le16(RIO2_IO_TYPE_WRITE);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301301 ret = aac_build_sgraw2(cmd, writecmd2,
1302 dev->scsi_host_ptr->sg_tablesize);
1303 if (ret < 0)
1304 return ret;
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301305 command = ContainerRawIo2;
1306 fibsize = sizeof(struct aac_raw_io2) +
1307 ((le32_to_cpu(writecmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
1308 } else {
1309 struct aac_raw_io *writecmd;
1310 writecmd = (struct aac_raw_io *) fib_data(fib);
1311 writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
1312 writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04001313 writecmd->count = cpu_to_le32(count *
1314 dev->fsa_dev[scmd_id(cmd)].block_size);
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301315 writecmd->cid = cpu_to_le16(scmd_id(cmd));
1316 writecmd->flags = (fua && ((aac_cache & 5) != 1) &&
1317 (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
1318 cpu_to_le16(RIO_TYPE_WRITE|RIO_SUREWRITE) :
1319 cpu_to_le16(RIO_TYPE_WRITE);
1320 writecmd->bpTotal = 0;
1321 writecmd->bpComplete = 0;
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301322 ret = aac_build_sgraw(cmd, &writecmd->sg);
1323 if (ret < 0)
1324 return ret;
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301325 command = ContainerRawIo;
1326 fibsize = sizeof(struct aac_raw_io) +
1327 ((le32_to_cpu(writecmd->sg.count)-1) * sizeof (struct sgentryraw));
1328 }
1329
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001330 BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
1331 /*
1332 * Now send the Fib to the adapter
1333 */
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05301334 return aac_fib_send(command,
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001335 fib,
1336 fibsize,
1337 FsaNormal,
1338 0, 1,
1339 (fib_callback) io_callback,
1340 (void *) cmd);
1341}
1342
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04001343static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001344{
1345 u16 fibsize;
1346 struct aac_write64 *writecmd;
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301347 long ret;
1348
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001349 aac_fib_init(fib);
1350 writecmd = (struct aac_write64 *) fib_data(fib);
1351 writecmd->command = cpu_to_le32(VM_CtHostWrite64);
1352 writecmd->cid = cpu_to_le16(scmd_id(cmd));
1353 writecmd->sector_count = cpu_to_le16(count);
1354 writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
1355 writecmd->pad = 0;
1356 writecmd->flags = 0;
1357
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301358 ret = aac_build_sg64(cmd, &writecmd->sg);
1359 if (ret < 0)
1360 return ret;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001361 fibsize = sizeof(struct aac_write64) +
1362 ((le32_to_cpu(writecmd->sg.count) - 1) *
1363 sizeof (struct sgentry64));
1364 BUG_ON (fibsize > (fib->dev->max_fib_size -
1365 sizeof(struct aac_fibhdr)));
1366 /*
1367 * Now send the Fib to the adapter
1368 */
1369 return aac_fib_send(ContainerCommand64,
1370 fib,
1371 fibsize,
1372 FsaNormal,
1373 0, 1,
1374 (fib_callback) io_callback,
1375 (void *) cmd);
1376}
1377
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04001378static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001379{
1380 u16 fibsize;
1381 struct aac_write *writecmd;
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04001382 struct aac_dev *dev = fib->dev;
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301383 long ret;
1384
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001385 aac_fib_init(fib);
1386 writecmd = (struct aac_write *) fib_data(fib);
1387 writecmd->command = cpu_to_le32(VM_CtBlockWrite);
Christoph Hellwigf3307f72007-11-08 17:27:47 +00001388 writecmd->cid = cpu_to_le32(scmd_id(cmd));
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001389 writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04001390 writecmd->count = cpu_to_le32(count *
1391 dev->fsa_dev[scmd_id(cmd)].block_size);
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001392 writecmd->sg.count = cpu_to_le32(1);
1393 /* ->stable is not used - it did mean which type of write */
1394
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301395 ret = aac_build_sg(cmd, &writecmd->sg);
1396 if (ret < 0)
1397 return ret;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001398 fibsize = sizeof(struct aac_write) +
1399 ((le32_to_cpu(writecmd->sg.count) - 1) *
1400 sizeof (struct sgentry));
1401 BUG_ON (fibsize > (fib->dev->max_fib_size -
1402 sizeof(struct aac_fibhdr)));
1403 /*
1404 * Now send the Fib to the adapter
1405 */
1406 return aac_fib_send(ContainerCommand,
1407 fib,
1408 fibsize,
1409 FsaNormal,
1410 0, 1,
1411 (fib_callback) io_callback,
1412 (void *) cmd);
1413}
1414
1415static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd)
1416{
1417 struct aac_srb * srbcmd;
1418 u32 flag;
1419 u32 timeout;
1420
1421 aac_fib_init(fib);
1422 switch(cmd->sc_data_direction){
1423 case DMA_TO_DEVICE:
1424 flag = SRB_DataOut;
1425 break;
1426 case DMA_BIDIRECTIONAL:
1427 flag = SRB_DataIn | SRB_DataOut;
1428 break;
1429 case DMA_FROM_DEVICE:
1430 flag = SRB_DataIn;
1431 break;
1432 case DMA_NONE:
1433 default: /* shuts up some versions of gcc */
1434 flag = SRB_NoDataXfer;
1435 break;
1436 }
1437
1438 srbcmd = (struct aac_srb*) fib_data(fib);
1439 srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
1440 srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scmd_channel(cmd)));
1441 srbcmd->id = cpu_to_le32(scmd_id(cmd));
1442 srbcmd->lun = cpu_to_le32(cmd->device->lun);
1443 srbcmd->flags = cpu_to_le32(flag);
Jens Axboe242f9dc2008-09-14 05:55:09 -07001444 timeout = cmd->request->timeout/HZ;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001445 if (timeout == 0)
1446 timeout = 1;
1447 srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds
1448 srbcmd->retry_limit = 0; /* Obsolete parameter */
1449 srbcmd->cdb_size = cpu_to_le32(cmd->cmd_len);
1450 return srbcmd;
1451}
1452
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08001453static struct aac_hba_cmd_req *aac_construct_hbacmd(struct fib *fib,
1454 struct scsi_cmnd *cmd)
1455{
1456 struct aac_hba_cmd_req *hbacmd;
1457 struct aac_dev *dev;
1458 int bus, target;
1459 u64 address;
1460
1461 dev = (struct aac_dev *)cmd->device->host->hostdata;
1462
1463 hbacmd = (struct aac_hba_cmd_req *)fib->hw_fib_va;
1464 memset(hbacmd, 0, 96); /* sizeof(*hbacmd) is not necessary */
1465 /* iu_type is a parameter of aac_hba_send */
1466 switch (cmd->sc_data_direction) {
1467 case DMA_TO_DEVICE:
1468 hbacmd->byte1 = 2;
1469 break;
1470 case DMA_FROM_DEVICE:
1471 case DMA_BIDIRECTIONAL:
1472 hbacmd->byte1 = 1;
1473 break;
1474 case DMA_NONE:
1475 default:
1476 break;
1477 }
1478 hbacmd->lun[1] = cpu_to_le32(cmd->device->lun);
1479
1480 bus = aac_logical_to_phys(scmd_channel(cmd));
1481 target = scmd_id(cmd);
1482 hbacmd->it_nexus = dev->hba_map[bus][target].rmw_nexus;
1483
1484 /* we fill in reply_qid later in aac_src_deliver_message */
1485 /* we fill in iu_type, request_id later in aac_hba_send */
1486 /* we fill in emb_data_desc_count later in aac_build_sghba */
1487
1488 memcpy(hbacmd->cdb, cmd->cmnd, cmd->cmd_len);
1489 hbacmd->data_length = cpu_to_le32(scsi_bufflen(cmd));
1490
1491 address = (u64)fib->hw_error_pa;
1492 hbacmd->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
1493 hbacmd->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff));
1494 hbacmd->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
1495
1496 return hbacmd;
1497}
1498
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001499static void aac_srb_callback(void *context, struct fib * fibptr);
1500
1501static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd)
1502{
1503 u16 fibsize;
1504 struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301505 long ret;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001506
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301507 ret = aac_build_sg64(cmd, (struct sgmap64 *) &srbcmd->sg);
1508 if (ret < 0)
1509 return ret;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09001510 srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001511
1512 memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
1513 memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
1514 /*
1515 * Build Scatter/Gather list
1516 */
1517 fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
1518 ((le32_to_cpu(srbcmd->sg.count) & 0xff) *
1519 sizeof (struct sgentry64));
1520 BUG_ON (fibsize > (fib->dev->max_fib_size -
1521 sizeof(struct aac_fibhdr)));
1522
1523 /*
1524 * Now send the Fib to the adapter
1525 */
1526 return aac_fib_send(ScsiPortCommand64, fib,
1527 fibsize, FsaNormal, 0, 1,
1528 (fib_callback) aac_srb_callback,
1529 (void *) cmd);
1530}
1531
1532static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
1533{
1534 u16 fibsize;
1535 struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301536 long ret;
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001537
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05301538 ret = aac_build_sg(cmd, (struct sgmap *)&srbcmd->sg);
1539 if (ret < 0)
1540 return ret;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09001541 srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
Mark Haverkampe8f32de2007-01-23 15:00:30 -08001542
1543 memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
1544 memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
1545 /*
1546 * Build Scatter/Gather list
1547 */
1548 fibsize = sizeof (struct aac_srb) +
1549 (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
1550 sizeof (struct sgentry));
1551 BUG_ON (fibsize > (fib->dev->max_fib_size -
1552 sizeof(struct aac_fibhdr)));
1553
1554 /*
1555 * Now send the Fib to the adapter
1556 */
1557 return aac_fib_send(ScsiPortCommand, fib, fibsize, FsaNormal, 0, 1,
1558 (fib_callback) aac_srb_callback, (void *) cmd);
1559}
1560
Salyzyn, Mark94cf6ba2007-12-13 16:14:18 -08001561static int aac_scsi_32_64(struct fib * fib, struct scsi_cmnd * cmd)
1562{
Leubner, Achimd8e965072009-04-01 07:16:08 -07001563 if ((sizeof(dma_addr_t) > 4) && fib->dev->needs_dac &&
1564 (fib->dev->adapter_info.options & AAC_OPT_SGMAP_HOST64))
Salyzyn, Mark94cf6ba2007-12-13 16:14:18 -08001565 return FAILED;
1566 return aac_scsi_32(fib, cmd);
1567}
1568
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08001569static int aac_adapter_hba(struct fib *fib, struct scsi_cmnd *cmd)
1570{
1571 struct aac_hba_cmd_req *hbacmd = aac_construct_hbacmd(fib, cmd);
1572 struct aac_dev *dev;
1573 long ret;
1574
1575 dev = (struct aac_dev *)cmd->device->host->hostdata;
1576
1577 ret = aac_build_sghba(cmd, hbacmd,
1578 dev->scsi_host_ptr->sg_tablesize, (u64)fib->hw_sgl_pa);
1579 if (ret < 0)
1580 return ret;
1581
1582 /*
1583 * Now send the HBA command to the adapter
1584 */
1585 fib->hbacmd_size = 64 + le32_to_cpu(hbacmd->emb_data_desc_count) *
1586 sizeof(struct aac_hba_sgl);
1587
1588 return aac_hba_send(HBA_IU_TYPE_SCSI_CMD_REQ, fib,
1589 (fib_callback) aac_hba_callback,
1590 (void *) cmd);
1591}
1592
Raghava Aditya Renukunta71a91ca2017-02-02 15:53:26 -08001593int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target)
1594{
1595 struct fib *fibptr;
1596 struct aac_srb *srbcmd;
1597 struct sgmap64 *sg64;
1598 struct aac_ciss_identify_pd *identify_resp;
1599 dma_addr_t addr;
1600 u32 vbus, vid;
1601 u16 fibsize, datasize;
1602 int rcode = -ENOMEM;
1603
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08001604
Raghava Aditya Renukunta71a91ca2017-02-02 15:53:26 -08001605 fibptr = aac_fib_alloc(dev);
1606 if (!fibptr)
1607 goto out;
1608
1609 fibsize = sizeof(struct aac_srb) -
1610 sizeof(struct sgentry) + sizeof(struct sgentry64);
1611 datasize = sizeof(struct aac_ciss_identify_pd);
1612
1613 identify_resp = pci_alloc_consistent(dev->pdev, datasize, &addr);
1614
1615 if (!identify_resp)
1616 goto fib_free_ptr;
1617
1618 vbus = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceBus);
1619 vid = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceTarget);
1620
1621 aac_fib_init(fibptr);
1622
1623 srbcmd = (struct aac_srb *) fib_data(fibptr);
1624 srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
1625 srbcmd->channel = cpu_to_le32(vbus);
1626 srbcmd->id = cpu_to_le32(vid);
1627 srbcmd->lun = 0;
1628 srbcmd->flags = cpu_to_le32(SRB_DataIn);
1629 srbcmd->timeout = cpu_to_le32(10);
1630 srbcmd->retry_limit = 0;
1631 srbcmd->cdb_size = cpu_to_le32(12);
1632 srbcmd->count = cpu_to_le32(datasize);
1633
1634 memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
1635 srbcmd->cdb[0] = 0x26;
1636 srbcmd->cdb[2] = (u8)((AAC_MAX_LUN + target) & 0x00FF);
1637 srbcmd->cdb[6] = CISS_IDENTIFY_PHYSICAL_DEVICE;
1638
1639 sg64 = (struct sgmap64 *)&srbcmd->sg;
1640 sg64->count = cpu_to_le32(1);
1641 sg64->sg[0].addr[1] = cpu_to_le32((u32)(((addr) >> 16) >> 16));
1642 sg64->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
1643 sg64->sg[0].count = cpu_to_le32(datasize);
1644
1645 rcode = aac_fib_send(ScsiPortCommand64,
1646 fibptr, fibsize, FsaNormal, 1, 1, NULL, NULL);
1647
1648 if (identify_resp->current_queue_depth_limit <= 0 ||
1649 identify_resp->current_queue_depth_limit > 32)
1650 dev->hba_map[bus][target].qd_limit = 32;
1651 else
1652 dev->hba_map[bus][target].qd_limit =
1653 identify_resp->current_queue_depth_limit;
1654
1655 pci_free_consistent(dev->pdev, datasize, (void *)identify_resp, addr);
1656
1657 aac_fib_complete(fibptr);
1658
1659fib_free_ptr:
1660 aac_fib_free(fibptr);
1661out:
1662 return rcode;
1663}
1664
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001665/**
1666 * aac_update hba_map()- update current hba map with data from FW
1667 * @dev: aac_dev structure
1668 * @phys_luns: FW information from report phys luns
1669 *
1670 * Update our hba map with the information gathered from the FW
1671 */
1672void aac_update_hba_map(struct aac_dev *dev,
Raghava Aditya Renukunta6223a392017-02-02 15:53:28 -08001673 struct aac_ciss_phys_luns_resp *phys_luns, int rescan)
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001674{
1675 /* ok and extended reporting */
1676 u32 lun_count, nexus;
1677 u32 i, bus, target;
1678 u8 expose_flag, attribs;
1679 u8 devtype;
1680
1681 lun_count = ((phys_luns->list_length[0] << 24)
1682 + (phys_luns->list_length[1] << 16)
1683 + (phys_luns->list_length[2] << 8)
1684 + (phys_luns->list_length[3])) / 24;
1685
1686 for (i = 0; i < lun_count; ++i) {
1687
1688 bus = phys_luns->lun[i].level2[1] & 0x3f;
1689 target = phys_luns->lun[i].level2[0];
1690 expose_flag = phys_luns->lun[i].bus >> 6;
1691 attribs = phys_luns->lun[i].node_ident[9];
1692 nexus = *((u32 *) &phys_luns->lun[i].node_ident[12]);
1693
1694 if (bus >= AAC_MAX_BUSES || target >= AAC_MAX_TARGETS)
1695 continue;
1696
1697 dev->hba_map[bus][target].expose = expose_flag;
1698
1699 if (expose_flag != 0) {
1700 devtype = AAC_DEVTYPE_RAID_MEMBER;
1701 goto update_devtype;
1702 }
1703
1704 if (nexus != 0 && (attribs & 8)) {
1705 devtype = AAC_DEVTYPE_NATIVE_RAW;
1706 dev->hba_map[bus][target].rmw_nexus =
1707 nexus;
1708 } else
1709 devtype = AAC_DEVTYPE_ARC_RAW;
1710
1711 if (devtype != AAC_DEVTYPE_NATIVE_RAW)
1712 goto update_devtype;
1713
Raghava Aditya Renukunta71a91ca2017-02-02 15:53:26 -08001714 if (aac_issue_bmic_identify(dev, bus, target) < 0)
1715 dev->hba_map[bus][target].qd_limit = 32;
1716
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001717update_devtype:
Raghava Aditya Renukunta6223a392017-02-02 15:53:28 -08001718 if (rescan == AAC_INIT)
1719 dev->hba_map[bus][target].devtype = devtype;
1720 else
1721 dev->hba_map[bus][target].new_devtype = devtype;
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001722 }
1723}
1724
1725/**
1726 * aac_report_phys_luns() Process topology change
1727 * @dev: aac_dev structure
1728 * @fibptr: fib pointer
1729 *
1730 * Execute a CISS REPORT PHYS LUNS and process the results into
1731 * the current hba_map.
1732 */
Raghava Aditya Renukunta6223a392017-02-02 15:53:28 -08001733int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan)
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001734{
1735 int fibsize, datasize;
1736 struct aac_ciss_phys_luns_resp *phys_luns;
1737 struct aac_srb *srbcmd;
1738 struct sgmap64 *sg64;
1739 dma_addr_t addr;
1740 u32 vbus, vid;
1741 u32 rcode = 0;
1742
1743 /* Thor SA Firmware -> CISS_REPORT_PHYSICAL_LUNS */
1744 fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry)
1745 + sizeof(struct sgentry64);
1746 datasize = sizeof(struct aac_ciss_phys_luns_resp)
1747 + (AAC_MAX_TARGETS - 1) * sizeof(struct _ciss_lun);
1748
1749 phys_luns = (struct aac_ciss_phys_luns_resp *) pci_alloc_consistent(
1750 dev->pdev, datasize, &addr);
1751
1752 if (phys_luns == NULL) {
1753 rcode = -ENOMEM;
1754 goto err_out;
1755 }
1756
1757 vbus = (u32) le16_to_cpu(
1758 dev->supplement_adapter_info.VirtDeviceBus);
1759 vid = (u32) le16_to_cpu(
1760 dev->supplement_adapter_info.VirtDeviceTarget);
1761
1762 aac_fib_init(fibptr);
1763
1764 srbcmd = (struct aac_srb *) fib_data(fibptr);
1765 srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
1766 srbcmd->channel = cpu_to_le32(vbus);
1767 srbcmd->id = cpu_to_le32(vid);
1768 srbcmd->lun = 0;
1769 srbcmd->flags = cpu_to_le32(SRB_DataIn);
1770 srbcmd->timeout = cpu_to_le32(10);
1771 srbcmd->retry_limit = 0;
1772 srbcmd->cdb_size = cpu_to_le32(12);
1773 srbcmd->count = cpu_to_le32(datasize);
1774
1775 memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
1776 srbcmd->cdb[0] = CISS_REPORT_PHYSICAL_LUNS;
1777 srbcmd->cdb[1] = 2; /* extended reporting */
1778 srbcmd->cdb[8] = (u8)(datasize >> 8);
1779 srbcmd->cdb[9] = (u8)(datasize);
1780
1781 sg64 = (struct sgmap64 *) &srbcmd->sg;
1782 sg64->count = cpu_to_le32(1);
1783 sg64->sg[0].addr[1] = cpu_to_le32(upper_32_bits(addr));
1784 sg64->sg[0].addr[0] = cpu_to_le32(lower_32_bits(addr));
1785 sg64->sg[0].count = cpu_to_le32(datasize);
1786
1787 rcode = aac_fib_send(ScsiPortCommand64, fibptr, fibsize,
1788 FsaNormal, 1, 1, NULL, NULL);
1789
1790 /* analyse data */
1791 if (rcode >= 0 && phys_luns->resp_flag == 2) {
1792 /* ok and extended reporting */
Raghava Aditya Renukunta6223a392017-02-02 15:53:28 -08001793 aac_update_hba_map(dev, phys_luns, rescan);
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001794 }
1795
1796 pci_free_consistent(dev->pdev, datasize, (void *) phys_luns, addr);
1797err_out:
1798 return rcode;
1799}
1800
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801int aac_get_adapter_info(struct aac_dev* dev)
1802{
1803 struct fib* fibptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 int rcode;
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001805 u32 tmp, bus, target;
Mark Haverkamp84971732005-06-20 11:55:24 -07001806 struct aac_adapter_info *info;
1807 struct aac_bus_info *command;
1808 struct aac_bus_info_response *bus_info;
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001809
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08001810 if (!(fibptr = aac_fib_alloc(dev)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 return -ENOMEM;
1812
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08001813 aac_fib_init(fibptr);
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001814 info = (struct aac_adapter_info *) fib_data(fibptr);
1815 memset(info,0,sizeof(*info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08001817 rcode = aac_fib_send(RequestAdapterInfo,
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08001818 fibptr,
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001819 sizeof(*info),
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08001820 FsaNormal,
Mark Haverkamp92033442005-09-20 12:56:50 -07001821 -1, 1, /* First `interrupt' command uses special wait */
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08001822 NULL,
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001823 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001825 if (rcode < 0) {
Penchala Narasimha Reddy Chilakala, ERS-HCLTechcacb6dc2009-12-21 18:39:27 +05301826 /* FIB should be freed only after
1827 * getting the response from the F/W */
1828 if (rcode != -ERESTARTSYS) {
1829 aac_fib_complete(fibptr);
1830 aac_fib_free(fibptr);
1831 }
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001832 return rcode;
1833 }
1834 memcpy(&dev->adapter_info, info, sizeof(*info));
1835
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001836 dev->supplement_adapter_info.VirtDeviceBus = 0xffff;
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001837 if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
Salyzyn, Mark06a43d12008-01-08 12:32:00 -08001838 struct aac_supplement_adapter_info * sinfo;
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001839
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08001840 aac_fib_init(fibptr);
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001841
Salyzyn, Mark06a43d12008-01-08 12:32:00 -08001842 sinfo = (struct aac_supplement_adapter_info *) fib_data(fibptr);
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001843
Salyzyn, Mark06a43d12008-01-08 12:32:00 -08001844 memset(sinfo,0,sizeof(*sinfo));
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001845
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08001846 rcode = aac_fib_send(RequestSupplementAdapterInfo,
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001847 fibptr,
Salyzyn, Mark06a43d12008-01-08 12:32:00 -08001848 sizeof(*sinfo),
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001849 FsaNormal,
1850 1, 1,
1851 NULL,
1852 NULL);
1853
1854 if (rcode >= 0)
Salyzyn, Mark06a43d12008-01-08 12:32:00 -08001855 memcpy(&dev->supplement_adapter_info, sinfo, sizeof(*sinfo));
Penchala Narasimha Reddy Chilakala, ERS-HCLTechcacb6dc2009-12-21 18:39:27 +05301856 if (rcode == -ERESTARTSYS) {
1857 fibptr = aac_fib_alloc(dev);
1858 if (!fibptr)
1859 return -ENOMEM;
1860 }
1861
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001862 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001864 /* reset all previous mapped devices (i.e. for init. after IOP_RESET) */
1865 for (bus = 0; bus < AAC_MAX_BUSES; bus++) {
Raghava Aditya Renukunta71a91ca2017-02-02 15:53:26 -08001866 for (target = 0; target < AAC_MAX_TARGETS; target++) {
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001867 dev->hba_map[bus][target].devtype = 0;
Raghava Aditya Renukunta71a91ca2017-02-02 15:53:26 -08001868 dev->hba_map[bus][target].qd_limit = 0;
1869 }
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001870 }
Mark Haverkamp84971732005-06-20 11:55:24 -07001871
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08001872 /*
1873 * GetBusInfo
Mark Haverkamp84971732005-06-20 11:55:24 -07001874 */
1875
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08001876 aac_fib_init(fibptr);
Mark Haverkamp84971732005-06-20 11:55:24 -07001877
1878 bus_info = (struct aac_bus_info_response *) fib_data(fibptr);
1879
1880 memset(bus_info, 0, sizeof(*bus_info));
1881
1882 command = (struct aac_bus_info *)bus_info;
1883
1884 command->Command = cpu_to_le32(VM_Ioctl);
1885 command->ObjType = cpu_to_le32(FT_DRIVE);
1886 command->MethodId = cpu_to_le32(1);
1887 command->CtlCmd = cpu_to_le32(GetBusInfo);
1888
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08001889 rcode = aac_fib_send(ContainerCommand,
Mark Haverkamp84971732005-06-20 11:55:24 -07001890 fibptr,
1891 sizeof (*bus_info),
1892 FsaNormal,
1893 1, 1,
1894 NULL, NULL);
1895
Salyzyn, Mark94cf6ba2007-12-13 16:14:18 -08001896 /* reasoned default */
1897 dev->maximum_num_physicals = 16;
Mark Haverkamp84971732005-06-20 11:55:24 -07001898 if (rcode >= 0 && le32_to_cpu(bus_info->Status) == ST_OK) {
1899 dev->maximum_num_physicals = le32_to_cpu(bus_info->TargetsPerBus);
1900 dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount);
1901 }
1902
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001903 if (!dev->sync_mode && dev->sa_firmware &&
1904 dev->supplement_adapter_info.VirtDeviceBus != 0xffff) {
1905 /* Thor SA Firmware -> CISS_REPORT_PHYSICAL_LUNS */
Raghava Aditya Renukunta6223a392017-02-02 15:53:28 -08001906 rcode = aac_report_phys_luns(dev, fibptr, AAC_INIT);
Raghava Aditya Renukuntac83b11e2017-02-02 15:53:19 -08001907 }
1908
Mark Haverkamp8c867b22006-08-03 08:03:30 -07001909 if (!dev->in_reset) {
Salyzyn, Mark24f02e12007-06-19 16:29:24 -04001910 char buffer[16];
Mark Haverkamp8c867b22006-08-03 08:03:30 -07001911 tmp = le32_to_cpu(dev->adapter_info.kernelrev);
1912 printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08001913 dev->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 dev->id,
1915 tmp>>24,
1916 (tmp>>16)&0xff,
1917 tmp&0xff,
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07001918 le32_to_cpu(dev->adapter_info.kernelbuild),
1919 (int)sizeof(dev->supplement_adapter_info.BuildDate),
1920 dev->supplement_adapter_info.BuildDate);
Mark Haverkamp8c867b22006-08-03 08:03:30 -07001921 tmp = le32_to_cpu(dev->adapter_info.monitorrev);
1922 printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 dev->name, dev->id,
1924 tmp>>24,(tmp>>16)&0xff,tmp&0xff,
1925 le32_to_cpu(dev->adapter_info.monitorbuild));
Mark Haverkamp8c867b22006-08-03 08:03:30 -07001926 tmp = le32_to_cpu(dev->adapter_info.biosrev);
1927 printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 dev->name, dev->id,
1929 tmp>>24,(tmp>>16)&0xff,tmp&0xff,
1930 le32_to_cpu(dev->adapter_info.biosbuild));
Salyzyn, Mark24f02e12007-06-19 16:29:24 -04001931 buffer[0] = '\0';
Tony Jonesee959b02008-02-22 00:13:36 +01001932 if (aac_get_serial_number(
Salyzyn, Mark24f02e12007-06-19 16:29:24 -04001933 shost_to_class(dev->scsi_host_ptr), buffer))
1934 printk(KERN_INFO "%s%d: serial %s",
1935 dev->name, dev->id, buffer);
Salyzyn, Marka45c8632007-03-28 13:44:54 -04001936 if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) {
1937 printk(KERN_INFO "%s%d: TSID %.*s\n",
1938 dev->name, dev->id,
1939 (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
1940 dev->supplement_adapter_info.VpdInfo.Tsid);
1941 }
Salyzyn, Mark2f7ecc52008-02-08 08:36:23 -08001942 if (!aac_check_reset || ((aac_check_reset == 1) &&
Salyzyn, Marka3940da2008-01-08 12:48:25 -08001943 (dev->supplement_adapter_info.SupportedOptions2 &
1944 AAC_OPTION_IGNORE_RESET))) {
Salyzyn, Mark29c97682007-06-12 09:33:54 -04001945 printk(KERN_INFO "%s%d: Reset Adapter Ignored\n",
1946 dev->name, dev->id);
1947 }
Mark Haverkamp8c867b22006-08-03 08:03:30 -07001948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
Salyzyn, Mark95e852e2008-01-08 12:01:07 -08001950 dev->cache_protected = 0;
Salyzyn, Markcb1042f2008-01-17 09:25:07 -08001951 dev->jbod = ((dev->supplement_adapter_info.FeatureBits &
1952 AAC_FEATURE_JBOD) != 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 dev->nondasd_support = 0;
1954 dev->raid_scsi_mode = 0;
Salyzyn, Mark95e852e2008-01-08 12:01:07 -08001955 if(dev->adapter_info.options & AAC_OPT_NONDASD)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 dev->nondasd_support = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957
1958 /*
1959 * If the firmware supports ROMB RAID/SCSI mode and we are currently
1960 * in RAID/SCSI mode, set the flag. For now if in this mode we will
1961 * force nondasd support on. If we decide to allow the non-dasd flag
1962 * additional changes changes will have to be made to support
1963 * RAID/SCSI. the function aac_scsi_cmd in this module will have to be
1964 * changed to support the new dev->raid_scsi_mode flag instead of
1965 * leaching off of the dev->nondasd_support flag. Also in linit.c the
1966 * function aac_detect will have to be modified where it sets up the
1967 * max number of channels based on the aac->nondasd_support flag only.
1968 */
1969 if ((dev->adapter_info.options & AAC_OPT_SCSI_MANAGED) &&
1970 (dev->adapter_info.options & AAC_OPT_RAID_SCSI_MODE)) {
1971 dev->nondasd_support = 1;
1972 dev->raid_scsi_mode = 1;
1973 }
1974 if (dev->raid_scsi_mode != 0)
1975 printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled\n",
1976 dev->name, dev->id);
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08001977
Salyzyn, Mark95e852e2008-01-08 12:01:07 -08001978 if (nondasd != -1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 dev->nondasd_support = (nondasd!=0);
Salyzyn, Mark2f7ecc52008-02-08 08:36:23 -08001980 if (dev->nondasd_support && !dev->in_reset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
Yang Hongyange9304382009-04-13 14:40:14 -07001983 if (dma_get_required_mask(&dev->pdev->dev) > DMA_BIT_MASK(32))
Leubner, Achimd8e965072009-04-01 07:16:08 -07001984 dev->needs_dac = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 dev->dac_support = 0;
Leubner, Achimd8e965072009-04-01 07:16:08 -07001986 if ((sizeof(dma_addr_t) > 4) && dev->needs_dac &&
1987 (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)) {
Salyzyn, Mark2f7ecc52008-02-08 08:36:23 -08001988 if (!dev->in_reset)
1989 printk(KERN_INFO "%s%d: 64bit support enabled.\n",
1990 dev->name, dev->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 dev->dac_support = 1;
1992 }
1993
1994 if(dacmode != -1) {
1995 dev->dac_support = (dacmode!=0);
1996 }
Leubner, Achimd8e965072009-04-01 07:16:08 -07001997
1998 /* avoid problems with AAC_QUIRK_SCSI_32 controllers */
1999 if (dev->dac_support && (aac_get_driver_ident(dev->cardtype)->quirks
2000 & AAC_QUIRK_SCSI_32)) {
2001 dev->nondasd_support = 0;
2002 dev->jbod = 0;
2003 expose_physicals = 0;
2004 }
2005
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 if(dev->dac_support != 0) {
Yang Hongyang6a355282009-04-06 19:01:13 -07002007 if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(64)) &&
2008 !pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(64))) {
Salyzyn, Mark2f7ecc52008-02-08 08:36:23 -08002009 if (!dev->in_reset)
2010 printk(KERN_INFO"%s%d: 64 Bit DAC enabled\n",
2011 dev->name, dev->id);
Yang Hongyang284901a2009-04-06 19:01:15 -07002012 } else if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(32)) &&
2013 !pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 printk(KERN_INFO"%s%d: DMA mask set failed, 64 Bit DAC disabled\n",
2015 dev->name, dev->id);
2016 dev->dac_support = 0;
2017 } else {
2018 printk(KERN_WARNING"%s%d: No suitable DMA available.\n",
2019 dev->name, dev->id);
2020 rcode = -ENOMEM;
2021 }
2022 }
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002023 /*
Mark Haverkampe8f32de2007-01-23 15:00:30 -08002024 * Deal with configuring for the individualized limits of each packet
2025 * interface.
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07002026 */
Mark Haverkampe8f32de2007-01-23 15:00:30 -08002027 dev->a_ops.adapter_scsi = (dev->dac_support)
Salyzyn, Mark94cf6ba2007-12-13 16:14:18 -08002028 ? ((aac_get_driver_ident(dev->cardtype)->quirks & AAC_QUIRK_SCSI_32)
2029 ? aac_scsi_32_64
2030 : aac_scsi_64)
Mark Haverkampe8f32de2007-01-23 15:00:30 -08002031 : aac_scsi_32;
2032 if (dev->raw_io_interface) {
2033 dev->a_ops.adapter_bounds = (dev->raw_io_64)
2034 ? aac_bounds_64
2035 : aac_bounds_32;
2036 dev->a_ops.adapter_read = aac_read_raw_io;
2037 dev->a_ops.adapter_write = aac_write_raw_io;
2038 } else {
2039 dev->a_ops.adapter_bounds = aac_bounds_32;
Mark Haverkamp0e68c002005-08-03 15:39:49 -07002040 dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07002041 sizeof(struct aac_fibhdr) -
Mark Haverkamp63a70ee2005-09-20 12:57:04 -07002042 sizeof(struct aac_write) + sizeof(struct sgentry)) /
2043 sizeof(struct sgentry);
Mark Haverkamp0e68c002005-08-03 15:39:49 -07002044 if (dev->dac_support) {
Mark Haverkampe8f32de2007-01-23 15:00:30 -08002045 dev->a_ops.adapter_read = aac_read_block64;
2046 dev->a_ops.adapter_write = aac_write_block64;
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002047 /*
2048 * 38 scatter gather elements
Mark Haverkamp0e68c002005-08-03 15:39:49 -07002049 */
2050 dev->scsi_host_ptr->sg_tablesize =
2051 (dev->max_fib_size -
2052 sizeof(struct aac_fibhdr) -
2053 sizeof(struct aac_write64) +
Mark Haverkamp63a70ee2005-09-20 12:57:04 -07002054 sizeof(struct sgentry64)) /
2055 sizeof(struct sgentry64);
Mark Haverkampe8f32de2007-01-23 15:00:30 -08002056 } else {
2057 dev->a_ops.adapter_read = aac_read_block;
2058 dev->a_ops.adapter_write = aac_write_block;
Mark Haverkamp0e68c002005-08-03 15:39:49 -07002059 }
2060 dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
Mahesh Rajashekharae8b12f02011-03-17 02:10:32 -07002061 if (!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
Mark Haverkamp0e68c002005-08-03 15:39:49 -07002062 /*
2063 * Worst case size that could cause sg overflow when
2064 * we break up SG elements that are larger than 64KB.
2065 * Would be nice if we could tell the SCSI layer what
2066 * the maximum SG element size can be. Worst case is
2067 * (sg_tablesize-1) 4KB elements with one 64KB
2068 * element.
2069 * 32bit -> 468 or 238KB 64bit -> 424 or 212KB
2070 */
2071 dev->scsi_host_ptr->max_sectors =
2072 (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
2073 }
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07002074 }
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08002075 if (!dev->sync_mode && dev->sa_firmware &&
2076 dev->scsi_host_ptr->sg_tablesize > HBA_MAX_SG_SEPARATE)
2077 dev->scsi_host_ptr->sg_tablesize = dev->sg_tablesize =
2078 HBA_MAX_SG_SEPARATE;
2079
Penchala Narasimha Reddy Chilakala, ERS-HCLTechcacb6dc2009-12-21 18:39:27 +05302080 /* FIB should be freed only after getting the response from the F/W */
2081 if (rcode != -ERESTARTSYS) {
2082 aac_fib_complete(fibptr);
2083 aac_fib_free(fibptr);
2084 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
2086 return rcode;
2087}
2088
2089
Mark Haverkampe53cb352005-08-03 15:39:09 -07002090static void io_callback(void *context, struct fib * fibptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091{
2092 struct aac_dev *dev;
2093 struct aac_read_reply *readreply;
2094 struct scsi_cmnd *scsicmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 u32 cid;
2096
2097 scsicmd = (struct scsi_cmnd *) context;
2098
Mark Haverkamp03d44332007-03-15 10:27:45 -07002099 if (!aac_valid_context(scsicmd, fibptr))
2100 return;
2101
Salyzyn, Mark1a655042007-06-11 16:17:55 -04002102 dev = fibptr->dev;
Mark Haverkampe5718772006-03-27 09:43:25 -08002103 cid = scmd_id(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002105 if (nblank(dprintk(x))) {
2106 u64 lba;
2107 switch (scsicmd->cmnd[0]) {
2108 case WRITE_6:
2109 case READ_6:
2110 lba = ((scsicmd->cmnd[1] & 0x1F) << 16) |
2111 (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
2112 break;
2113 case WRITE_16:
2114 case READ_16:
2115 lba = ((u64)scsicmd->cmnd[2] << 56) |
2116 ((u64)scsicmd->cmnd[3] << 48) |
2117 ((u64)scsicmd->cmnd[4] << 40) |
2118 ((u64)scsicmd->cmnd[5] << 32) |
2119 ((u64)scsicmd->cmnd[6] << 24) |
2120 (scsicmd->cmnd[7] << 16) |
2121 (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
2122 break;
2123 case WRITE_12:
2124 case READ_12:
2125 lba = ((u64)scsicmd->cmnd[2] << 24) |
2126 (scsicmd->cmnd[3] << 16) |
2127 (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
2128 break;
2129 default:
2130 lba = ((u64)scsicmd->cmnd[2] << 24) |
2131 (scsicmd->cmnd[3] << 16) |
2132 (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
2133 break;
2134 }
2135 printk(KERN_DEBUG
2136 "io_callback[cpu %d]: lba = %llu, t = %ld.\n",
2137 smp_processor_id(), (unsigned long long)lba, jiffies);
2138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
Eric Sesterhenn125e1872006-06-23 02:06:06 -07002140 BUG_ON(fibptr == NULL);
FUJITA Tomonori727eead2007-05-26 02:00:42 +09002141
2142 scsi_dma_unmap(scsicmd);
2143
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 readreply = (struct aac_read_reply *)fib_data(fibptr);
Mark Salyzyn655d7222008-04-30 16:03:42 -04002145 switch (le32_to_cpu(readreply->status)) {
2146 case ST_OK:
2147 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
2148 SAM_STAT_GOOD;
2149 dev->fsa_dev[cid].sense_data.sense_key = NO_SENSE;
2150 break;
2151 case ST_NOT_READY:
2152 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
2153 SAM_STAT_CHECK_CONDITION;
2154 set_sense(&dev->fsa_dev[cid].sense_data, NOT_READY,
2155 SENCODE_BECOMING_READY, ASENCODE_BECOMING_READY, 0, 0);
2156 memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
2157 min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
2158 SCSI_SENSE_BUFFERSIZE));
2159 break;
Raghava Aditya Renukuntaf956a662017-02-02 15:53:23 -08002160 case ST_MEDERR:
2161 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
2162 SAM_STAT_CHECK_CONDITION;
2163 set_sense(&dev->fsa_dev[cid].sense_data, MEDIUM_ERROR,
2164 SENCODE_UNRECOVERED_READ_ERROR, ASENCODE_NO_SENSE, 0, 0);
2165 memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
2166 min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
2167 SCSI_SENSE_BUFFERSIZE));
2168 break;
Mark Salyzyn655d7222008-04-30 16:03:42 -04002169 default:
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07002170#ifdef AAC_DETAILED_STATUS_INFO
Mark Haverkampe53cb352005-08-03 15:39:09 -07002171 printk(KERN_WARNING "io_callback: io failed, status = %d\n",
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07002172 le32_to_cpu(readreply->status));
2173#endif
Mark Salyzyn655d7222008-04-30 16:03:42 -04002174 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
2175 SAM_STAT_CHECK_CONDITION;
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08002176 set_sense(&dev->fsa_dev[cid].sense_data,
2177 HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
2178 ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
Salyzyn, Mark3ace4262008-01-14 07:25:33 -08002180 min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
2181 SCSI_SENSE_BUFFERSIZE));
Mark Salyzyn655d7222008-04-30 16:03:42 -04002182 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 }
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002184 aac_fib_complete(fibptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185
Mark Haverkamp8e0c5eb2005-10-24 10:52:22 -07002186 scsicmd->scsi_done(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187}
2188
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002189static int aac_read(struct scsi_cmnd * scsicmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190{
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002191 u64 lba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 u32 count;
2193 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 struct aac_dev *dev;
2195 struct fib * cmd_fibcontext;
Rajashekhara, Maheshda3cc672010-05-10 04:24:01 -07002196 int cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197
2198 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
2199 /*
2200 * Get block address and transfer length
2201 */
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002202 switch (scsicmd->cmnd[0]) {
2203 case READ_6:
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002204 dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", scmd_id(scsicmd)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002206 lba = ((scsicmd->cmnd[1] & 0x1F) << 16) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002207 (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 count = scsicmd->cmnd[4];
2209
2210 if (count == 0)
2211 count = 256;
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002212 break;
2213 case READ_16:
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002214 dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", scmd_id(scsicmd)));
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002215
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002216 lba = ((u64)scsicmd->cmnd[2] << 56) |
2217 ((u64)scsicmd->cmnd[3] << 48) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002218 ((u64)scsicmd->cmnd[4] << 40) |
2219 ((u64)scsicmd->cmnd[5] << 32) |
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002220 ((u64)scsicmd->cmnd[6] << 24) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002221 (scsicmd->cmnd[7] << 16) |
2222 (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002223 count = (scsicmd->cmnd[10] << 24) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002224 (scsicmd->cmnd[11] << 16) |
2225 (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
2226 break;
2227 case READ_12:
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002228 dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", scmd_id(scsicmd)));
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002229
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002230 lba = ((u64)scsicmd->cmnd[2] << 24) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002231 (scsicmd->cmnd[3] << 16) |
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002232 (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
2233 count = (scsicmd->cmnd[6] << 24) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002234 (scsicmd->cmnd[7] << 16) |
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002235 (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002236 break;
2237 default:
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002238 dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", scmd_id(scsicmd)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002240 lba = ((u64)scsicmd->cmnd[2] << 24) |
2241 (scsicmd->cmnd[3] << 16) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002242 (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002244 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 }
Rajashekhara, Maheshda3cc672010-05-10 04:24:01 -07002246
2247 if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
2248 cid = scmd_id(scsicmd);
2249 dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
2250 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
2251 SAM_STAT_CHECK_CONDITION;
2252 set_sense(&dev->fsa_dev[cid].sense_data,
2253 HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
2254 ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
2255 memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
2256 min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
2257 SCSI_SENSE_BUFFERSIZE));
2258 scsicmd->scsi_done(scsicmd);
2259 return 1;
2260 }
2261
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002262 dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07002263 smp_processor_id(), (unsigned long long)lba, jiffies));
Mark Haverkampe8f32de2007-01-23 15:00:30 -08002264 if (aac_adapter_bounds(dev,scsicmd,lba))
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002265 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 /*
2267 * Alocate and initialize a Fib
2268 */
Raghava Aditya Renukunta6bf3b632016-02-03 15:05:59 -08002269 cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Mark Haverkampe8f32de2007-01-23 15:00:30 -08002271 status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
2273 /*
2274 * Check that the command queued to the controller
2275 */
Mark Haverkamp77d644d2006-03-27 09:43:40 -08002276 if (status == -EINPROGRESS) {
2277 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 return 0;
Mark Haverkamp77d644d2006-03-27 09:43:40 -08002279 }
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002280
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002281 printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 /*
2283 * For some reason, the Fib didn't queue, return QUEUE_FULL
2284 */
2285 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
Mark Haverkamp8e0c5eb2005-10-24 10:52:22 -07002286 scsicmd->scsi_done(scsicmd);
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002287 aac_fib_complete(cmd_fibcontext);
2288 aac_fib_free(cmd_fibcontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 return 0;
2290}
2291
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002292static int aac_write(struct scsi_cmnd * scsicmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293{
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002294 u64 lba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 u32 count;
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002296 int fua;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 struct aac_dev *dev;
2299 struct fib * cmd_fibcontext;
Rajashekhara, Maheshda3cc672010-05-10 04:24:01 -07002300 int cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301
2302 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
2303 /*
2304 * Get block address and transfer length
2305 */
2306 if (scsicmd->cmnd[0] == WRITE_6) /* 6 byte command */
2307 {
2308 lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
2309 count = scsicmd->cmnd[4];
2310 if (count == 0)
2311 count = 256;
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002312 fua = 0;
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002313 } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002314 dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002315
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002316 lba = ((u64)scsicmd->cmnd[2] << 56) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002317 ((u64)scsicmd->cmnd[3] << 48) |
2318 ((u64)scsicmd->cmnd[4] << 40) |
2319 ((u64)scsicmd->cmnd[5] << 32) |
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002320 ((u64)scsicmd->cmnd[6] << 24) |
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002321 (scsicmd->cmnd[7] << 16) |
2322 (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
2323 count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
2324 (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002325 fua = scsicmd->cmnd[1] & 0x8;
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002326 } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002327 dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002328
2329 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16)
2330 | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
2331 count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
2332 | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002333 fua = scsicmd->cmnd[1] & 0x8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 } else {
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002335 dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002336 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002338 fua = scsicmd->cmnd[1] & 0x8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 }
Rajashekhara, Maheshda3cc672010-05-10 04:24:01 -07002340
2341 if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
2342 cid = scmd_id(scsicmd);
2343 dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
2344 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
2345 SAM_STAT_CHECK_CONDITION;
2346 set_sense(&dev->fsa_dev[cid].sense_data,
2347 HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
2348 ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
2349 memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
2350 min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
2351 SCSI_SENSE_BUFFERSIZE));
2352 scsicmd->scsi_done(scsicmd);
2353 return 1;
2354 }
2355
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002356 dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 smp_processor_id(), (unsigned long long)lba, jiffies));
Mark Haverkampe8f32de2007-01-23 15:00:30 -08002358 if (aac_adapter_bounds(dev,scsicmd,lba))
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002359 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 /*
2361 * Allocate and initialize a Fib then setup a BlockWrite command
2362 */
Raghava Aditya Renukunta6bf3b632016-02-03 15:05:59 -08002363 cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002365 status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
2367 /*
2368 * Check that the command queued to the controller
2369 */
Mark Haverkamp77d644d2006-03-27 09:43:40 -08002370 if (status == -EINPROGRESS) {
2371 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 return 0;
2373 }
2374
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002375 printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 /*
2377 * For some reason, the Fib didn't queue, return QUEUE_FULL
2378 */
2379 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
Mark Haverkamp8e0c5eb2005-10-24 10:52:22 -07002380 scsicmd->scsi_done(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002382 aac_fib_complete(cmd_fibcontext);
2383 aac_fib_free(cmd_fibcontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 return 0;
2385}
2386
2387static void synchronize_callback(void *context, struct fib *fibptr)
2388{
2389 struct aac_synchronize_reply *synchronizereply;
2390 struct scsi_cmnd *cmd;
2391
2392 cmd = context;
2393
Mark Haverkamp03d44332007-03-15 10:27:45 -07002394 if (!aac_valid_context(cmd, fibptr))
2395 return;
2396
Salyzyn, Markb90f90d2007-07-27 09:48:49 -04002397 dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 smp_processor_id(), jiffies));
2399 BUG_ON(fibptr == NULL);
2400
2401
2402 synchronizereply = fib_data(fibptr);
2403 if (le32_to_cpu(synchronizereply->status) == CT_OK)
Salyzyn, Markb90f90d2007-07-27 09:48:49 -04002404 cmd->result = DID_OK << 16 |
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
2406 else {
2407 struct scsi_device *sdev = cmd->device;
Salyzyn, Mark1a655042007-06-11 16:17:55 -04002408 struct aac_dev *dev = fibptr->dev;
Mark Haverkampe5718772006-03-27 09:43:25 -08002409 u32 cid = sdev_id(sdev);
Salyzyn, Markb90f90d2007-07-27 09:48:49 -04002410 printk(KERN_WARNING
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 "synchronize_callback: synchronize failed, status = %d\n",
2412 le32_to_cpu(synchronizereply->status));
Salyzyn, Markb90f90d2007-07-27 09:48:49 -04002413 cmd->result = DID_OK << 16 |
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08002415 set_sense(&dev->fsa_dev[cid].sense_data,
2416 HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
2417 ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +09002419 min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
2420 SCSI_SENSE_BUFFERSIZE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 }
2422
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002423 aac_fib_complete(fibptr);
2424 aac_fib_free(fibptr);
Mark Haverkamp8e0c5eb2005-10-24 10:52:22 -07002425 cmd->scsi_done(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426}
2427
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002428static int aac_synchronize(struct scsi_cmnd *scsicmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429{
2430 int status;
2431 struct fib *cmd_fibcontext;
2432 struct aac_synchronize *synchronizecmd;
2433 struct scsi_cmnd *cmd;
2434 struct scsi_device *sdev = scsicmd->device;
2435 int active = 0;
Mark Haverkamp90ee3462006-08-03 08:03:07 -07002436 struct aac_dev *aac;
Salyzyn, Markb90f90d2007-07-27 09:48:49 -04002437 u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) |
2438 (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
2439 u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 unsigned long flags;
2441
2442 /*
Mark Haverkamp77d644d2006-03-27 09:43:40 -08002443 * Wait for all outstanding queued commands to complete to this
2444 * specific target (block).
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 */
2446 spin_lock_irqsave(&sdev->list_lock, flags);
2447 list_for_each_entry(cmd, &sdev->cmd_list, list)
Salyzyn, Markb90f90d2007-07-27 09:48:49 -04002448 if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
2449 u64 cmnd_lba;
2450 u32 cmnd_count;
2451
2452 if (cmd->cmnd[0] == WRITE_6) {
2453 cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) |
2454 (cmd->cmnd[2] << 8) |
2455 cmd->cmnd[3];
2456 cmnd_count = cmd->cmnd[4];
2457 if (cmnd_count == 0)
2458 cmnd_count = 256;
2459 } else if (cmd->cmnd[0] == WRITE_16) {
2460 cmnd_lba = ((u64)cmd->cmnd[2] << 56) |
2461 ((u64)cmd->cmnd[3] << 48) |
2462 ((u64)cmd->cmnd[4] << 40) |
2463 ((u64)cmd->cmnd[5] << 32) |
2464 ((u64)cmd->cmnd[6] << 24) |
2465 (cmd->cmnd[7] << 16) |
2466 (cmd->cmnd[8] << 8) |
2467 cmd->cmnd[9];
2468 cmnd_count = (cmd->cmnd[10] << 24) |
2469 (cmd->cmnd[11] << 16) |
2470 (cmd->cmnd[12] << 8) |
2471 cmd->cmnd[13];
2472 } else if (cmd->cmnd[0] == WRITE_12) {
2473 cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
2474 (cmd->cmnd[3] << 16) |
2475 (cmd->cmnd[4] << 8) |
2476 cmd->cmnd[5];
2477 cmnd_count = (cmd->cmnd[6] << 24) |
2478 (cmd->cmnd[7] << 16) |
2479 (cmd->cmnd[8] << 8) |
2480 cmd->cmnd[9];
2481 } else if (cmd->cmnd[0] == WRITE_10) {
2482 cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
2483 (cmd->cmnd[3] << 16) |
2484 (cmd->cmnd[4] << 8) |
2485 cmd->cmnd[5];
2486 cmnd_count = (cmd->cmnd[7] << 8) |
2487 cmd->cmnd[8];
2488 } else
2489 continue;
2490 if (((cmnd_lba + cmnd_count) < lba) ||
2491 (count && ((lba + count) < cmnd_lba)))
2492 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 ++active;
2494 break;
2495 }
2496
2497 spin_unlock_irqrestore(&sdev->list_lock, flags);
2498
2499 /*
2500 * Yield the processor (requeue for later)
2501 */
2502 if (active)
2503 return SCSI_MLQUEUE_DEVICE_BUSY;
2504
Salyzyn, Markf8583172007-10-30 15:50:49 -04002505 aac = (struct aac_dev *)sdev->host->hostdata;
Mark Haverkamp8c867b22006-08-03 08:03:30 -07002506 if (aac->in_reset)
2507 return SCSI_MLQUEUE_HOST_BUSY;
2508
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 /*
Mark Haverkamp 7c00ffa2005-05-16 18:28:42 -07002510 * Allocate and initialize a Fib
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 */
Mark Haverkamp90ee3462006-08-03 08:03:07 -07002512 if (!(cmd_fibcontext = aac_fib_alloc(aac)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 return SCSI_MLQUEUE_HOST_BUSY;
2514
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002515 aac_fib_init(cmd_fibcontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
2517 synchronizecmd = fib_data(cmd_fibcontext);
2518 synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
2519 synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE);
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002520 synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));
Salyzyn, Markb90f90d2007-07-27 09:48:49 -04002521 synchronizecmd->count =
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
2523
2524 /*
2525 * Now send the Fib to the adapter
2526 */
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002527 status = aac_fib_send(ContainerCommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 cmd_fibcontext,
2529 sizeof(struct aac_synchronize),
2530 FsaNormal,
2531 0, 1,
2532 (fib_callback)synchronize_callback,
2533 (void *)scsicmd);
2534
2535 /*
2536 * Check that the command queued to the controller
2537 */
Mark Haverkamp77d644d2006-03-27 09:43:40 -08002538 if (status == -EINPROGRESS) {
2539 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 return 0;
Mark Haverkamp77d644d2006-03-27 09:43:40 -08002541 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
Salyzyn, Markb90f90d2007-07-27 09:48:49 -04002543 printk(KERN_WARNING
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08002544 "aac_synchronize: aac_fib_send failed with status: %d.\n", status);
2545 aac_fib_complete(cmd_fibcontext);
2546 aac_fib_free(cmd_fibcontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 return SCSI_MLQUEUE_HOST_BUSY;
2548}
2549
Mark Salyzyn655d7222008-04-30 16:03:42 -04002550static void aac_start_stop_callback(void *context, struct fib *fibptr)
2551{
2552 struct scsi_cmnd *scsicmd = context;
2553
2554 if (!aac_valid_context(scsicmd, fibptr))
2555 return;
2556
2557 BUG_ON(fibptr == NULL);
2558
2559 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
2560
2561 aac_fib_complete(fibptr);
2562 aac_fib_free(fibptr);
2563 scsicmd->scsi_done(scsicmd);
2564}
2565
2566static int aac_start_stop(struct scsi_cmnd *scsicmd)
2567{
2568 int status;
2569 struct fib *cmd_fibcontext;
2570 struct aac_power_management *pmcmd;
2571 struct scsi_device *sdev = scsicmd->device;
2572 struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
2573
2574 if (!(aac->supplement_adapter_info.SupportedOptions2 &
2575 AAC_OPTION_POWER_MANAGEMENT)) {
2576 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
2577 SAM_STAT_GOOD;
2578 scsicmd->scsi_done(scsicmd);
2579 return 0;
2580 }
2581
2582 if (aac->in_reset)
2583 return SCSI_MLQUEUE_HOST_BUSY;
2584
2585 /*
2586 * Allocate and initialize a Fib
2587 */
Raghava Aditya Renukunta6bf3b632016-02-03 15:05:59 -08002588 cmd_fibcontext = aac_fib_alloc_tag(aac, scsicmd);
Mark Salyzyn655d7222008-04-30 16:03:42 -04002589
2590 aac_fib_init(cmd_fibcontext);
2591
2592 pmcmd = fib_data(cmd_fibcontext);
2593 pmcmd->command = cpu_to_le32(VM_ContainerConfig);
2594 pmcmd->type = cpu_to_le32(CT_POWER_MANAGEMENT);
2595 /* Eject bit ignored, not relevant */
2596 pmcmd->sub = (scsicmd->cmnd[4] & 1) ?
2597 cpu_to_le32(CT_PM_START_UNIT) : cpu_to_le32(CT_PM_STOP_UNIT);
2598 pmcmd->cid = cpu_to_le32(sdev_id(sdev));
2599 pmcmd->parm = (scsicmd->cmnd[1] & 1) ?
2600 cpu_to_le32(CT_PM_UNIT_IMMEDIATE) : 0;
2601
2602 /*
2603 * Now send the Fib to the adapter
2604 */
2605 status = aac_fib_send(ContainerCommand,
2606 cmd_fibcontext,
2607 sizeof(struct aac_power_management),
2608 FsaNormal,
2609 0, 1,
2610 (fib_callback)aac_start_stop_callback,
2611 (void *)scsicmd);
2612
2613 /*
2614 * Check that the command queued to the controller
2615 */
2616 if (status == -EINPROGRESS) {
2617 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
2618 return 0;
2619 }
2620
2621 aac_fib_complete(cmd_fibcontext);
2622 aac_fib_free(cmd_fibcontext);
2623 return SCSI_MLQUEUE_HOST_BUSY;
2624}
2625
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626/**
2627 * aac_scsi_cmd() - Process SCSI command
2628 * @scsicmd: SCSI command block
2629 *
2630 * Emulate a SCSI command and queue the required request for the
2631 * aacraid firmware.
2632 */
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002633
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
2635{
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08002636 u32 cid, bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 struct Scsi_Host *host = scsicmd->device->host;
2638 struct aac_dev *dev = (struct aac_dev *)host->hostdata;
2639 struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002640
Mark Haverkamp90ee3462006-08-03 08:03:07 -07002641 if (fsa_dev_ptr == NULL)
2642 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 /*
2644 * If the bus, id or lun is out of range, return fail
2645 * Test does not apply to ID 16, the pseudo id for the controller
2646 * itself.
2647 */
Salyzyn, Mark1a655042007-06-11 16:17:55 -04002648 cid = scmd_id(scsicmd);
2649 if (cid != host->this_id) {
2650 if (scmd_channel(scsicmd) == CONTAINER_CHANNEL) {
2651 if((cid >= dev->maximum_num_containers) ||
Mark Haverkampe5718772006-03-27 09:43:25 -08002652 (scsicmd->device->lun != 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 scsicmd->result = DID_NO_CONNECT << 16;
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002654 goto scsi_done_ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656
2657 /*
2658 * If the target container doesn't exist, it may have
2659 * been newly created
2660 */
Mark Salyzyn655d7222008-04-30 16:03:42 -04002661 if (((fsa_dev_ptr[cid].valid & 1) == 0) ||
2662 (fsa_dev_ptr[cid].sense_data.sense_key ==
2663 NOT_READY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 switch (scsicmd->cmnd[0]) {
Hannes Reineckeeb846d92014-11-17 14:25:19 +01002665 case SERVICE_ACTION_IN_16:
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002666 if (!(dev->raw_io_interface) ||
2667 !(dev->raw_io_64) ||
2668 ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
2669 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 case INQUIRY:
2671 case READ_CAPACITY:
2672 case TEST_UNIT_READY:
Mark Haverkamp8c867b22006-08-03 08:03:30 -07002673 if (dev->in_reset)
2674 return -1;
Mark Haverkampfe76df42007-03-15 12:55:07 -07002675 return _aac_probe_container(scsicmd,
2676 aac_probe_container_callback2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 default:
2678 break;
2679 }
2680 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 } else { /* check for physical non-dasd devices */
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08002682 bus = aac_logical_to_phys(scmd_channel(scsicmd));
2683 if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS &&
2684 (dev->hba_map[bus][cid].expose
2685 == AAC_HIDE_DISK)){
2686 if (scsicmd->cmnd[0] == INQUIRY) {
2687 scsicmd->result = DID_NO_CONNECT << 16;
2688 goto scsi_done_ret;
2689 }
2690 }
2691
2692 if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS &&
2693 dev->hba_map[bus][cid].devtype
2694 == AAC_DEVTYPE_NATIVE_RAW) {
2695 if (dev->in_reset)
2696 return -1;
2697 return aac_send_hba_fib(scsicmd);
2698 } else if (dev->nondasd_support || expose_physicals ||
2699 dev->jbod) {
Mark Haverkamp8c867b22006-08-03 08:03:30 -07002700 if (dev->in_reset)
2701 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 return aac_send_srb_fib(scsicmd);
2703 } else {
2704 scsicmd->result = DID_NO_CONNECT << 16;
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002705 goto scsi_done_ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 }
2707 }
2708 }
2709 /*
2710 * else Command for the controller itself
2711 */
2712 else if ((scsicmd->cmnd[0] != INQUIRY) && /* only INQUIRY & TUR cmnd supported for controller */
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08002713 (scsicmd->cmnd[0] != TEST_UNIT_READY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 {
2715 dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0]));
2716 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08002717 set_sense(&dev->fsa_dev[cid].sense_data,
2718 ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
2719 ASENCODE_INVALID_COMMAND, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
Salyzyn, Mark3ace4262008-01-14 07:25:33 -08002721 min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
2722 SCSI_SENSE_BUFFERSIZE));
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002723 goto scsi_done_ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 }
2725
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 switch (scsicmd->cmnd[0]) {
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002727 case READ_6:
2728 case READ_10:
2729 case READ_12:
2730 case READ_16:
2731 if (dev->in_reset)
2732 return -1;
2733 return aac_read(scsicmd);
2734
2735 case WRITE_6:
2736 case WRITE_10:
2737 case WRITE_12:
2738 case WRITE_16:
2739 if (dev->in_reset)
2740 return -1;
2741 return aac_write(scsicmd);
2742
2743 case SYNCHRONIZE_CACHE:
2744 if (((aac_cache & 6) == 6) && dev->cache_protected) {
2745 scsicmd->result = AAC_STAT_GOOD;
2746 break;
2747 }
2748 /* Issue FIB to tell Firmware to flush it's cache */
2749 if ((aac_cache & 6) != 2)
2750 return aac_synchronize(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 case INQUIRY:
2752 {
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002753 struct inquiry_data inq_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
Salyzyn, Mark1a655042007-06-11 16:17:55 -04002755 dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002756 memset(&inq_data, 0, sizeof (struct inquiry_data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
Leubner, Achimd8e965072009-04-01 07:16:08 -07002758 if ((scsicmd->cmnd[1] & 0x1) && aac_wwn) {
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04002759 char *arr = (char *)&inq_data;
2760
2761 /* EVPD bit set */
2762 arr[0] = (scmd_id(scsicmd) == host->this_id) ?
2763 INQD_PDT_PROC : INQD_PDT_DA;
2764 if (scsicmd->cmnd[2] == 0) {
2765 /* supported vital product data pages */
Mahesh Rajashekhara5d910642015-03-26 10:41:26 -04002766 arr[3] = 3;
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04002767 arr[4] = 0x0;
2768 arr[5] = 0x80;
Mahesh Rajashekhara5d910642015-03-26 10:41:26 -04002769 arr[6] = 0x83;
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04002770 arr[1] = scsicmd->cmnd[2];
FUJITA Tomonorid4345022008-03-09 13:44:34 +09002771 scsi_sg_copy_from_buffer(scsicmd, &inq_data,
2772 sizeof(inq_data));
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002773 scsicmd->result = AAC_STAT_GOOD;
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04002774 } else if (scsicmd->cmnd[2] == 0x80) {
2775 /* unit serial number page */
2776 arr[3] = setinqserial(dev, &arr[4],
2777 scmd_id(scsicmd));
2778 arr[1] = scsicmd->cmnd[2];
FUJITA Tomonorid4345022008-03-09 13:44:34 +09002779 scsi_sg_copy_from_buffer(scsicmd, &inq_data,
2780 sizeof(inq_data));
Leubner, Achimd8e965072009-04-01 07:16:08 -07002781 if (aac_wwn != 2)
2782 return aac_get_container_serial(
2783 scsicmd);
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002784 scsicmd->result = AAC_STAT_GOOD;
Mahesh Rajashekhara5d910642015-03-26 10:41:26 -04002785 } else if (scsicmd->cmnd[2] == 0x83) {
2786 /* vpd page 0x83 - Device Identification Page */
2787 char *sno = (char *)&inq_data;
2788 sno[3] = setinqserial(dev, &sno[4],
2789 scmd_id(scsicmd));
2790 if (aac_wwn != 2)
2791 return aac_get_container_serial(
2792 scsicmd);
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002793 scsicmd->result = AAC_STAT_GOOD;
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04002794 } else {
2795 /* vpd page not implemented */
2796 scsicmd->result = DID_OK << 16 |
2797 COMMAND_COMPLETE << 8 |
2798 SAM_STAT_CHECK_CONDITION;
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08002799 set_sense(&dev->fsa_dev[cid].sense_data,
2800 ILLEGAL_REQUEST, SENCODE_INVALID_CDB_FIELD,
2801 ASENCODE_NO_SENSE, 7, 2);
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04002802 memcpy(scsicmd->sense_buffer,
2803 &dev->fsa_dev[cid].sense_data,
Salyzyn, Mark3ace4262008-01-14 07:25:33 -08002804 min_t(size_t,
2805 sizeof(dev->fsa_dev[cid].sense_data),
2806 SCSI_SENSE_BUFFERSIZE));
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04002807 }
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002808 break;
Salyzyn, Mark88e2f982007-07-17 14:01:28 -04002809 }
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002810 inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002811 inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
2812 inq_data.inqd_len = 31;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002814 inq_data.inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 /*
2816 * Set the Vendor, Product, and Revision Level
2817 * see: <vendor>.c i.e. aac.c
2818 */
Salyzyn, Mark1a655042007-06-11 16:17:55 -04002819 if (cid == host->this_id) {
Tobias Klauser6391a112006-06-08 22:23:48 -07002820 setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002821 inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */
FUJITA Tomonorid4345022008-03-09 13:44:34 +09002822 scsi_sg_copy_from_buffer(scsicmd, &inq_data,
2823 sizeof(inq_data));
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002824 scsicmd->result = AAC_STAT_GOOD;
2825 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 }
Mark Haverkamp8c867b22006-08-03 08:03:30 -07002827 if (dev->in_reset)
2828 return -1;
Mark Haverkamp794d0602005-10-24 10:51:53 -07002829 setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002830 inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
FUJITA Tomonorid4345022008-03-09 13:44:34 +09002831 scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
Mark Haverkamp9e7c3492007-03-15 10:26:55 -07002832 return aac_get_container_name(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 }
Hannes Reineckeeb846d92014-11-17 14:25:19 +01002834 case SERVICE_ACTION_IN_16:
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002835 if (!(dev->raw_io_interface) ||
2836 !(dev->raw_io_64) ||
2837 ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
2838 break;
2839 {
2840 u64 capacity;
Mark Haverkamp07ce5eb2005-11-08 14:26:33 -08002841 char cp[13];
FUJITA Tomonorib271f1c2008-02-24 15:25:23 -08002842 unsigned int alloc_len;
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002843
2844 dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
2845 capacity = fsa_dev_ptr[cid].size - 1;
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002846 cp[0] = (capacity >> 56) & 0xff;
2847 cp[1] = (capacity >> 48) & 0xff;
2848 cp[2] = (capacity >> 40) & 0xff;
2849 cp[3] = (capacity >> 32) & 0xff;
2850 cp[4] = (capacity >> 24) & 0xff;
2851 cp[5] = (capacity >> 16) & 0xff;
2852 cp[6] = (capacity >> 8) & 0xff;
2853 cp[7] = (capacity >> 0) & 0xff;
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002854 cp[8] = (fsa_dev_ptr[cid].block_size >> 24) & 0xff;
2855 cp[9] = (fsa_dev_ptr[cid].block_size >> 16) & 0xff;
2856 cp[10] = (fsa_dev_ptr[cid].block_size >> 8) & 0xff;
2857 cp[11] = (fsa_dev_ptr[cid].block_size) & 0xff;
Mark Haverkamp07ce5eb2005-11-08 14:26:33 -08002858 cp[12] = 0;
Mark Haverkamp07ce5eb2005-11-08 14:26:33 -08002859
FUJITA Tomonorib271f1c2008-02-24 15:25:23 -08002860 alloc_len = ((scsicmd->cmnd[10] << 24)
2861 + (scsicmd->cmnd[11] << 16)
2862 + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]);
2863
2864 alloc_len = min_t(size_t, alloc_len, sizeof(cp));
FUJITA Tomonorid4345022008-03-09 13:44:34 +09002865 scsi_sg_copy_from_buffer(scsicmd, cp, alloc_len);
FUJITA Tomonorib271f1c2008-02-24 15:25:23 -08002866 if (alloc_len < scsi_bufflen(scsicmd))
2867 scsi_set_resid(scsicmd,
2868 scsi_bufflen(scsicmd) - alloc_len);
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002869
2870 /* Do not cache partition table for arrays */
2871 scsicmd->device->removable = 1;
2872
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002873 scsicmd->result = AAC_STAT_GOOD;
2874 break;
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002875 }
2876
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 case READ_CAPACITY:
2878 {
2879 u32 capacity;
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002880 char cp[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
2882 dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002883 if (fsa_dev_ptr[cid].size <= 0x100000000ULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 capacity = fsa_dev_ptr[cid].size - 1;
2885 else
2886 capacity = (u32)-1;
Mark Haverkamp3b2946c2005-08-15 10:50:24 -07002887
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 cp[0] = (capacity >> 24) & 0xff;
2889 cp[1] = (capacity >> 16) & 0xff;
2890 cp[2] = (capacity >> 8) & 0xff;
2891 cp[3] = (capacity >> 0) & 0xff;
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002892 cp[4] = (fsa_dev_ptr[cid].block_size >> 24) & 0xff;
2893 cp[5] = (fsa_dev_ptr[cid].block_size >> 16) & 0xff;
2894 cp[6] = (fsa_dev_ptr[cid].block_size >> 8) & 0xff;
2895 cp[7] = (fsa_dev_ptr[cid].block_size) & 0xff;
FUJITA Tomonorid4345022008-03-09 13:44:34 +09002896 scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
Mark Haverkamp7a8cf292005-09-22 09:15:24 -07002897 /* Do not cache partition table for arrays */
2898 scsicmd->device->removable = 1;
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002899 scsicmd->result = AAC_STAT_GOOD;
2900 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901 }
2902
2903 case MODE_SENSE:
2904 {
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002905 int mode_buf_length = 4;
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002906 u32 capacity;
2907 aac_modep_data mpd;
2908
2909 if (fsa_dev_ptr[cid].size <= 0x100000000ULL)
2910 capacity = fsa_dev_ptr[cid].size - 1;
2911 else
2912 capacity = (u32)-1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913
2914 dprintk((KERN_DEBUG "MODE SENSE command.\n"));
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002915 memset((char *)&mpd, 0, sizeof(aac_modep_data));
2916
2917 /* Mode data length */
2918 mpd.hd.data_length = sizeof(mpd.hd) - 1;
2919 /* Medium type - default */
2920 mpd.hd.med_type = 0;
2921 /* Device-specific param,
2922 bit 8: 0/1 = write enabled/protected
2923 bit 4: 0/1 = FUA enabled */
2924 mpd.hd.dev_par = 0;
2925
Salyzyn, Mark95e852e2008-01-08 12:01:07 -08002926 if (dev->raw_io_interface && ((aac_cache & 5) != 1))
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002927 mpd.hd.dev_par = 0x10;
2928 if (scsicmd->cmnd[1] & 0x8)
2929 mpd.hd.bd_length = 0; /* Block descriptor length */
2930 else {
2931 mpd.hd.bd_length = sizeof(mpd.bd);
2932 mpd.hd.data_length += mpd.hd.bd_length;
2933 mpd.bd.block_length[0] =
2934 (fsa_dev_ptr[cid].block_size >> 16) & 0xff;
2935 mpd.bd.block_length[1] =
2936 (fsa_dev_ptr[cid].block_size >> 8) & 0xff;
2937 mpd.bd.block_length[2] =
2938 fsa_dev_ptr[cid].block_size & 0xff;
Mahesh Rajashekhara5d910642015-03-26 10:41:26 -04002939
2940 mpd.mpc_buf[0] = scsicmd->cmnd[2];
2941 if (scsicmd->cmnd[2] == 0x1C) {
2942 /* page length */
2943 mpd.mpc_buf[1] = 0xa;
2944 /* Mode data length */
2945 mpd.hd.data_length = 23;
2946 } else {
2947 /* Mode data length */
2948 mpd.hd.data_length = 15;
2949 }
2950
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002951 if (capacity > 0xffffff) {
2952 mpd.bd.block_count[0] = 0xff;
2953 mpd.bd.block_count[1] = 0xff;
2954 mpd.bd.block_count[2] = 0xff;
2955 } else {
2956 mpd.bd.block_count[0] = (capacity >> 16) & 0xff;
2957 mpd.bd.block_count[1] = (capacity >> 8) & 0xff;
2958 mpd.bd.block_count[2] = capacity & 0xff;
2959 }
2960 }
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002961 if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
2962 ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002963 mpd.hd.data_length += 3;
2964 mpd.mpc_buf[0] = 8;
2965 mpd.mpc_buf[1] = 1;
2966 mpd.mpc_buf[2] = ((aac_cache & 6) == 2)
Salyzyn, Mark95e852e2008-01-08 12:01:07 -08002967 ? 0 : 0x04; /* WCE */
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002968 mode_buf_length = sizeof(mpd);
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002969 }
Mahesh Rajashekhara5d910642015-03-26 10:41:26 -04002970
2971 if (mode_buf_length > scsicmd->cmnd[4])
2972 mode_buf_length = scsicmd->cmnd[4];
2973 else
2974 mode_buf_length = sizeof(mpd);
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002975 scsi_sg_copy_from_buffer(scsicmd,
2976 (char *)&mpd,
2977 mode_buf_length);
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08002978 scsicmd->result = AAC_STAT_GOOD;
2979 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 }
2981 case MODE_SENSE_10:
2982 {
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002983 u32 capacity;
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04002984 int mode_buf_length = 8;
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002985 aac_modep10_data mpd10;
2986
2987 if (fsa_dev_ptr[cid].size <= 0x100000000ULL)
2988 capacity = fsa_dev_ptr[cid].size - 1;
2989 else
2990 capacity = (u32)-1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991
2992 dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04002993 memset((char *)&mpd10, 0, sizeof(aac_modep10_data));
2994 /* Mode data length (MSB) */
2995 mpd10.hd.data_length[0] = 0;
2996 /* Mode data length (LSB) */
2997 mpd10.hd.data_length[1] = sizeof(mpd10.hd) - 1;
2998 /* Medium type - default */
2999 mpd10.hd.med_type = 0;
3000 /* Device-specific param,
3001 bit 8: 0/1 = write enabled/protected
3002 bit 4: 0/1 = FUA enabled */
3003 mpd10.hd.dev_par = 0;
3004
Salyzyn, Mark95e852e2008-01-08 12:01:07 -08003005 if (dev->raw_io_interface && ((aac_cache & 5) != 1))
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04003006 mpd10.hd.dev_par = 0x10;
3007 mpd10.hd.rsrvd[0] = 0; /* reserved */
3008 mpd10.hd.rsrvd[1] = 0; /* reserved */
3009 if (scsicmd->cmnd[1] & 0x8) {
3010 /* Block descriptor length (MSB) */
3011 mpd10.hd.bd_length[0] = 0;
3012 /* Block descriptor length (LSB) */
3013 mpd10.hd.bd_length[1] = 0;
3014 } else {
3015 mpd10.hd.bd_length[0] = 0;
3016 mpd10.hd.bd_length[1] = sizeof(mpd10.bd);
3017
3018 mpd10.hd.data_length[1] += mpd10.hd.bd_length[1];
3019
3020 mpd10.bd.block_length[0] =
3021 (fsa_dev_ptr[cid].block_size >> 16) & 0xff;
3022 mpd10.bd.block_length[1] =
3023 (fsa_dev_ptr[cid].block_size >> 8) & 0xff;
3024 mpd10.bd.block_length[2] =
3025 fsa_dev_ptr[cid].block_size & 0xff;
3026
3027 if (capacity > 0xffffff) {
3028 mpd10.bd.block_count[0] = 0xff;
3029 mpd10.bd.block_count[1] = 0xff;
3030 mpd10.bd.block_count[2] = 0xff;
3031 } else {
3032 mpd10.bd.block_count[0] =
3033 (capacity >> 16) & 0xff;
3034 mpd10.bd.block_count[1] =
3035 (capacity >> 8) & 0xff;
3036 mpd10.bd.block_count[2] =
3037 capacity & 0xff;
3038 }
3039 }
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04003040 if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
3041 ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04003042 mpd10.hd.data_length[1] += 3;
3043 mpd10.mpc_buf[0] = 8;
3044 mpd10.mpc_buf[1] = 1;
3045 mpd10.mpc_buf[2] = ((aac_cache & 6) == 2)
Salyzyn, Mark95e852e2008-01-08 12:01:07 -08003046 ? 0 : 0x04; /* WCE */
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04003047 mode_buf_length = sizeof(mpd10);
Salyzyn, Mark9d399cc2007-05-18 14:51:34 -04003048 if (mode_buf_length > scsicmd->cmnd[8])
3049 mode_buf_length = scsicmd->cmnd[8];
3050 }
Mahesh Rajashekharab8364392015-03-26 10:41:24 -04003051 scsi_sg_copy_from_buffer(scsicmd,
3052 (char *)&mpd10,
3053 mode_buf_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08003055 scsicmd->result = AAC_STAT_GOOD;
3056 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 }
3058 case REQUEST_SENSE:
3059 dprintk((KERN_DEBUG "REQUEST SENSE command.\n"));
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08003060 memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
3061 sizeof(struct sense_data));
3062 memset(&dev->fsa_dev[cid].sense_data, 0,
3063 sizeof(struct sense_data));
3064 scsicmd->result = AAC_STAT_GOOD;
3065 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066
3067 case ALLOW_MEDIUM_REMOVAL:
3068 dprintk((KERN_DEBUG "LOCK command.\n"));
3069 if (scsicmd->cmnd[4])
3070 fsa_dev_ptr[cid].locked = 1;
3071 else
3072 fsa_dev_ptr[cid].locked = 0;
3073
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08003074 scsicmd->result = AAC_STAT_GOOD;
3075 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 /*
3077 * These commands are all No-Ops
3078 */
3079 case TEST_UNIT_READY:
Mark Salyzyn655d7222008-04-30 16:03:42 -04003080 if (fsa_dev_ptr[cid].sense_data.sense_key == NOT_READY) {
3081 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
3082 SAM_STAT_CHECK_CONDITION;
3083 set_sense(&dev->fsa_dev[cid].sense_data,
3084 NOT_READY, SENCODE_BECOMING_READY,
3085 ASENCODE_BECOMING_READY, 0, 0);
3086 memcpy(scsicmd->sense_buffer,
3087 &dev->fsa_dev[cid].sense_data,
3088 min_t(size_t,
3089 sizeof(dev->fsa_dev[cid].sense_data),
3090 SCSI_SENSE_BUFFERSIZE));
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08003091 break;
Mark Salyzyn655d7222008-04-30 16:03:42 -04003092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093 case RESERVE:
3094 case RELEASE:
3095 case REZERO_UNIT:
3096 case REASSIGN_BLOCKS:
3097 case SEEK_10:
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08003098 scsicmd->result = AAC_STAT_GOOD;
3099 break;
Mark Salyzyn655d7222008-04-30 16:03:42 -04003100
3101 case START_STOP:
3102 return aac_start_stop(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08003104 /* FALLTHRU */
3105 default:
3106 /*
3107 * Unhandled commands
3108 */
3109 dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n",
3110 scsicmd->cmnd[0]));
3111 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
3112 SAM_STAT_CHECK_CONDITION;
3113 set_sense(&dev->fsa_dev[cid].sense_data,
Salyzyn, Mark8e31e602008-02-06 13:54:12 -08003114 ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
3115 ASENCODE_INVALID_COMMAND, 0, 0);
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08003116 memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
Salyzyn, Mark3ace4262008-01-14 07:25:33 -08003117 min_t(size_t,
3118 sizeof(dev->fsa_dev[cid].sense_data),
3119 SCSI_SENSE_BUFFERSIZE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 }
Raghava Aditya Renukuntac4e2fbc2017-02-02 15:53:20 -08003121
3122scsi_done_ret:
3123
3124 scsicmd->scsi_done(scsicmd);
3125 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126}
3127
3128static int query_disk(struct aac_dev *dev, void __user *arg)
3129{
3130 struct aac_query_disk qd;
3131 struct fsa_dev_info *fsa_dev_ptr;
3132
3133 fsa_dev_ptr = dev->fsa_dev;
Mark Haverkamp90ee3462006-08-03 08:03:07 -07003134 if (!fsa_dev_ptr)
Mark Haverkamp65101352006-09-19 08:59:23 -07003135 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
3137 return -EFAULT;
3138 if (qd.cnum == -1)
Mark Haverkampe5718772006-03-27 09:43:25 -08003139 qd.cnum = qd.id;
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08003140 else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 {
3142 if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers)
3143 return -EINVAL;
3144 qd.instance = dev->scsi_host_ptr->host_no;
3145 qd.bus = 0;
3146 qd.id = CONTAINER_TO_ID(qd.cnum);
3147 qd.lun = CONTAINER_TO_LUN(qd.cnum);
3148 }
3149 else return -EINVAL;
3150
Salyzyn, Markfd622b12007-07-17 10:59:19 -04003151 qd.valid = fsa_dev_ptr[qd.cnum].valid != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 qd.locked = fsa_dev_ptr[qd.cnum].locked;
3153 qd.deleted = fsa_dev_ptr[qd.cnum].deleted;
3154
3155 if (fsa_dev_ptr[qd.cnum].devname[0] == '\0')
3156 qd.unmapped = 1;
3157 else
3158 qd.unmapped = 0;
3159
3160 strlcpy(qd.name, fsa_dev_ptr[qd.cnum].devname,
3161 min(sizeof(qd.name), sizeof(fsa_dev_ptr[qd.cnum].devname) + 1));
3162
3163 if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk)))
3164 return -EFAULT;
3165 return 0;
3166}
3167
3168static int force_delete_disk(struct aac_dev *dev, void __user *arg)
3169{
3170 struct aac_delete_disk dd;
3171 struct fsa_dev_info *fsa_dev_ptr;
3172
3173 fsa_dev_ptr = dev->fsa_dev;
Mark Haverkamp65101352006-09-19 08:59:23 -07003174 if (!fsa_dev_ptr)
3175 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176
3177 if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
3178 return -EFAULT;
3179
3180 if (dd.cnum >= dev->maximum_num_containers)
3181 return -EINVAL;
3182 /*
3183 * Mark this container as being deleted.
3184 */
3185 fsa_dev_ptr[dd.cnum].deleted = 1;
3186 /*
3187 * Mark the container as no longer valid
3188 */
3189 fsa_dev_ptr[dd.cnum].valid = 0;
3190 return 0;
3191}
3192
3193static int delete_disk(struct aac_dev *dev, void __user *arg)
3194{
3195 struct aac_delete_disk dd;
3196 struct fsa_dev_info *fsa_dev_ptr;
3197
3198 fsa_dev_ptr = dev->fsa_dev;
Mark Haverkamp90ee3462006-08-03 08:03:07 -07003199 if (!fsa_dev_ptr)
Mark Haverkamp65101352006-09-19 08:59:23 -07003200 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201
3202 if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
3203 return -EFAULT;
3204
3205 if (dd.cnum >= dev->maximum_num_containers)
3206 return -EINVAL;
3207 /*
3208 * If the container is locked, it can not be deleted by the API.
3209 */
3210 if (fsa_dev_ptr[dd.cnum].locked)
3211 return -EBUSY;
3212 else {
3213 /*
3214 * Mark the container as no longer being valid.
3215 */
3216 fsa_dev_ptr[dd.cnum].valid = 0;
3217 fsa_dev_ptr[dd.cnum].devname[0] = '\0';
3218 return 0;
3219 }
3220}
3221
3222int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg)
3223{
3224 switch (cmd) {
3225 case FSACTL_QUERY_DISK:
3226 return query_disk(dev, arg);
3227 case FSACTL_DELETE_DISK:
3228 return delete_disk(dev, arg);
3229 case FSACTL_FORCE_DELETE_DISK:
3230 return force_delete_disk(dev, arg);
3231 case FSACTL_GET_CONTAINERS:
3232 return aac_get_containers(dev);
3233 default:
3234 return -ENOTTY;
3235 }
3236}
3237
3238/**
3239 *
3240 * aac_srb_callback
3241 * @context: the context set in the fib - here it is scsi cmd
3242 * @fibptr: pointer to the fib
3243 *
3244 * Handles the completion of a scsi command to a non dasd device
3245 *
3246 */
3247
3248static void aac_srb_callback(void *context, struct fib * fibptr)
3249{
3250 struct aac_dev *dev;
3251 struct aac_srb_reply *srbreply;
3252 struct scsi_cmnd *scsicmd;
3253
3254 scsicmd = (struct scsi_cmnd *) context;
Mark Haverkamp03d44332007-03-15 10:27:45 -07003255
3256 if (!aac_valid_context(scsicmd, fibptr))
3257 return;
3258
Eric Sesterhenn125e1872006-06-23 02:06:06 -07003259 BUG_ON(fibptr == NULL);
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003260
Salyzyn, Mark1a655042007-06-11 16:17:55 -04003261 dev = fibptr->dev;
3262
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003263 srbreply = (struct aac_srb_reply *) fib_data(fibptr);
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003264
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265 scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05303267 if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) {
3268 /* fast response */
3269 srbreply->srb_status = cpu_to_le32(SRB_STATUS_SUCCESS);
3270 srbreply->scsi_status = cpu_to_le32(SAM_STAT_GOOD);
3271 } else {
3272 /*
3273 * Calculate resid for sg
3274 */
3275 scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
3276 - le32_to_cpu(srbreply->data_xfer_length));
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003277 }
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003278
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003280 scsi_dma_unmap(scsicmd);
3281
3282 /* expose physical device if expose_physicald flag is on */
3283 if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
3284 && expose_physicals > 0)
3285 aac_expose_phy_device(scsicmd);
3286
3287 /*
3288 * First check the fib status
3289 */
3290
3291 if (le32_to_cpu(srbreply->status) != ST_OK) {
3292 int len;
3293
3294 pr_warn("aac_srb_callback: srb failed, status = %d\n",
3295 le32_to_cpu(srbreply->status));
3296 len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
3297 SCSI_SENSE_BUFFERSIZE);
3298 scsicmd->result = DID_ERROR << 16
3299 | COMMAND_COMPLETE << 8
3300 | SAM_STAT_CHECK_CONDITION;
3301 memcpy(scsicmd->sense_buffer,
3302 srbreply->sense_data, len);
3303 }
3304
3305 /*
3306 * Next check the srb status
3307 */
3308 switch ((le32_to_cpu(srbreply->srb_status))&0x3f) {
3309 case SRB_STATUS_ERROR_RECOVERY:
3310 case SRB_STATUS_PENDING:
3311 case SRB_STATUS_SUCCESS:
3312 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
3313 break;
3314 case SRB_STATUS_DATA_OVERRUN:
3315 switch (scsicmd->cmnd[0]) {
3316 case READ_6:
3317 case WRITE_6:
3318 case READ_10:
3319 case WRITE_10:
3320 case READ_12:
3321 case WRITE_12:
3322 case READ_16:
3323 case WRITE_16:
3324 if (le32_to_cpu(srbreply->data_xfer_length)
3325 < scsicmd->underflow)
3326 pr_warn("aacraid: SCSI CMD underflow\n");
3327 else
3328 pr_warn("aacraid: SCSI CMD Data Overrun\n");
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003329 scsicmd->result = DID_ERROR << 16
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003330 | COMMAND_COMPLETE << 8;
3331 break;
3332 case INQUIRY:
3333 scsicmd->result = DID_OK << 16
3334 | COMMAND_COMPLETE << 8;
3335 break;
3336 default:
Mark Haverkampbb08f922006-02-01 09:30:44 -08003337 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 break;
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003339 }
3340 break;
3341 case SRB_STATUS_ABORTED:
3342 scsicmd->result = DID_ABORT << 16 | ABORT << 8;
3343 break;
3344 case SRB_STATUS_ABORT_FAILED:
3345 /*
3346 * Not sure about this one - but assuming the
3347 * hba was trying to abort for some reason
3348 */
3349 scsicmd->result = DID_ERROR << 16 | ABORT << 8;
3350 break;
3351 case SRB_STATUS_PARITY_ERROR:
3352 scsicmd->result = DID_PARITY << 16
3353 | MSG_PARITY_ERROR << 8;
3354 break;
3355 case SRB_STATUS_NO_DEVICE:
3356 case SRB_STATUS_INVALID_PATH_ID:
3357 case SRB_STATUS_INVALID_TARGET_ID:
3358 case SRB_STATUS_INVALID_LUN:
3359 case SRB_STATUS_SELECTION_TIMEOUT:
3360 scsicmd->result = DID_NO_CONNECT << 16
3361 | COMMAND_COMPLETE << 8;
3362 break;
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003363
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003364 case SRB_STATUS_COMMAND_TIMEOUT:
3365 case SRB_STATUS_TIMEOUT:
3366 scsicmd->result = DID_TIME_OUT << 16
3367 | COMMAND_COMPLETE << 8;
3368 break;
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003369
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003370 case SRB_STATUS_BUSY:
3371 scsicmd->result = DID_BUS_BUSY << 16
3372 | COMMAND_COMPLETE << 8;
3373 break;
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003374
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003375 case SRB_STATUS_BUS_RESET:
3376 scsicmd->result = DID_RESET << 16
3377 | COMMAND_COMPLETE << 8;
3378 break;
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003379
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003380 case SRB_STATUS_MESSAGE_REJECTED:
3381 scsicmd->result = DID_ERROR << 16
3382 | MESSAGE_REJECT << 8;
3383 break;
3384 case SRB_STATUS_REQUEST_FLUSHED:
3385 case SRB_STATUS_ERROR:
3386 case SRB_STATUS_INVALID_REQUEST:
3387 case SRB_STATUS_REQUEST_SENSE_FAILED:
3388 case SRB_STATUS_NO_HBA:
3389 case SRB_STATUS_UNEXPECTED_BUS_FREE:
3390 case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
3391 case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
3392 case SRB_STATUS_DELAYED_RETRY:
3393 case SRB_STATUS_BAD_FUNCTION:
3394 case SRB_STATUS_NOT_STARTED:
3395 case SRB_STATUS_NOT_IN_USE:
3396 case SRB_STATUS_FORCE_ABORT:
3397 case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
3398 default:
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003399#ifdef AAC_DETAILED_STATUS_INFO
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003400 pr_info("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x -scsi status 0x%x\n",
3401 le32_to_cpu(srbreply->srb_status) & 0x3F,
3402 aac_get_status_string(
3403 le32_to_cpu(srbreply->srb_status) & 0x3F),
3404 scsicmd->cmnd[0],
3405 le32_to_cpu(srbreply->scsi_status));
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003406#endif
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003407 /*
3408 * When the CC bit is SET by the host in ATA pass thru CDB,
3409 * driver is supposed to return DID_OK
3410 *
3411 * When the CC bit is RESET by the host, driver should
3412 * return DID_ERROR
3413 */
3414 if ((scsicmd->cmnd[0] == ATA_12)
3415 || (scsicmd->cmnd[0] == ATA_16)) {
3416
3417 if (scsicmd->cmnd[2] & (0x01 << 5)) {
3418 scsicmd->result = DID_OK << 16
3419 | COMMAND_COMPLETE << 8;
3420 break;
Rajashekhara, Mahesh1fc80102010-05-10 04:17:57 -07003421 } else {
3422 scsicmd->result = DID_ERROR << 16
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003423 | COMMAND_COMPLETE << 8;
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003424 break;
Rajashekhara, Mahesh1fc80102010-05-10 04:17:57 -07003425 }
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003426 } else {
3427 scsicmd->result = DID_ERROR << 16
3428 | COMMAND_COMPLETE << 8;
3429 break;
Mahesh Rajashekhara55b87602015-08-28 06:38:37 -04003430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 }
Raghava Aditya Renukunta4ec57fb2017-02-02 15:53:21 -08003432 if (le32_to_cpu(srbreply->scsi_status)
3433 == SAM_STAT_CHECK_CONDITION) {
3434 int len;
3435
3436 scsicmd->result |= SAM_STAT_CHECK_CONDITION;
3437 len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
3438 SCSI_SENSE_BUFFERSIZE);
3439#ifdef AAC_DETAILED_STATUS_INFO
3440 pr_warn("aac_srb_callback: check condition, status = %d len=%d\n",
3441 le32_to_cpu(srbreply->status), len);
3442#endif
3443 memcpy(scsicmd->sense_buffer,
3444 srbreply->sense_data, len);
3445 }
3446
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 /*
3448 * OR in the scsi status (already shifted up a bit)
3449 */
3450 scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
3451
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08003452 aac_fib_complete(fibptr);
Mark Haverkamp8e0c5eb2005-10-24 10:52:22 -07003453 scsicmd->scsi_done(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454}
3455
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08003456static void hba_resp_task_complete(struct aac_dev *dev,
3457 struct scsi_cmnd *scsicmd,
3458 struct aac_hba_resp *err) {
3459
3460 scsicmd->result = err->status;
3461 /* set residual count */
3462 scsi_set_resid(scsicmd, le32_to_cpu(err->residual_count));
3463
3464 switch (err->status) {
3465 case SAM_STAT_GOOD:
3466 scsicmd->result |= DID_OK << 16 | COMMAND_COMPLETE << 8;
3467 break;
3468 case SAM_STAT_CHECK_CONDITION:
3469 {
3470 int len;
3471
3472 len = min_t(u8, err->sense_response_data_len,
3473 SCSI_SENSE_BUFFERSIZE);
3474 if (len)
3475 memcpy(scsicmd->sense_buffer,
3476 err->sense_response_buf, len);
3477 scsicmd->result |= DID_OK << 16 | COMMAND_COMPLETE << 8;
3478 break;
3479 }
3480 case SAM_STAT_BUSY:
3481 scsicmd->result |= DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
3482 break;
3483 case SAM_STAT_TASK_ABORTED:
3484 scsicmd->result |= DID_ABORT << 16 | ABORT << 8;
3485 break;
3486 case SAM_STAT_RESERVATION_CONFLICT:
3487 case SAM_STAT_TASK_SET_FULL:
3488 default:
3489 scsicmd->result |= DID_ERROR << 16 | COMMAND_COMPLETE << 8;
3490 break;
3491 }
3492}
3493
3494static void hba_resp_task_failure(struct aac_dev *dev,
3495 struct scsi_cmnd *scsicmd,
3496 struct aac_hba_resp *err)
3497{
3498 switch (err->status) {
3499 case HBA_RESP_STAT_HBAMODE_DISABLED:
3500 {
3501 u32 bus, cid;
3502
3503 bus = aac_logical_to_phys(scmd_channel(scsicmd));
3504 cid = scmd_id(scsicmd);
3505 if (dev->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) {
3506 dev->hba_map[bus][cid].devtype = AAC_DEVTYPE_ARC_RAW;
3507 dev->hba_map[bus][cid].rmw_nexus = 0xffffffff;
3508 }
3509 scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
3510 break;
3511 }
3512 case HBA_RESP_STAT_IO_ERROR:
3513 case HBA_RESP_STAT_NO_PATH_TO_DEVICE:
3514 scsicmd->result = DID_OK << 16 |
3515 COMMAND_COMPLETE << 8 | SAM_STAT_BUSY;
3516 break;
3517 case HBA_RESP_STAT_IO_ABORTED:
3518 scsicmd->result = DID_ABORT << 16 | ABORT << 8;
3519 break;
3520 case HBA_RESP_STAT_INVALID_DEVICE:
3521 scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
3522 break;
3523 case HBA_RESP_STAT_UNDERRUN:
3524 /* UNDERRUN is OK */
3525 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
3526 break;
3527 case HBA_RESP_STAT_OVERRUN:
3528 default:
3529 scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
3530 break;
3531 }
3532}
3533
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534/**
3535 *
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08003536 * aac_hba_callback
3537 * @context: the context set in the fib - here it is scsi cmd
3538 * @fibptr: pointer to the fib
3539 *
3540 * Handles the completion of a native HBA scsi command
3541 *
3542 */
3543void aac_hba_callback(void *context, struct fib *fibptr)
3544{
3545 struct aac_dev *dev;
3546 struct scsi_cmnd *scsicmd;
3547
3548 struct aac_hba_resp *err =
3549 &((struct aac_native_hba *)fibptr->hw_fib_va)->resp.err;
3550
3551 scsicmd = (struct scsi_cmnd *) context;
3552
3553 if (!aac_valid_context(scsicmd, fibptr))
3554 return;
3555
3556 WARN_ON(fibptr == NULL);
3557 dev = fibptr->dev;
3558
3559 if (!(fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF))
3560 scsi_dma_unmap(scsicmd);
3561
3562 if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) {
3563 /* fast response */
3564 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
3565 goto out;
3566 }
3567
3568 switch (err->service_response) {
3569 case HBA_RESP_SVCRES_TASK_COMPLETE:
3570 hba_resp_task_complete(dev, scsicmd, err);
3571 break;
3572 case HBA_RESP_SVCRES_FAILURE:
3573 hba_resp_task_failure(dev, scsicmd, err);
3574 break;
3575 case HBA_RESP_SVCRES_TMF_REJECTED:
3576 scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8;
3577 break;
3578 case HBA_RESP_SVCRES_TMF_LUN_INVALID:
3579 scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
3580 break;
3581 case HBA_RESP_SVCRES_TMF_COMPLETE:
3582 case HBA_RESP_SVCRES_TMF_SUCCEEDED:
3583 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
3584 break;
3585 default:
3586 scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
3587 break;
3588 }
3589
3590out:
3591 aac_fib_complete(fibptr);
3592
3593 if (fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF)
3594 scsicmd->SCp.sent_command = 1;
3595 else
3596 scsicmd->scsi_done(scsicmd);
3597}
3598
3599/**
3600 *
3601 * aac_send_srb_fib
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602 * @scsicmd: the scsi command block
3603 *
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08003604 * This routine will form a FIB and fill in the aac_srb from the
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 * scsicmd passed in.
3606 */
3607
3608static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
3609{
3610 struct fib* cmd_fibcontext;
3611 struct aac_dev* dev;
3612 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613
Mark Haverkamp84971732005-06-20 11:55:24 -07003614 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
Mark Haverkampe5718772006-03-27 09:43:25 -08003615 if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
Mark Haverkamp84971732005-06-20 11:55:24 -07003616 scsicmd->device->lun > 7) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 scsicmd->result = DID_NO_CONNECT << 16;
3618 scsicmd->scsi_done(scsicmd);
3619 return 0;
3620 }
3621
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 /*
3623 * Allocate and initialize a Fib then setup a BlockWrite command
3624 */
Raghava Aditya Renukunta6bf3b632016-02-03 15:05:59 -08003625 cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
Raghava Aditya Renukunta6bf3b632016-02-03 15:05:59 -08003626
Mark Haverkampe8f32de2007-01-23 15:00:30 -08003627 status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 /*
3630 * Check that the command queued to the controller
3631 */
Mark Haverkamp77d644d2006-03-27 09:43:40 -08003632 if (status == -EINPROGRESS) {
3633 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 return 0;
3635 }
3636
Mark Haverkampbfb35aa82006-02-01 09:30:55 -08003637 printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
3638 aac_fib_complete(cmd_fibcontext);
3639 aac_fib_free(cmd_fibcontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640
3641 return -1;
3642}
3643
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08003644/**
3645 *
3646 * aac_send_hba_fib
3647 * @scsicmd: the scsi command block
3648 *
3649 * This routine will form a FIB and fill in the aac_hba_cmd_req from the
3650 * scsicmd passed in.
3651 */
3652static int aac_send_hba_fib(struct scsi_cmnd *scsicmd)
3653{
3654 struct fib *cmd_fibcontext;
3655 struct aac_dev *dev;
3656 int status;
3657
3658 dev = shost_priv(scsicmd->device->host);
3659 if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
3660 scsicmd->device->lun > AAC_MAX_LUN - 1) {
3661 scsicmd->result = DID_NO_CONNECT << 16;
3662 scsicmd->scsi_done(scsicmd);
3663 return 0;
3664 }
3665
3666 /*
3667 * Allocate and initialize a Fib then setup a BlockWrite command
3668 */
3669 cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
3670 if (!cmd_fibcontext)
3671 return -1;
3672
3673 status = aac_adapter_hba(cmd_fibcontext, scsicmd);
3674
3675 /*
3676 * Check that the command queued to the controller
3677 */
3678 if (status == -EINPROGRESS) {
3679 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
3680 return 0;
3681 }
3682
3683 pr_warn("aac_hba_cmd_req: aac_fib_send failed with status: %d\n",
3684 status);
3685 aac_fib_complete(cmd_fibcontext);
3686 aac_fib_free(cmd_fibcontext);
3687
3688 return -1;
3689}
3690
3691
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05303692static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *psg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693{
3694 struct aac_dev *dev;
3695 unsigned long byte_count = 0;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003696 int nseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697
3698 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
3699 // Get rid of old data
3700 psg->count = 0;
3701 psg->sg[0].addr = 0;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003702 psg->sg[0].count = 0;
3703
3704 nseg = scsi_dma_map(scsicmd);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05303705 if (nseg < 0)
3706 return nseg;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003707 if (nseg) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 struct scatterlist *sg;
3709 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003711 psg->count = cpu_to_le32(nseg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003713 scsi_for_each_sg(scsicmd, sg, nseg, i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
3715 psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
3716 byte_count += sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717 }
3718 /* hba wants the size to be exact */
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003719 if (byte_count > scsi_bufflen(scsicmd)) {
3720 u32 temp = le32_to_cpu(psg->sg[i-1].count) -
3721 (byte_count - scsi_bufflen(scsicmd));
Mark Haverkamp 56b58712005-04-27 06:05:51 -07003722 psg->sg[i-1].count = cpu_to_le32(temp);
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003723 byte_count = scsi_bufflen(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 }
3725 /* Check for command underflow */
3726 if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
3727 printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
3728 byte_count, scsicmd->underflow);
3729 }
3730 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 return byte_count;
3732}
3733
3734
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05303735static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736{
3737 struct aac_dev *dev;
3738 unsigned long byte_count = 0;
Mark Haverkamp 56b58712005-04-27 06:05:51 -07003739 u64 addr;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003740 int nseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741
3742 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
3743 // Get rid of old data
3744 psg->count = 0;
3745 psg->sg[0].addr[0] = 0;
3746 psg->sg[0].addr[1] = 0;
3747 psg->sg[0].count = 0;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003748
3749 nseg = scsi_dma_map(scsicmd);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05303750 if (nseg < 0)
3751 return nseg;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003752 if (nseg) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 struct scatterlist *sg;
3754 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003756 scsi_for_each_sg(scsicmd, sg, nseg, i) {
Mark Haverkamp1241f352006-03-27 09:44:23 -08003757 int count = sg_dma_len(sg);
Mark Haverkamp 56b58712005-04-27 06:05:51 -07003758 addr = sg_dma_address(sg);
3759 psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
3760 psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
Mark Haverkamp1241f352006-03-27 09:44:23 -08003761 psg->sg[i].count = cpu_to_le32(count);
3762 byte_count += count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 }
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003764 psg->count = cpu_to_le32(nseg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 /* hba wants the size to be exact */
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003766 if (byte_count > scsi_bufflen(scsicmd)) {
3767 u32 temp = le32_to_cpu(psg->sg[i-1].count) -
3768 (byte_count - scsi_bufflen(scsicmd));
Mark Haverkamp 56b58712005-04-27 06:05:51 -07003769 psg->sg[i-1].count = cpu_to_le32(temp);
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003770 byte_count = scsi_bufflen(scsicmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 }
3772 /* Check for command underflow */
3773 if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
3774 printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
3775 byte_count, scsicmd->underflow);
3776 }
3777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 return byte_count;
3779}
3780
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05303781static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg)
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003782{
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003783 unsigned long byte_count = 0;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003784 int nseg;
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003785
3786 // Get rid of old data
3787 psg->count = 0;
3788 psg->sg[0].next = 0;
3789 psg->sg[0].prev = 0;
3790 psg->sg[0].addr[0] = 0;
3791 psg->sg[0].addr[1] = 0;
3792 psg->sg[0].count = 0;
3793 psg->sg[0].flags = 0;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003794
3795 nseg = scsi_dma_map(scsicmd);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05303796 if (nseg < 0)
3797 return nseg;
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003798 if (nseg) {
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003799 struct scatterlist *sg;
3800 int i;
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003801
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003802 scsi_for_each_sg(scsicmd, sg, nseg, i) {
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003803 int count = sg_dma_len(sg);
3804 u64 addr = sg_dma_address(sg);
3805 psg->sg[i].next = 0;
3806 psg->sg[i].prev = 0;
3807 psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
3808 psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
3809 psg->sg[i].count = cpu_to_le32(count);
3810 psg->sg[i].flags = 0;
3811 byte_count += count;
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003812 }
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003813 psg->count = cpu_to_le32(nseg);
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003814 /* hba wants the size to be exact */
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003815 if (byte_count > scsi_bufflen(scsicmd)) {
3816 u32 temp = le32_to_cpu(psg->sg[i-1].count) -
3817 (byte_count - scsi_bufflen(scsicmd));
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003818 psg->sg[i-1].count = cpu_to_le32(temp);
FUJITA Tomonori727eead2007-05-26 02:00:42 +09003819 byte_count = scsi_bufflen(scsicmd);
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003820 }
3821 /* Check for command underflow */
3822 if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
3823 printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
3824 byte_count, scsicmd->underflow);
3825 }
3826 }
Mark Haverkamp0e68c002005-08-03 15:39:49 -07003827 return byte_count;
3828}
3829
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05303830static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
3831 struct aac_raw_io2 *rio2, int sg_max)
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05303832{
3833 unsigned long byte_count = 0;
3834 int nseg;
3835
3836 nseg = scsi_dma_map(scsicmd);
Mahesh Rajashekhara0b433442012-10-19 19:21:07 +05303837 if (nseg < 0)
3838 return nseg;
Mahesh Rajashekhara85d22bb2012-07-14 18:18:51 +05303839 if (nseg) {
3840 struct scatterlist *sg;
3841 int i, conformable = 0;
3842 u32 min_size = PAGE_SIZE, cur_size;
3843
3844 scsi_for_each_sg(scsicmd, sg, nseg, i) {
3845 int count = sg_dma_len(sg);
3846 u64 addr = sg_dma_address(sg);
3847
3848 BUG_ON(i >= sg_max);
3849 rio2->sge[i].addrHigh = cpu_to_le32((u32)(addr>>32));
3850 rio2->sge[i].addrLow = cpu_to_le32((u32)(addr & 0xffffffff));
3851 cur_size = cpu_to_le32(count);
3852 rio2->sge[i].length = cur_size;
3853 rio2->sge[i].flags = 0;
3854 if (i == 0) {
3855 conformable = 1;
3856 rio2->sgeFirstSize = cur_size;
3857 } else if (i == 1) {
3858 rio2->sgeNominalSize = cur_size;
3859 min_size = cur_size;
3860 } else if ((i+1) < nseg && cur_size != rio2->sgeNominalSize) {
3861 conformable = 0;
3862 if (cur_size < min_size)
3863 min_size = cur_size;
3864 }
3865 byte_count += count;
3866 }
3867
3868 /* hba wants the size to be exact */
3869 if (byte_count > scsi_bufflen(scsicmd)) {
3870 u32 temp = le32_to_cpu(rio2->sge[i-1].length) -
3871 (byte_count - scsi_bufflen(scsicmd));
3872 rio2->sge[i-1].length = cpu_to_le32(temp);
3873 byte_count = scsi_bufflen(scsicmd);
3874 }
3875
3876 rio2->sgeCnt = cpu_to_le32(nseg);
3877 rio2->flags |= cpu_to_le16(RIO2_SG_FORMAT_IEEE1212);
3878 /* not conformable: evaluate required sg elements */
3879 if (!conformable) {
3880 int j, nseg_new = nseg, err_found;
3881 for (i = min_size / PAGE_SIZE; i >= 1; --i) {
3882 err_found = 0;
3883 nseg_new = 2;
3884 for (j = 1; j < nseg - 1; ++j) {
3885 if (rio2->sge[j].length % (i*PAGE_SIZE)) {
3886 err_found = 1;
3887 break;
3888 }
3889 nseg_new += (rio2->sge[j].length / (i*PAGE_SIZE));
3890 }
3891 if (!err_found)
3892 break;
3893 }
3894 if (i > 0 && nseg_new <= sg_max)
3895 aac_convert_sgraw2(rio2, i, nseg, nseg_new);
3896 } else
3897 rio2->flags |= cpu_to_le16(RIO2_SGL_CONFORMANT);
3898
3899 /* Check for command underflow */
3900 if (scsicmd->underflow && (byte_count < scsicmd->underflow)) {
3901 printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
3902 byte_count, scsicmd->underflow);
3903 }
3904 }
3905
3906 return byte_count;
3907}
3908
3909static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int nseg_new)
3910{
3911 struct sge_ieee1212 *sge;
3912 int i, j, pos;
3913 u32 addr_low;
3914
3915 if (aac_convert_sgl == 0)
3916 return 0;
3917
3918 sge = kmalloc(nseg_new * sizeof(struct sge_ieee1212), GFP_ATOMIC);
3919 if (sge == NULL)
3920 return -1;
3921
3922 for (i = 1, pos = 1; i < nseg-1; ++i) {
3923 for (j = 0; j < rio2->sge[i].length / (pages * PAGE_SIZE); ++j) {
3924 addr_low = rio2->sge[i].addrLow + j * pages * PAGE_SIZE;
3925 sge[pos].addrLow = addr_low;
3926 sge[pos].addrHigh = rio2->sge[i].addrHigh;
3927 if (addr_low < rio2->sge[i].addrLow)
3928 sge[pos].addrHigh++;
3929 sge[pos].length = pages * PAGE_SIZE;
3930 sge[pos].flags = 0;
3931 pos++;
3932 }
3933 }
3934 sge[pos] = rio2->sge[nseg-1];
3935 memcpy(&rio2->sge[1], &sge[1], (nseg_new-1)*sizeof(struct sge_ieee1212));
3936
3937 kfree(sge);
3938 rio2->sgeCnt = cpu_to_le32(nseg_new);
3939 rio2->flags |= cpu_to_le16(RIO2_SGL_CONFORMANT);
3940 rio2->sgeNominalSize = pages * PAGE_SIZE;
3941 return 0;
3942}
3943
Raghava Aditya Renukuntaab5d1292017-02-02 15:53:30 -08003944static long aac_build_sghba(struct scsi_cmnd *scsicmd,
3945 struct aac_hba_cmd_req *hbacmd,
3946 int sg_max,
3947 u64 sg_address)
3948{
3949 unsigned long byte_count = 0;
3950 int nseg;
3951 struct scatterlist *sg;
3952 int i;
3953 u32 cur_size;
3954 struct aac_hba_sgl *sge;
3955
3956
3957
3958 nseg = scsi_dma_map(scsicmd);
3959 if (nseg <= 0) {
3960 byte_count = nseg;
3961 goto out;
3962 }
3963
3964 if (nseg > HBA_MAX_SG_EMBEDDED)
3965 sge = &hbacmd->sge[2];
3966 else
3967 sge = &hbacmd->sge[0];
3968
3969 scsi_for_each_sg(scsicmd, sg, nseg, i) {
3970 int count = sg_dma_len(sg);
3971 u64 addr = sg_dma_address(sg);
3972
3973 WARN_ON(i >= sg_max);
3974 sge->addr_hi = cpu_to_le32((u32)(addr>>32));
3975 sge->addr_lo = cpu_to_le32((u32)(addr & 0xffffffff));
3976 cur_size = cpu_to_le32(count);
3977 sge->len = cur_size;
3978 sge->flags = 0;
3979 byte_count += count;
3980 sge++;
3981 }
3982
3983 sge--;
3984 /* hba wants the size to be exact */
3985 if (byte_count > scsi_bufflen(scsicmd)) {
3986 u32 temp;
3987
3988 temp = le32_to_cpu(sge->len) - byte_count
3989 - scsi_bufflen(scsicmd);
3990 sge->len = cpu_to_le32(temp);
3991 byte_count = scsi_bufflen(scsicmd);
3992 }
3993
3994 if (nseg <= HBA_MAX_SG_EMBEDDED) {
3995 hbacmd->emb_data_desc_count = cpu_to_le32(nseg);
3996 sge->flags = cpu_to_le32(0x40000000);
3997 } else {
3998 /* not embedded */
3999 hbacmd->sge[0].flags = cpu_to_le32(0x80000000);
4000 hbacmd->emb_data_desc_count = (u8)cpu_to_le32(1);
4001 hbacmd->sge[0].addr_hi = (u32)cpu_to_le32(sg_address >> 32);
4002 hbacmd->sge[0].addr_lo =
4003 cpu_to_le32((u32)(sg_address & 0xffffffff));
4004 }
4005
4006 /* Check for command underflow */
4007 if (scsicmd->underflow && (byte_count < scsicmd->underflow)) {
4008 pr_warn("aacraid: cmd len %08lX cmd underflow %08X\n",
4009 byte_count, scsicmd->underflow);
4010 }
4011out:
4012 return byte_count;
4013}
4014
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015#ifdef AAC_DETAILED_STATUS_INFO
4016
4017struct aac_srb_status_info {
4018 u32 status;
4019 char *str;
4020};
4021
4022
4023static struct aac_srb_status_info srb_status_info[] = {
4024 { SRB_STATUS_PENDING, "Pending Status"},
4025 { SRB_STATUS_SUCCESS, "Success"},
4026 { SRB_STATUS_ABORTED, "Aborted Command"},
4027 { SRB_STATUS_ABORT_FAILED, "Abort Failed"},
Tobias Klauser6391a112006-06-08 22:23:48 -07004028 { SRB_STATUS_ERROR, "Error Event"},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 { SRB_STATUS_BUSY, "Device Busy"},
4030 { SRB_STATUS_INVALID_REQUEST, "Invalid Request"},
4031 { SRB_STATUS_INVALID_PATH_ID, "Invalid Path ID"},
4032 { SRB_STATUS_NO_DEVICE, "No Device"},
4033 { SRB_STATUS_TIMEOUT, "Timeout"},
4034 { SRB_STATUS_SELECTION_TIMEOUT, "Selection Timeout"},
4035 { SRB_STATUS_COMMAND_TIMEOUT, "Command Timeout"},
4036 { SRB_STATUS_MESSAGE_REJECTED, "Message Rejected"},
4037 { SRB_STATUS_BUS_RESET, "Bus Reset"},
4038 { SRB_STATUS_PARITY_ERROR, "Parity Error"},
4039 { SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"},
4040 { SRB_STATUS_NO_HBA, "No HBA"},
4041 { SRB_STATUS_DATA_OVERRUN, "Data Overrun/Data Underrun"},
4042 { SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"},
4043 { SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"},
4044 { SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"},
4045 { SRB_STATUS_REQUEST_FLUSHED, "Request Flushed"},
4046 { SRB_STATUS_DELAYED_RETRY, "Delayed Retry"},
Tobias Klauser6391a112006-06-08 22:23:48 -07004047 { SRB_STATUS_INVALID_LUN, "Invalid LUN"},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048 { SRB_STATUS_INVALID_TARGET_ID, "Invalid TARGET ID"},
4049 { SRB_STATUS_BAD_FUNCTION, "Bad Function"},
4050 { SRB_STATUS_ERROR_RECOVERY, "Error Recovery"},
4051 { SRB_STATUS_NOT_STARTED, "Not Started"},
4052 { SRB_STATUS_NOT_IN_USE, "Not In Use"},
Salyzyn, Mark8ce3eca2008-01-16 07:39:06 -08004053 { SRB_STATUS_FORCE_ABORT, "Force Abort"},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 { SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"},
4055 { 0xff, "Unknown Error"}
4056};
4057
4058char *aac_get_status_string(u32 status)
4059{
4060 int i;
4061
Tobias Klauser6391a112006-06-08 22:23:48 -07004062 for (i = 0; i < ARRAY_SIZE(srb_status_info); i++)
4063 if (srb_status_info[i].status == status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 return srb_status_info[i].str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
4066 return "Bad Status Code";
4067}
4068
4069#endif