1 /*
2 * linux/drivers/message/fusion/mptscsih.c
3 * High performance SCSI / Fibre Channel SCSI Host device driver.
4 * For use with PCI chip/adapter(s):
5 * LSIFC9xx/LSI409xx Fibre Channel
6 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
7 *
8 * Credits:
9 * This driver would not exist if not for Alan Cox's development
10 * of the linux i2o driver.
11 *
12 * A special thanks to Pamela Delaney (LSI Logic) for tons of work
13 * and countless enhancements while adding support for the 1030
14 * chip family. Pam has been instrumental in the development of
15 * of the 2.xx.xx series fusion drivers, and her contributions are
16 * far too numerous to hope to list in one place.
17 *
18 * A huge debt of gratitude is owed to David S. Miller (DaveM)
19 * for fixing much of the stupid and broken stuff in the early
20 * driver while porting to sparc64 platform. THANK YOU!
21 *
22 * (see mptbase.c)
23 *
24 * Copyright (c) 1999-2004 LSI Logic Corporation
25 * Original author: Steven J. Ralston
26 * (mailto:sjralston1@netscape.net)
27 * (mailto:mpt_linux_developer@lsil.com)
28 *
29 * $Id: mptscsih.c,v 1.1.2.4 2003/05/07 14:08:34 pdelaney Exp $
30 */
31 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
32 /*
33 This program is free software; you can redistribute it and/or modify
34 it under the terms of the GNU General Public License as published by
35 the Free Software Foundation; version 2 of the License.
36
37 This program is distributed in the hope that it will be useful,
38 but WITHOUT ANY WARRANTY; without even the implied warranty of
39 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 GNU General Public License for more details.
41
42 NO WARRANTY
43 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
44 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
45 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
46 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
47 solely responsible for determining the appropriateness of using and
48 distributing the Program and assumes all risks associated with its
49 exercise of rights under this Agreement, including but not limited to
50 the risks and costs of program errors, damage to or loss of data,
51 programs or equipment, and unavailability or interruption of operations.
52
53 DISCLAIMER OF LIABILITY
54 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
55 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
57 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
58 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
59 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
60 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
61
62 You should have received a copy of the GNU General Public License
63 along with this program; if not, write to the Free Software
64 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
65 */
66 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
67
68 #include <linux/module.h>
69 #include <linux/version.h>
70 #include <linux/kernel.h>
71 #include <linux/init.h>
72 #include <linux/errno.h>
73 #include <linux/kdev_t.h>
74 #include <linux/blkdev.h>
75 #include <linux/blk.h> /* for io_request_lock (spinlock) decl */
76 #include <linux/delay.h> /* for mdelay */
77 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
78 #include <linux/reboot.h> /* notifier code */
79 #include "../../scsi/scsi.h"
80 #include "../../scsi/hosts.h"
81 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45)
82 #include "../../scsi/sd.h"
83 #endif
84
85 #include "mptbase.h"
86 #include "mptscsih.h"
87 #include "isense.h"
88
89 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
90 #define my_NAME "Fusion MPT SCSI Host driver"
91 #define my_VERSION MPT_LINUX_VERSION_COMMON
92 #define MYNAM "mptscsih"
93
94 MODULE_AUTHOR(MODULEAUTHOR);
95 MODULE_DESCRIPTION(my_NAME);
96 MODULE_LICENSE("GPL");
97
98 /* Set string for command line args from insmod */
99 #ifdef MODULE
100 char *mptscsih = 0;
101 MODULE_PARM(mptscsih, "s");
102 #endif
103
104 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
105
106 typedef struct _BIG_SENSE_BUF {
107 u8 data[MPT_SENSE_BUFFER_ALLOC];
108 } BIG_SENSE_BUF;
109
110 #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
111 #define MPT_SCANDV_DID_RESET (0x00000001)
112 #define MPT_SCANDV_SENSE (0x00000002)
113 #define MPT_SCANDV_SOME_ERROR (0x00000004)
114 #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
115 #define MPT_SCANDV_ISSUE_SENSE (0x00000010)
116
117 #define MPT_SCANDV_MAX_RETRIES (10)
118
119 #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
120 #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
121 #define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */
122 #define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */
123 #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occured with this command */
124 #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
125
126 typedef struct _internal_cmd {
127 char *data; /* data pointer */
128 dma_addr_t data_dma; /* data dma address */
129 int size; /* transfer size */
130 u8 cmd; /* SCSI Op Code */
131 u8 bus; /* bus number */
132 u8 id; /* SCSI ID (virtual) */
133 u8 lun;
134 u8 flags; /* Bit Field - See above */
135 u8 physDiskNum; /* Phys disk number, -1 else */
136 u8 rsvd2;
137 u8 rsvd;
138 } INTERNAL_CMD;
139
140 typedef struct _negoparms {
141 u8 width;
142 u8 offset;
143 u8 factor;
144 u8 flags;
145 } NEGOPARMS;
146
147 typedef struct _dv_parameters {
148 NEGOPARMS max;
149 NEGOPARMS now;
150 u8 cmd;
151 u8 id;
152 u16 pad1;
153 } DVPARAMETERS;
154
155
156 /*
157 * Other private/forward protos...
158 */
159 static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
160 static void mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
161 static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
162
163 static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
164 SCSIIORequest_t *pReq, int req_idx);
165 static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
166 static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
167 static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
168 #ifndef MPT_SCSI_USE_NEW_EH
169 static void search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd);
170 #else
171 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
172 #endif
173 static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
174 static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
175 static void post_pendingQ_commands(MPT_SCSI_HOST *hd);
176
177 static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag);
178 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag);
179
180 static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
181 static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
182
183 static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
184 void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
185 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
186 static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
187 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
188 static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
189 static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
190 static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
191 static void mptscsih_timer_expired(unsigned long data);
192 static void mptscsih_taskmgmt_timeout(unsigned long data);
193 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
194 static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
195
196 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
197 static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
198 static void mptscsih_domainValidation(void *hd);
199 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
200 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
201 static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
202 static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
203 static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
204 #endif
205 static int mptscsih_setup(char *str);
206 static int mptscsih_halt(struct notifier_block *nb, ulong event, void *buf);
207
208 /*
209 * Reboot Notification
210 */
211 static struct notifier_block mptscsih_notifier = {
212 mptscsih_halt, NULL, 0
213 };
214
215 /*
216 * Private data...
217 */
218
219 static int mpt_scsi_hosts = 0;
220
221 static int ScsiDoneCtx = -1;
222 static int ScsiTaskCtx = -1;
223 static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
224
225 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,28)
226 static struct proc_dir_entry proc_mpt_scsihost =
227 {
228 .low_ino = PROC_SCSI_MPT,
229 .namelen = 8,
230 .name = "mptscsih",
231 .mode = S_IFDIR | S_IRUGO | S_IXUGO,
232 .nlink = 2,
233 };
234 #endif
235
236 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
237
238 #ifndef MPT_SCSI_USE_NEW_EH
239 /*
240 * Stuff to handle single-threading SCSI TaskMgmt
241 * (abort/reset) requests...
242 */
243 static spinlock_t mytaskQ_lock = SPIN_LOCK_UNLOCKED;
244 static int mytaskQ_bh_active = 0;
245 static struct mpt_work_struct mptscsih_ptaskfoo;
246 static atomic_t mpt_taskQdepth;
247 #endif
248
249 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
250 /*
251 * Domain Validation task structure
252 */
253 static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
254 static int dvtaskQ_active = 0;
255 static int dvtaskQ_release = 0;
256 static struct mpt_work_struct mptscsih_dvTask;
257 #endif
258
259 /*
260 * Wait Queue setup
261 */
262 static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
263 static int scandv_wait_done = 1;
264
265 /* Driver default setup
266 */
267 static struct mptscsih_driver_setup
268 driver_setup = MPTSCSIH_DRIVER_SETUP;
269
270 #ifdef MPTSCSIH_DBG_TIMEOUT
271 static Scsi_Cmnd *foo_to[8];
272 #endif
273
274 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
275 /*
276 * Private inline routines...
277 */
278 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
279 /* 19991030 -sralston
280 * Return absolute SCSI data direction:
281 * 1 = _DATA_OUT
282 * 0 = _DIR_NONE
283 * -1 = _DATA_IN
284 *
285 * Changed: 3-20-2002 pdelaney to use the default data
286 * direction and the defines set up in the
287 * 2.4 kernel series
288 * 1 = _DATA_OUT changed to SCSI_DATA_WRITE (1)
289 * 0 = _DIR_NONE changed to SCSI_DATA_NONE (3)
290 * -1 = _DATA_IN changed to SCSI_DATA_READ (2)
291 * If the direction is unknown, fall through to original code.
292 *
293 * Mid-layer bug fix(): sg interface generates the wrong data
294 * direction in some cases. Set the direction the hard way for
295 * the most common commands.
296 */
297 static inline int
mptscsih_io_direction(Scsi_Cmnd * cmd)298 mptscsih_io_direction(Scsi_Cmnd *cmd)
299 {
300 switch (cmd->cmnd[0]) {
301 case WRITE_6:
302 case WRITE_10:
303 return SCSI_DATA_WRITE;
304 break;
305 case READ_6:
306 case READ_10:
307 return SCSI_DATA_READ;
308 break;
309 }
310
311 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
312 if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
313 return cmd->sc_data_direction;
314 #endif
315 switch (cmd->cmnd[0]) {
316 /* _DATA_OUT commands */
317 case WRITE_6: case WRITE_10: case WRITE_12:
318 case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
319 case WRITE_VERIFY: case WRITE_VERIFY_12:
320 case COMPARE: case COPY: case COPY_VERIFY:
321 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
322 case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
323 case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
324 case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
325 case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
326 case REASSIGN_BLOCKS:
327 case PERSISTENT_RESERVE_OUT:
328 case 0xea:
329 case 0xa3:
330 return SCSI_DATA_WRITE;
331
332 /* No data transfer commands */
333 case SEEK_6: case SEEK_10:
334 case RESERVE: case RELEASE:
335 case TEST_UNIT_READY:
336 case START_STOP:
337 case ALLOW_MEDIUM_REMOVAL:
338 return SCSI_DATA_NONE;
339
340 /* Conditional data transfer commands */
341 case FORMAT_UNIT:
342 if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */
343 return SCSI_DATA_WRITE;
344 else
345 return SCSI_DATA_NONE;
346
347 case VERIFY:
348 if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */
349 return SCSI_DATA_WRITE;
350 else
351 return SCSI_DATA_NONE;
352
353 case RESERVE_10:
354 if (cmd->cmnd[1] & 0x03) /* RESERVE:{LongID|Extent} (data out phase)? */
355 return SCSI_DATA_WRITE;
356 else
357 return SCSI_DATA_NONE;
358
359 /* Must be data _IN! */
360 default:
361 return SCSI_DATA_READ;
362 }
363 } /* mptscsih_io_direction() */
364
365 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
366 /**
367 * mptscsih_add_sge - Place a simple SGE at address pAddr.
368 * @pAddr: virtual address for SGE
369 * @flagslength: SGE flags and data transfer length
370 * @dma_addr: Physical address
371 *
372 * This routine places a MPT request frame back on the MPT adapter's
373 * FreeQ.
374 */
375 static inline void
mptscsih_add_sge(char * pAddr,u32 flagslength,dma_addr_t dma_addr)376 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
377 {
378 if (sizeof(dma_addr_t) == sizeof(u64)) {
379 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
380 u32 tmp = dma_addr & 0xFFFFFFFF;
381
382 pSge->FlagsLength = cpu_to_le32(flagslength);
383 pSge->Address.Low = cpu_to_le32(tmp);
384 tmp = (u32) ((u64)dma_addr >> 32);
385 pSge->Address.High = cpu_to_le32(tmp);
386
387 } else {
388 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
389 pSge->FlagsLength = cpu_to_le32(flagslength);
390 pSge->Address = cpu_to_le32(dma_addr);
391 }
392 } /* mptscsih_add_sge() */
393
394 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
395 /**
396 * mptscsih_add_chain - Place a chain SGE at address pAddr.
397 * @pAddr: virtual address for SGE
398 * @next: nextChainOffset value (u32's)
399 * @length: length of next SGL segment
400 * @dma_addr: Physical address
401 *
402 * This routine places a MPT request frame back on the MPT adapter's
403 * FreeQ.
404 */
405 static inline void
mptscsih_add_chain(char * pAddr,u8 next,u16 length,dma_addr_t dma_addr)406 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
407 {
408 if (sizeof(dma_addr_t) == sizeof(u64)) {
409 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
410 u32 tmp = dma_addr & 0xFFFFFFFF;
411
412 pChain->Length = cpu_to_le16(length);
413 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
414
415 pChain->NextChainOffset = next;
416
417 pChain->Address.Low = cpu_to_le32(tmp);
418 tmp = (u32) ((u64)dma_addr >> 32);
419 pChain->Address.High = cpu_to_le32(tmp);
420 } else {
421 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
422 pChain->Length = cpu_to_le16(length);
423 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
424 pChain->NextChainOffset = next;
425 pChain->Address = cpu_to_le32(dma_addr);
426 }
427 } /* mptscsih_add_chain() */
428
429 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
430 /*
431 * mptscsih_getFreeChainBuffes - Function to get a free chain
432 * from the MPT_SCSI_HOST FreeChainQ.
433 * @hd: Pointer to the MPT_SCSI_HOST instance
434 * @req_idx: Index of the SCSI IO request frame. (output)
435 *
436 * return SUCCESS or FAILED
437 */
438 static inline int
mptscsih_getFreeChainBuffer(MPT_SCSI_HOST * hd,int * retIndex)439 mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
440 {
441 MPT_FRAME_HDR *chainBuf;
442 unsigned long flags;
443 int rc;
444 int chain_idx;
445
446 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
447 if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
448
449 int offset;
450
451 chainBuf = hd->FreeChainQ.head;
452 Q_DEL_ITEM(&chainBuf->u.frame.linkage);
453 offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
454 chain_idx = offset / hd->ioc->req_sz;
455 rc = SUCCESS;
456 }
457 else {
458 rc = FAILED;
459 chain_idx = MPT_HOST_NO_CHAIN;
460 }
461 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
462
463
464 *retIndex = chain_idx;
465
466 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
467 hd->ioc->name, *retIndex, chainBuf));
468
469 return rc;
470 } /* mptscsih_getFreeChainBuffer() */
471
472 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
473 /*
474 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
475 * SCSIIORequest_t Message Frame.
476 * @hd: Pointer to MPT_SCSI_HOST structure
477 * @SCpnt: Pointer to Scsi_Cmnd structure
478 * @pReq: Pointer to SCSIIORequest_t structure
479 *
480 * Returns ...
481 */
482 static int
mptscsih_AddSGE(MPT_SCSI_HOST * hd,Scsi_Cmnd * SCpnt,SCSIIORequest_t * pReq,int req_idx)483 mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
484 SCSIIORequest_t *pReq, int req_idx)
485 {
486 char *psge;
487 char *chainSge;
488 struct scatterlist *sg;
489 int frm_sz;
490 int sges_left, sg_done;
491 int chain_idx = MPT_HOST_NO_CHAIN;
492 int sgeOffset;
493 int numSgeSlots, numSgeThisFrame;
494 u32 sgflags, sgdir, thisxfer = 0;
495 int chain_dma_off = 0;
496 int newIndex;
497 int ii;
498 dma_addr_t v2;
499
500 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
501 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
502 sgdir = MPT_TRANSFER_HOST_TO_IOC;
503 } else {
504 sgdir = MPT_TRANSFER_IOC_TO_HOST;
505 }
506
507 psge = (char *) &pReq->SGL;
508 frm_sz = hd->ioc->req_sz;
509
510 /* Map the data portion, if any.
511 * sges_left = 0 if no data transfer.
512 */
513 if ( (sges_left = SCpnt->use_sg) ) {
514 if ( (sges_left = pci_map_sg(hd->ioc->pcidev,
515 (struct scatterlist *) SCpnt->request_buffer,
516 SCpnt->use_sg,
517 scsi_to_pci_dma_dir(SCpnt->sc_data_direction)))
518 == 0 )
519 return FAILED;
520 } else if (SCpnt->request_bufflen) {
521 dma_addr_t buf_dma_addr;
522 scPrivate *my_priv;
523
524 buf_dma_addr = pci_map_single(hd->ioc->pcidev,
525 SCpnt->request_buffer,
526 SCpnt->request_bufflen,
527 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
528
529 /* We hide it here for later unmap. */
530 my_priv = (scPrivate *) &SCpnt->SCp;
531 my_priv->p1 = (void *)(ulong) buf_dma_addr;
532
533 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
534 hd->ioc->name, SCpnt, SCpnt->request_bufflen));
535
536 mptscsih_add_sge((char *) &pReq->SGL,
537 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
538 buf_dma_addr);
539
540 return SUCCESS;
541 }
542
543 /* Handle the SG case.
544 */
545 sg = (struct scatterlist *) SCpnt->request_buffer;
546 sg_done = 0;
547 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
548 chainSge = NULL;
549
550 /* Prior to entering this loop - the following must be set
551 * current MF: sgeOffset (bytes)
552 * chainSge (Null if original MF is not a chain buffer)
553 * sg_done (num SGE done for this MF)
554 */
555
556 nextSGEset:
557 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
558 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
559
560 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
561
562 /* Get first (num - 1) SG elements
563 * Skip any SG entries with a length of 0
564 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
565 */
566 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
567 thisxfer = sg_dma_len(sg);
568 if (thisxfer == 0) {
569 sg ++; /* Get next SG element from the OS */
570 sg_done++;
571 continue;
572 }
573
574 v2 = sg_dma_address(sg);
575 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
576
577 sg++; /* Get next SG element from the OS */
578 psge += (sizeof(u32) + sizeof(dma_addr_t));
579 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
580 sg_done++;
581 }
582
583 if (numSgeThisFrame == sges_left) {
584 /* Add last element, end of buffer and end of list flags.
585 */
586 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
587 MPT_SGE_FLAGS_END_OF_BUFFER |
588 MPT_SGE_FLAGS_END_OF_LIST;
589
590 /* Add last SGE and set termination flags.
591 * Note: Last SGE may have a length of 0 - which should be ok.
592 */
593 thisxfer = sg_dma_len(sg);
594
595 v2 = sg_dma_address(sg);
596 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
597 /*
598 sg++;
599 psge += (sizeof(u32) + sizeof(dma_addr_t));
600 */
601 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
602 sg_done++;
603
604 if (chainSge) {
605 /* The current buffer is a chain buffer,
606 * but there is not another one.
607 * Update the chain element
608 * Offset and Length fields.
609 */
610 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
611 } else {
612 /* The current buffer is the original MF
613 * and there is no Chain buffer.
614 */
615 pReq->ChainOffset = 0;
616 }
617 } else {
618 /* At least one chain buffer is needed.
619 * Complete the first MF
620 * - last SGE element, set the LastElement bit
621 * - set ChainOffset (words) for orig MF
622 * (OR finish previous MF chain buffer)
623 * - update MFStructPtr ChainIndex
624 * - Populate chain element
625 * Also
626 * Loop until done.
627 */
628
629 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
630 hd->ioc->name, sg_done));
631
632 /* Set LAST_ELEMENT flag for last non-chain element
633 * in the buffer. Since psge points at the NEXT
634 * SGE element, go back one SGE element, update the flags
635 * and reset the pointer. (Note: sgflags & thisxfer are already
636 * set properly).
637 */
638 if (sg_done) {
639 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
640 sgflags = le32_to_cpu(*ptmp);
641 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
642 *ptmp = cpu_to_le32(sgflags);
643 }
644
645 if (chainSge) {
646 /* The current buffer is a chain buffer.
647 * chainSge points to the previous Chain Element.
648 * Update its chain element Offset and Length (must
649 * include chain element size) fields.
650 * Old chain element is now complete.
651 */
652 u8 nextChain = (u8) (sgeOffset >> 2);
653 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
654 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
655 } else {
656 /* The original MF buffer requires a chain buffer -
657 * set the offset.
658 * Last element in this MF is a chain element.
659 */
660 pReq->ChainOffset = (u8) (sgeOffset >> 2);
661 }
662
663 sges_left -= sg_done;
664
665
666 /* NOTE: psge points to the beginning of the chain element
667 * in current buffer. Get a chain buffer.
668 */
669 if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
670 return FAILED;
671
672 /* Update the tracking arrays.
673 * If chainSge == NULL, update ReqToChain, else ChainToChain
674 */
675 if (chainSge) {
676 hd->ChainToChain[chain_idx] = newIndex;
677 } else {
678 hd->ReqToChain[req_idx] = newIndex;
679 }
680 chain_idx = newIndex;
681 chain_dma_off = hd->ioc->req_sz * chain_idx;
682
683 /* Populate the chainSGE for the current buffer.
684 * - Set chain buffer pointer to psge and fill
685 * out the Address and Flags fields.
686 */
687 chainSge = (char *) psge;
688 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
689 psge, req_idx));
690
691 /* Start the SGE for the next buffer
692 */
693 psge = (char *) (hd->ChainBuffer + chain_dma_off);
694 sgeOffset = 0;
695 sg_done = 0;
696
697 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
698 psge, chain_idx));
699
700 /* Start the SGE for the next buffer
701 */
702
703 goto nextSGEset;
704 }
705
706 return SUCCESS;
707 } /* mptscsih_AddSGE() */
708
709 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
710 /*
711 * mptscsih_io_done - Main SCSI IO callback routine registered to
712 * Fusion MPT (base) driver
713 * @ioc: Pointer to MPT_ADAPTER structure
714 * @mf: Pointer to original MPT request frame
715 * @r: Pointer to MPT reply frame (NULL if TurboReply)
716 *
717 * This routine is called from mpt.c::mpt_interrupt() at the completion
718 * of any SCSI IO request.
719 * This routine is registered with the Fusion MPT (base) driver at driver
720 * load/init time via the mpt_register() API call.
721 *
722 * Returns 1 indicating alloc'd request frame ptr should be freed.
723 */
724 static int
mptscsih_io_done(MPT_ADAPTER * ioc,MPT_FRAME_HDR * mf,MPT_FRAME_HDR * mr)725 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
726 {
727 Scsi_Cmnd *sc;
728 MPT_SCSI_HOST *hd;
729 SCSIIORequest_t *pScsiReq;
730 SCSIIOReply_t *pScsiReply;
731 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
732 unsigned long flags;
733 #endif
734 u16 req_idx;
735
736 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
737
738 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
739 sc = hd->ScsiLookup[req_idx];
740 if (sc == NULL) {
741 MPIHeader_t *hdr = (MPIHeader_t *)mf;
742
743 /* Remark: writeSDP1 will use the ScsiDoneCtx
744 * If a SCSI I/O cmd, device disabled by OS and
745 * completion done. Cannot touch sc struct. Just free mem.
746 */
747 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
748 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n", ioc->name);
749
750 mptscsih_freeChainBuffers(hd, req_idx);
751 return 1;
752 }
753
754 dmfprintk((MYIOC_s_INFO_FMT "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
755 ioc->name, mf, mr, sc, req_idx));
756
757 sc->result = DID_OK << 16; /* Set default reply as OK */
758 pScsiReq = (SCSIIORequest_t *) mf;
759 pScsiReply = (SCSIIOReply_t *) mr;
760
761 #ifdef MPTSCSIH_DBG_TIMEOUT
762 if (ioc->timeout_cnt > 0) {
763 int ii, left = 0;
764
765 for (ii=0; ii < 8; ii++) {
766 if (sc == foo_to[ii]) {
767 printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n",
768 ioc->name, sc, jiffies);
769 foo_to[ii] = NULL;
770 }
771 if (foo_to[ii] != NULL)
772 left++;
773 }
774
775 if (left == 0) {
776 ioc->timeout_maxcnt = 0;
777 ioc->timeout_cnt = 0;
778 }
779 }
780 #endif
781 if (pScsiReply == NULL) {
782 /* special context reply handling */
783
784 /* If regular Inquiry cmd - save inquiry data
785 */
786 if (pScsiReq->CDB[0] == INQUIRY) {
787 int dlen;
788
789 dlen = le32_to_cpu(pScsiReq->DataLength);
790 mptscsih_initTarget(hd,
791 sc->channel,
792 sc->target,
793 pScsiReq->LUN[1],
794 sc->buffer,
795 dlen);
796 }
797 } else {
798 u32 xfer_cnt;
799 u16 status;
800 u8 scsi_state, scsi_status;
801
802 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
803 scsi_state = pScsiReply->SCSIState;
804
805 dprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
806 ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
807 mf, mr, sc));
808 dprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh"
809 ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
810 status, scsi_state, pScsiReply->SCSIStatus,
811 le32_to_cpu(pScsiReply->IOCLogInfo)));
812
813 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
814 copy_sense_data(sc, hd, mf, pScsiReply);
815
816 switch(status) {
817 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
818 /* CHECKME!
819 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
820 * But not: DID_BUS_BUSY lest one risk
821 * killing interrupt handler:-(
822 */
823 sc->result = STS_BUSY;
824 break;
825
826 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
827 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
828 sc->result = DID_BAD_TARGET << 16;
829 break;
830
831 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
832 /* Spoof to SCSI Selection Timeout! */
833 sc->result = DID_NO_CONNECT << 16;
834
835 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
836 hd->sel_timeout[pScsiReq->TargetID]++;
837 break;
838
839 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
840 #ifndef MPT_SCSI_USE_NEW_EH
841 search_taskQ_for_cmd(sc, hd);
842 #endif
843 /* Linux handles an unsolicited DID_RESET better
844 * than an unsolicited DID_ABORT.
845 */
846 sc->result = DID_RESET << 16;
847
848 /* GEM Workaround. */
849 if (hd->is_spi)
850 mptscsih_no_negotiate(hd, sc->target);
851 break;
852
853 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
854 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
855 #ifndef MPT_SCSI_USE_NEW_EH
856 search_taskQ_for_cmd(sc, hd);
857 #endif
858 sc->result = DID_RESET << 16;
859
860 /* GEM Workaround. */
861 if (hd->is_spi)
862 mptscsih_no_negotiate(hd, sc->target);
863 break;
864
865 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
866 sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
867 (CHECK_CONDITION << 1);
868 sc->sense_buffer[0] = 0x70;
869 sc->sense_buffer[2] = NO_SENSE;
870 sc->sense_buffer[12] = 0;
871 sc->sense_buffer[13] = 0;
872 dprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
873 break;
874
875 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
876 /*
877 * Do upfront check for valid SenseData and give it
878 * precedence!
879 */
880 scsi_status = pScsiReply->SCSIStatus;
881 sc->result = (DID_OK << 16) | scsi_status;
882 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
883 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
884 /* Have already saved the status and sense data
885 */
886 ;
887 } else {
888 if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) {
889 sc->result = DID_SOFT_ERROR << 16;
890 }
891 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
892 /* What to do?
893 */
894 sc->result = DID_SOFT_ERROR << 16;
895 }
896 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
897 /* Not real sure here either... */
898 sc->result = DID_RESET << 16;
899 }
900 }
901
902 /* Give report and update residual count.
903 */
904 dprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
905 sc->underflow));
906 dprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
907
908 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
909 sc->resid = sc->request_bufflen - xfer_cnt;
910 dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid));
911 #endif
912 /* Report Queue Full
913 */
914 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
915 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
916
917 /* If regular Inquiry cmd and some data was transferred,
918 * save inquiry data
919 */
920 if ( (pScsiReq->CDB[0] == INQUIRY) && xfer_cnt ) {
921 mptscsih_initTarget(hd,
922 sc->channel,
923 sc->target,
924 pScsiReq->LUN[1],
925 sc->buffer,
926 xfer_cnt);
927 }
928 break;
929
930 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
931 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
932 sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
933 if (scsi_state == 0) {
934 ;
935 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
936 /*
937 * If running against circa 200003dd 909 MPT f/w,
938 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
939 * (QUEUE_FULL) returned from device! --> get 0x0000?128
940 * and with SenseBytes set to 0.
941 */
942 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
943 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
944
945 #ifndef MPT_SCSI_USE_NEW_EH
946 /* ADDED 20011120 -sralston
947 * Scsi mid-layer (old_eh) doesn't seem to like it
948 * when RAID returns SCSIStatus=02 (CHECK CONDITION),
949 * SenseKey=01 (RECOVERED ERROR), ASC/ASCQ=95/01.
950 * Seems to be * treating this as a IO error:-(
951 *
952 * So just lie about it altogether here.
953 *
954 * NOTE: It still gets reported to syslog via
955 * mpt_ScsiHost_ErrorReport from copy_sense_data
956 * call far above.
957 */
958 if ( pScsiReply->SCSIStatus == STS_CHECK_CONDITION
959 && SD_Sense_Key(sc->sense_buffer) == SK_RECOVERED_ERROR
960 ) {
961 sc->result = 0;
962 }
963 #endif
964
965 }
966 else if (scsi_state &
967 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
968 ) {
969 /*
970 * What to do?
971 */
972 sc->result = DID_SOFT_ERROR << 16;
973 }
974 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
975 /* Not real sure here either... */
976 sc->result = DID_RESET << 16;
977 }
978 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
979 /* Device Inq. data indicates that it supports
980 * QTags, but rejects QTag messages.
981 * This command completed OK.
982 *
983 * Not real sure here either so do nothing... */
984 }
985
986 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
987 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
988
989 /* Add handling of:
990 * Reservation Conflict, Busy,
991 * Command Terminated, CHECK
992 */
993
994 /* If regular Inquiry cmd - save inquiry data
995 */
996 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
997 if ( (sc->result == (DID_OK << 16))
998 && xfer_cnt
999 && pScsiReq->CDB[0] == INQUIRY ) {
1000 mptscsih_initTarget(hd,
1001 sc->channel,
1002 sc->target,
1003 pScsiReq->LUN[1],
1004 sc->buffer,
1005 xfer_cnt);
1006 }
1007 break;
1008
1009 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
1010 if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) {
1011 /* Not real sure here either... */
1012 sc->result = DID_RESET << 16;
1013 } else
1014 sc->result = DID_SOFT_ERROR << 16;
1015 break;
1016
1017 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
1018 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
1019 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
1020 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
1021 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
1022 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
1023 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
1024 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
1025 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
1026 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
1027 default:
1028 /*
1029 * What to do?
1030 */
1031 sc->result = DID_SOFT_ERROR << 16;
1032 break;
1033
1034 } /* switch(status) */
1035
1036 dprintk((KERN_NOTICE " sc->result set to %08xh\n", sc->result));
1037 } /* end of address reply case */
1038
1039 /* Unmap the DMA buffers, if any. */
1040 if (sc->use_sg) {
1041 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
1042 sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
1043 } else if (sc->request_bufflen) {
1044 scPrivate *my_priv;
1045
1046 my_priv = (scPrivate *) &sc->SCp;
1047 pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
1048 sc->request_bufflen,
1049 scsi_to_pci_dma_dir(sc->sc_data_direction));
1050 }
1051
1052 hd->ScsiLookup[req_idx] = NULL;
1053
1054 #ifndef MPT_SCSI_USE_NEW_EH
1055 sc->host_scribble = NULL;
1056 #endif
1057
1058 MPT_HOST_LOCK(flags);
1059 sc->scsi_done(sc); /* Issue the command callback */
1060 MPT_HOST_UNLOCK(flags);
1061
1062 /* Free Chain buffers */
1063 mptscsih_freeChainBuffers(hd, req_idx);
1064 return 1;
1065 }
1066
1067 #ifndef MPT_SCSI_USE_NEW_EH /* { */
1068 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1069 /*
1070 * search_taskQ - Search SCSI task mgmt request queue for specific
1071 * request type.
1072 * @remove: (Boolean) Should request be removed if found?
1073 * @sc: Pointer to Scsi_Cmnd structure
1074 * @task_type: Task type to search for
1075 *
1076 * Returns pointer to MPT request frame if found, or %NULL if request
1077 * was not found.
1078 */
1079 static MPT_FRAME_HDR *
search_taskQ(int remove,Scsi_Cmnd * sc,MPT_SCSI_HOST * hd,u8 task_type)1080 search_taskQ(int remove, Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, u8 task_type)
1081 {
1082 MPT_FRAME_HDR *mf = NULL;
1083 unsigned long flags;
1084 int count = 0;
1085 int list_sz;
1086
1087 dprintk((KERN_INFO MYNAM ": search_taskQ(%d,sc=%p,%d) called\n",
1088 remove, sc, task_type));
1089 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1090 list_sz = hd->taskQcnt;
1091 if (! Q_IS_EMPTY(&hd->taskQ)) {
1092 mf = hd->taskQ.head;
1093 do {
1094 count++;
1095 if (mf->u.frame.linkage.argp1 == sc &&
1096 mf->u.frame.linkage.arg1 == task_type) {
1097 if (remove) {
1098 Q_DEL_ITEM(&mf->u.frame.linkage);
1099 hd->taskQcnt--;
1100 atomic_dec(&mpt_taskQdepth);
1101
1102 /* Don't save mf into nextmf because
1103 * exit after command has been deleted.
1104 */
1105
1106 /* Place the MF back on the FreeQ */
1107 Q_ADD_TAIL(&hd->ioc->FreeQ,
1108 &mf->u.frame.linkage,
1109 MPT_FRAME_HDR);
1110 #ifdef MFCNT
1111 hd->ioc->mfcnt--;
1112 #endif
1113 }
1114 break;
1115 }
1116 } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ);
1117 if (mf == (MPT_FRAME_HDR*)&hd->taskQ) {
1118 mf = NULL;
1119 }
1120 }
1121 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1122
1123 if (list_sz) {
1124 dprintk((KERN_INFO " Results=%p (%sFOUND%s)!\n",
1125 mf,
1126 mf ? "" : "NOT_",
1127 (mf && remove) ? "+REMOVED" : "" ));
1128 dprintk((KERN_INFO " (searched thru %d of %d items on taskQ)\n",
1129 count,
1130 list_sz ));
1131 }
1132
1133 return mf;
1134 }
1135
1136 /*
1137 * clean_taskQ - Clean the SCSI task mgmt request for
1138 * this SCSI host instance.
1139 * @hd: MPT_SCSI_HOST pointer
1140 *
1141 * Returns: None.
1142 */
1143 static void
clean_taskQ(MPT_SCSI_HOST * hd)1144 clean_taskQ(MPT_SCSI_HOST *hd)
1145 {
1146 MPT_FRAME_HDR *mf;
1147 MPT_FRAME_HDR *nextmf;
1148 MPT_ADAPTER *ioc = hd->ioc;
1149 unsigned long flags;
1150
1151 dprintk((KERN_INFO MYNAM ": clean_taskQ called\n"));
1152
1153 spin_lock_irqsave(&ioc->FreeQlock, flags);
1154 if (! Q_IS_EMPTY(&hd->taskQ)) {
1155 mf = hd->taskQ.head;
1156 do {
1157 Q_DEL_ITEM(&mf->u.frame.linkage);
1158 hd->taskQcnt--;
1159 atomic_dec(&mpt_taskQdepth);
1160
1161 nextmf = mf->u.frame.linkage.forw;
1162
1163 /* Place the MF back on the FreeQ */
1164 Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage,
1165 MPT_FRAME_HDR);
1166 #ifdef MFCNT
1167 hd->ioc->mfcnt--;
1168 #endif
1169 } while ((mf = nextmf) != (MPT_FRAME_HDR*)&hd->taskQ);
1170 }
1171 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1172
1173 return;
1174 }
1175
1176 /*
1177 * search_taskQ_for_cmd - Search the SCSI task mgmt request queue for
1178 * the specified command. If found, delete
1179 * @hd: MPT_SCSI_HOST pointer
1180 *
1181 * Returns: None.
1182 */
1183 static void
search_taskQ_for_cmd(Scsi_Cmnd * sc,MPT_SCSI_HOST * hd)1184 search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd)
1185 {
1186 MPT_FRAME_HDR *mf;
1187 unsigned long flags;
1188 int count = 0;
1189
1190 dprintk((KERN_INFO MYNAM ": search_taskQ_for_cmd(sc=%p) called\n", sc));
1191 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1192 if (! Q_IS_EMPTY(&hd->taskQ)) {
1193 mf = hd->taskQ.head;
1194 do {
1195 count++;
1196 if (mf->u.frame.linkage.argp1 == sc) {
1197 Q_DEL_ITEM(&mf->u.frame.linkage);
1198 hd->taskQcnt--;
1199 atomic_dec(&mpt_taskQdepth);
1200 dprintk((KERN_INFO MYNAM
1201 ": Cmd %p found! Deleting.\n", sc));
1202
1203 /* Don't save mf into nextmf because
1204 * exit after command has been deleted.
1205 */
1206
1207 /* Place the MF back on the FreeQ */
1208 Q_ADD_TAIL(&hd->ioc->FreeQ,
1209 &mf->u.frame.linkage,
1210 MPT_FRAME_HDR);
1211 #ifdef MFCNT
1212 hd->ioc->mfcnt--;
1213 #endif
1214 break;
1215 }
1216 } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ);
1217 }
1218 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1219
1220 return;
1221 }
1222
1223 #endif /* } MPT_SCSI_USE_NEW_EH */
1224
1225
1226 /*
1227 * Flush all commands on the doneQ.
1228 * Lock Q when deleting/adding members
1229 * Lock io_request_lock for OS callback.
1230 */
1231 static void
flush_doneQ(MPT_SCSI_HOST * hd)1232 flush_doneQ(MPT_SCSI_HOST *hd)
1233 {
1234 MPT_DONE_Q *buffer;
1235 Scsi_Cmnd *SCpnt;
1236 unsigned long flags;
1237
1238 /* Flush the doneQ.
1239 */
1240 dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n"));
1241 while (1) {
1242 spin_lock_irqsave(&hd->freedoneQlock, flags);
1243 if (Q_IS_EMPTY(&hd->doneQ)) {
1244 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1245 break;
1246 }
1247
1248 buffer = hd->doneQ.head;
1249 /* Delete from Q
1250 */
1251 Q_DEL_ITEM(buffer);
1252
1253 /* Set the Scsi_Cmnd pointer
1254 */
1255 SCpnt = (Scsi_Cmnd *) buffer->argp;
1256 buffer->argp = NULL;
1257
1258 /* Add to the freeQ
1259 */
1260 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1261 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1262
1263 /* Do the OS callback.
1264 */
1265 MPT_HOST_LOCK(flags);
1266 SCpnt->scsi_done(SCpnt);
1267 MPT_HOST_UNLOCK(flags);
1268 }
1269
1270 return;
1271 }
1272
1273 /*
1274 * Search the doneQ for a specific command. If found, delete from Q.
1275 * Calling function will finish processing.
1276 */
1277 static void
search_doneQ_for_cmd(MPT_SCSI_HOST * hd,Scsi_Cmnd * SCpnt)1278 search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
1279 {
1280 unsigned long flags;
1281 MPT_DONE_Q *buffer;
1282
1283 spin_lock_irqsave(&hd->freedoneQlock, flags);
1284 if (!Q_IS_EMPTY(&hd->doneQ)) {
1285 buffer = hd->doneQ.head;
1286 do {
1287 Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp;
1288 if (SCpnt == sc) {
1289 Q_DEL_ITEM(buffer);
1290 SCpnt->result = sc->result;
1291
1292 /* Set the Scsi_Cmnd pointer
1293 */
1294 buffer->argp = NULL;
1295
1296 /* Add to the freeQ
1297 */
1298 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1299 break;
1300 }
1301 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
1302 }
1303 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1304 return;
1305 }
1306
1307 static void
mptscsih_reset_timeouts(MPT_SCSI_HOST * hd)1308 mptscsih_reset_timeouts (MPT_SCSI_HOST *hd)
1309 {
1310 Scsi_Cmnd *SCpnt;
1311 int ii;
1312 int max = hd->ioc->req_depth;
1313
1314 for (ii= 0; ii < max; ii++) {
1315 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
1316 mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
1317 dtmprintk((MYIOC_s_WARN_FMT "resetting SCpnt=%p timeout + 60HZ",
1318 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1319 }
1320 }
1321 }
1322
1323 /*
1324 * mptscsih_flush_running_cmds - For each command found, search
1325 * Scsi_Host instance taskQ and reply to OS.
1326 * Called only if recovering from a FW reload.
1327 * @hd: Pointer to a SCSI HOST structure
1328 *
1329 * Returns: None.
1330 *
1331 * Must be called while new I/Os are being queued.
1332 */
1333 static void
mptscsih_flush_running_cmds(MPT_SCSI_HOST * hd)1334 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
1335 {
1336 Scsi_Cmnd *SCpnt;
1337 MPT_FRAME_HDR *mf;
1338 MPT_DONE_Q *buffer;
1339 int ii;
1340 int max = hd->ioc->req_depth;
1341
1342 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
1343 unsigned long flags;
1344 #endif
1345
1346 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
1347 for (ii= 0; ii < max; ii++) {
1348 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
1349
1350 /* Command found.
1351 */
1352 #ifndef MPT_SCSI_USE_NEW_EH
1353 /* Search taskQ, if found, delete.
1354 */
1355 search_taskQ_for_cmd(SCpnt, hd);
1356 #endif
1357
1358 /* Search pendingQ, if found,
1359 * delete from Q.
1360 */
1361 mptscsih_search_pendingQ(hd, ii);
1362
1363 /* Null ScsiLookup index
1364 */
1365 hd->ScsiLookup[ii] = NULL;
1366
1367 mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
1368 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", mf, SCpnt));
1369
1370 /* Set status, free OS resources (SG DMA buffers)
1371 * Free driver resources (chain, msg buffers)
1372 */
1373 if (SCpnt->use_sg) {
1374 pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
1375 SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1376 } else if (SCpnt->request_bufflen) {
1377 scPrivate *my_priv;
1378
1379 my_priv = (scPrivate *) &SCpnt->SCp;
1380 pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
1381 SCpnt->request_bufflen,
1382 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1383 }
1384 SCpnt->result = DID_RESET << 16;
1385 SCpnt->host_scribble = NULL;
1386
1387 /* Free Chain buffers */
1388 mptscsih_freeChainBuffers(hd, ii);
1389
1390 /* Free Message frames */
1391 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
1392
1393 #if 1
1394 /* Post to doneQ, do not reply until POST phase
1395 * of reset handler....prevents new commands from
1396 * being queued.
1397 */
1398 spin_lock_irqsave(&hd->freedoneQlock, flags);
1399 if (!Q_IS_EMPTY(&hd->freeQ)) {
1400 buffer = hd->freeQ.head;
1401 Q_DEL_ITEM(buffer);
1402
1403 /* Set the Scsi_Cmnd pointer
1404 */
1405 buffer->argp = (void *)SCpnt;
1406
1407 /* Add to the doneQ
1408 */
1409 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
1410 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1411 } else {
1412 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1413 SCpnt->scsi_done(SCpnt);
1414 }
1415 #else
1416 MPT_HOST_LOCK(flags);
1417 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1418 MPT_HOST_UNLOCK(flags);
1419 #endif
1420 }
1421 }
1422
1423 return;
1424 }
1425
1426 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1427 /*
1428 * mptscsih_initChainBuffers - Allocate memory for and initialize
1429 * chain buffers, chain buffer control arrays and spinlock.
1430 * @hd: Pointer to MPT_SCSI_HOST structure
1431 * @init: If set, initialize the spin lock.
1432 */
1433 static int
mptscsih_initChainBuffers(MPT_SCSI_HOST * hd,int init)1434 mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
1435 {
1436 MPT_FRAME_HDR *chain;
1437 u8 *mem;
1438 unsigned long flags;
1439 int sz, ii, num_chain;
1440 int scale, num_sge;
1441
1442 /* ReqToChain size must equal the req_depth
1443 * index = req_idx
1444 */
1445 if (hd->ReqToChain == NULL) {
1446 sz = hd->ioc->req_depth * sizeof(int);
1447 mem = kmalloc(sz, GFP_ATOMIC);
1448 if (mem == NULL)
1449 return -1;
1450
1451 hd->ReqToChain = (int *) mem;
1452 }
1453 for (ii = 0; ii < hd->ioc->req_depth; ii++)
1454 hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
1455
1456 /* ChainToChain size must equal the total number
1457 * of chain buffers to be allocated.
1458 * index = chain_idx
1459 *
1460 * Calculate the number of chain buffers needed(plus 1) per I/O
1461 * then multiply the the maximum number of simultaneous cmds
1462 *
1463 * num_sge = num sge in request frame + last chain buffer
1464 * scale = num sge per chain buffer if no chain element
1465 */
1466 scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1467 if (sizeof(dma_addr_t) == sizeof(u64))
1468 num_sge = scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
1469 else
1470 num_sge = 1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
1471
1472 num_chain = 1;
1473 while (hd->max_sge - num_sge > 0) {
1474 num_chain++;
1475 num_sge += (scale - 1);
1476 }
1477 num_chain++;
1478
1479 if ((int) hd->ioc->chip_type > (int) FC929)
1480 num_chain *= MPT_SCSI_CAN_QUEUE;
1481 else
1482 num_chain *= MPT_FC_CAN_QUEUE;
1483
1484 hd->num_chain = num_chain;
1485
1486 sz = num_chain * sizeof(int);
1487 if (hd->ChainToChain == NULL) {
1488 mem = kmalloc(sz, GFP_ATOMIC);
1489 if (mem == NULL)
1490 return -1;
1491
1492 hd->ChainToChain = (int *) mem;
1493 } else {
1494 mem = (u8 *) hd->ChainToChain;
1495 }
1496 memset(mem, 0xFF, sz);
1497
1498 sz = num_chain * hd->ioc->req_sz;
1499 if (hd->ChainBuffer == NULL) {
1500 /* Allocate free chain buffer pool
1501 */
1502 mem = pci_alloc_consistent(hd->ioc->pcidev, sz, &hd->ChainBufferDMA);
1503 if (mem == NULL)
1504 return -1;
1505
1506 hd->ChainBuffer = (u8*)mem;
1507 } else {
1508 mem = (u8 *) hd->ChainBuffer;
1509 }
1510 memset(mem, 0, sz);
1511
1512 dprintk((KERN_INFO " ChainBuffer @ %p(%p), sz=%d\n",
1513 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, sz));
1514
1515 /* Initialize the free chain Q.
1516 */
1517 if (init) {
1518 spin_lock_init(&hd->FreeChainQlock);
1519 }
1520
1521 spin_lock_irqsave (&hd->FreeChainQlock, flags);
1522 Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
1523
1524 /* Post the chain buffers to the FreeChainQ.
1525 */
1526 mem = (u8 *)hd->ChainBuffer;
1527 for (ii=0; ii < num_chain; ii++) {
1528 chain = (MPT_FRAME_HDR *) mem;
1529 Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
1530 mem += hd->ioc->req_sz;
1531 }
1532 spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
1533
1534 return 0;
1535 }
1536
1537 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1538 /*
1539 * Hack! It might be nice to report if a device is returning QUEUE_FULL
1540 * but maybe not each and every time...
1541 */
1542 static long last_queue_full = 0;
1543
1544 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1545 /*
1546 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1547 * from a SCSI target device.
1548 * @sc: Pointer to Scsi_Cmnd structure
1549 * @pScsiReply: Pointer to SCSIIOReply_t
1550 * @pScsiReq: Pointer to original SCSI request
1551 *
1552 * This routine periodically reports QUEUE_FULL status returned from a
1553 * SCSI target device. It reports this to the console via kernel
1554 * printk() API call, not more than once every 10 seconds.
1555 */
1556 static void
mptscsih_report_queue_full(Scsi_Cmnd * sc,SCSIIOReply_t * pScsiReply,SCSIIORequest_t * pScsiReq)1557 mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1558 {
1559 long time = jiffies;
1560
1561 if (time - last_queue_full > 10 * HZ) {
1562 char *ioc_str = "ioc?";
1563
1564 if (sc->host != NULL && sc->host->hostdata != NULL)
1565 ioc_str = ((MPT_SCSI_HOST *)sc->host->hostdata)->ioc->name;
1566 printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1567 ioc_str, 0, sc->target, sc->lun);
1568 last_queue_full = time;
1569 }
1570 }
1571
1572 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1573 static int BeenHereDoneThat = 0;
1574 static char *info_kbuf = NULL;
1575
1576 /* SCSI host fops start here... */
1577 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1578 /**
1579 * mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with
1580 * linux scsi mid-layer.
1581 * @tpnt: Pointer to Scsi_Host_Template structure
1582 *
1583 * (linux Scsi_Host_Template.detect routine)
1584 *
1585 * Returns number of SCSI host adapters that were successfully
1586 * registered with the linux scsi mid-layer via the scsi_register()
1587 * API call.
1588 */
1589 int
mptscsih_detect(Scsi_Host_Template * tpnt)1590 mptscsih_detect(Scsi_Host_Template *tpnt)
1591 {
1592 struct Scsi_Host *sh;
1593 MPT_SCSI_HOST *hd;
1594 MPT_ADAPTER *ioc;
1595 MPT_DONE_Q *freedoneQ;
1596 unsigned long flags;
1597 int sz, ii;
1598 int numSGE = 0;
1599 int scale;
1600 int ioc_cap;
1601 u8 *mem;
1602
1603 if (! BeenHereDoneThat++) {
1604 show_mptmod_ver(my_NAME, my_VERSION);
1605
1606 ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
1607 ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
1608 ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
1609
1610 #ifndef MPT_SCSI_USE_NEW_EH
1611 spin_lock_init(&mytaskQ_lock);
1612 #endif
1613
1614 if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
1615 dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n"));
1616 } else {
1617 /* FIXME! */
1618 }
1619
1620 if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
1621 dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
1622 } else {
1623 /* FIXME! */
1624 }
1625 }
1626 dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()\n"));
1627
1628 #ifdef MODULE
1629 /* Evaluate the command line arguments, if any */
1630 if (mptscsih)
1631 mptscsih_setup(mptscsih);
1632 #endif
1633 #ifndef MPT_SCSI_USE_NEW_EH
1634 atomic_set(&mpt_taskQdepth, 0);
1635 #endif
1636
1637 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
1638 /* 20010202 -sralston
1639 * Added sanity check on readiness of the MPT adapter.
1640 */
1641 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1642 printk(MYIOC_s_WARN_FMT "Skipping because it's not operational!\n",
1643 ioc->name);
1644 continue;
1645 }
1646
1647 if (!ioc->active) {
1648 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1649 ioc->name);
1650 continue;
1651 }
1652
1653
1654 /* Sanity check - ensure at least 1 port is INITIATOR capable
1655 */
1656 ioc_cap = 0;
1657 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1658 if (ioc->pfacts[ii].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)
1659 ioc_cap ++;
1660 }
1661
1662 if (!ioc_cap) {
1663 printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1664 ioc->name, ioc);
1665 continue;
1666 }
1667
1668
1669 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
1670 tpnt->proc_dir = &proc_mpt_scsihost;
1671 #endif
1672 tpnt->proc_info = mptscsih_proc_info;
1673 sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
1674 if (sh != NULL) {
1675 spin_lock_irqsave(&ioc->FreeQlock, flags);
1676 sh->io_port = 0;
1677 sh->n_io_port = 0;
1678 sh->irq = 0;
1679
1680 /* Yikes! This is important!
1681 * Otherwise, by default, linux
1682 * only scans target IDs 0-7!
1683 * pfactsN->MaxDevices unreliable
1684 * (not supported in early
1685 * versions of the FW).
1686 * max_id = 1 + actual max id,
1687 * max_lun = 1 + actual last lun,
1688 * see hosts.h :o(
1689 */
1690 if ((int)ioc->chip_type > (int)FC929)
1691 sh->max_id = MPT_MAX_SCSI_DEVICES;
1692 else {
1693 /* For FC, increase the queue depth
1694 * from MPT_SCSI_CAN_QUEUE (31)
1695 * to MPT_FC_CAN_QUEUE (63).
1696 */
1697 sh->can_queue = MPT_FC_CAN_QUEUE;
1698 sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1699 }
1700 sh->max_lun = MPT_LAST_LUN + 1;
1701
1702 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
1703 sh->max_sectors = MPT_SCSI_MAX_SECTORS;
1704 #endif
1705 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || defined CONFIG_HIGHIO
1706 sh->highmem_io = 1;
1707 #endif
1708 /* MPI uses {port, bus, id, lun}, but logically maps
1709 * devices on different ports to different buses, i.e.,
1710 * bus 1 may be the 2nd bus on port 0 or the 1st bus on port 1.
1711 * Map bus to channel, ignore port number in SCSI....
1712 * hd->port = 0;
1713 * If max_channel > 0, need to adjust mem alloc, free, DV
1714 * and all access to VirtDev
1715 */
1716 sh->max_channel = 0;
1717 sh->this_id = ioc->pfacts[0].PortSCSIID;
1718
1719 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
1720 /* OS entry to allow host drivers to force
1721 * a queue depth on a per device basis.
1722 */
1723 sh->select_queue_depths = mptscsih_select_queue_depths;
1724 #endif
1725 /* Required entry.
1726 */
1727 sh->unique_id = ioc->id;
1728
1729 /* Verify that we won't exceed the maximum
1730 * number of chain buffers
1731 * We can optimize: ZZ = req_sz/sizeof(SGE)
1732 * For 32bit SGE's:
1733 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1734 * + (req_sz - 64)/sizeof(SGE)
1735 * A slightly different algorithm is required for
1736 * 64bit SGEs.
1737 */
1738 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1739 if (sizeof(dma_addr_t) == sizeof(u64)) {
1740 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
1741 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
1742 } else {
1743 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
1744 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
1745 }
1746
1747 if (numSGE < sh->sg_tablesize) {
1748 /* Reset this value */
1749 dprintk((MYIOC_s_INFO_FMT
1750 "Resetting sg_tablesize to %d from %d\n",
1751 ioc->name, numSGE, sh->sg_tablesize));
1752 sh->sg_tablesize = numSGE;
1753 }
1754
1755 /* Set the pci device pointer in Scsi_Host structure.
1756 */
1757 scsi_set_pci_device(sh, ioc->pcidev);
1758
1759 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1760
1761 hd = (MPT_SCSI_HOST *) sh->hostdata;
1762 hd->ioc = ioc;
1763 hd->max_sge = sh->sg_tablesize;
1764
1765 if ((int)ioc->chip_type > (int)FC929)
1766 hd->is_spi = 1;
1767
1768 if (DmpService &&
1769 (ioc->chip_type == FC919 || ioc->chip_type == FC929))
1770 hd->is_multipath = 1;
1771
1772 /* SCSI needs Scsi_Cmnd lookup table!
1773 * (with size equal to req_depth*PtrSz!)
1774 */
1775 sz = hd->ioc->req_depth * sizeof(void *);
1776 mem = kmalloc(sz, GFP_ATOMIC);
1777 if (mem == NULL)
1778 goto done;
1779
1780 memset(mem, 0, sz);
1781 hd->ScsiLookup = (struct scsi_cmnd **) mem;
1782
1783 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1784 ioc->name, hd->ScsiLookup, sz));
1785
1786 if (mptscsih_initChainBuffers(hd, 1) < 0)
1787 goto done;
1788
1789 /* Allocate memory for free and doneQ's
1790 */
1791 sz = sh->can_queue * sizeof(MPT_DONE_Q);
1792 mem = kmalloc(sz, GFP_ATOMIC);
1793 if (mem == NULL)
1794 goto done;
1795
1796 memset(mem, 0xFF, sz);
1797 hd->memQ = mem;
1798
1799 /* Initialize the free, done and pending Qs.
1800 */
1801 Q_INIT(&hd->freeQ, MPT_DONE_Q);
1802 Q_INIT(&hd->doneQ, MPT_DONE_Q);
1803 Q_INIT(&hd->pendingQ, MPT_DONE_Q);
1804 spin_lock_init(&hd->freedoneQlock);
1805
1806 mem = hd->memQ;
1807 for (ii=0; ii < sh->can_queue; ii++) {
1808 freedoneQ = (MPT_DONE_Q *) mem;
1809 Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
1810 mem += sizeof(MPT_DONE_Q);
1811 }
1812
1813 /* Initialize this Scsi_Host
1814 * internal task Q.
1815 */
1816 Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
1817 hd->taskQcnt = 0;
1818
1819 /* Allocate memory for the device structures.
1820 * A non-Null pointer at an offset
1821 * indicates a device exists.
1822 * max_id = 1 + maximum id (hosts.h)
1823 */
1824 sz = sh->max_id * sizeof(void *);
1825 mem = kmalloc(sz, GFP_ATOMIC);
1826 if (mem == NULL)
1827 goto done;
1828
1829 memset(mem, 0, sz);
1830 hd->Targets = (VirtDevice **) mem;
1831
1832 dprintk((KERN_INFO " Targets @ %p, sz=%d\n", hd->Targets, sz));
1833
1834
1835 /* Clear the TM flags
1836 */
1837 hd->tmPending = 0;
1838 #ifdef MPT_SCSI_USE_NEW_EH
1839 hd->tmState = TM_STATE_NONE;
1840 #endif
1841 hd->resetPending = 0;
1842 hd->abortSCpnt = NULL;
1843 hd->tmPtr = NULL;
1844 hd->numTMrequests = 0;
1845
1846 /* Clear the pointer used to store
1847 * single-threaded commands, i.e., those
1848 * issued during a bus scan, dv and
1849 * configuration pages.
1850 */
1851 hd->cmdPtr = NULL;
1852
1853 /* Attach the SCSI Host to the IOC structure
1854 */
1855 ioc->sh = sh;
1856
1857 /* Initialize this SCSI Hosts' timers
1858 * To use, set the timer expires field
1859 * and add_timer
1860 */
1861 init_timer(&hd->timer);
1862 hd->timer.data = (unsigned long) hd;
1863 hd->timer.function = mptscsih_timer_expired;
1864
1865 init_timer(&hd->TMtimer);
1866 hd->TMtimer.data = (unsigned long) hd;
1867 hd->TMtimer.function = mptscsih_taskmgmt_timeout;
1868 hd->qtag_tick = jiffies;
1869
1870 /* Moved Earlier Pam D */
1871 /* ioc->sh = sh; */
1872
1873 #ifdef MPTSCSIH_DBG_TIMEOUT
1874 hd->ioc->timeout_hard = 0;
1875 hd->ioc->timeout_delta = 30 * HZ;
1876 hd->ioc->timeout_maxcnt = 0;
1877 hd->ioc->timeout_cnt = 0;
1878 for (ii=0; ii < 8; ii++)
1879 foo_to[ii] = NULL;
1880 #endif
1881
1882 if (hd->is_spi) {
1883 /* Update with the driver setup
1884 * values.
1885 */
1886 if (hd->ioc->spi_data.maxBusWidth > driver_setup.max_width)
1887 hd->ioc->spi_data.maxBusWidth = driver_setup.max_width;
1888 if (hd->ioc->spi_data.minSyncFactor < driver_setup.min_sync_fac)
1889 hd->ioc->spi_data.minSyncFactor = driver_setup.min_sync_fac;
1890
1891 if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC)
1892 hd->ioc->spi_data.maxSyncOffset = 0;
1893
1894 hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
1895
1896 hd->negoNvram = 0;
1897 #ifdef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
1898 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1899 #endif
1900 if (driver_setup.dv == 0)
1901 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1902
1903 hd->ioc->spi_data.forceDv = 0;
1904 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
1905 hd->ioc->spi_data.dvStatus[ii] = MPT_SCSICFG_NEGOTIATE;
1906
1907 if (hd->negoNvram == 0) {
1908 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
1909 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_NOT_DONE;
1910 }
1911
1912 ddvprintk((MYIOC_s_INFO_FMT
1913 "dv %x width %x factor %x saf_te %x\n",
1914 hd->ioc->name, driver_setup.dv,
1915 driver_setup.max_width,
1916 driver_setup.min_sync_fac,
1917 driver_setup.saf_te));
1918 }
1919
1920 mpt_scsi_hosts++;
1921 }
1922 }
1923
1924 done:
1925 if (mpt_scsi_hosts > 0)
1926 register_reboot_notifier(&mptscsih_notifier);
1927 else {
1928 mpt_reset_deregister(ScsiDoneCtx);
1929 dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));
1930
1931 mpt_event_deregister(ScsiDoneCtx);
1932 dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));
1933
1934 mpt_deregister(ScsiScanDvCtx);
1935 mpt_deregister(ScsiTaskCtx);
1936 mpt_deregister(ScsiDoneCtx);
1937
1938 if (info_kbuf != NULL)
1939 kfree(info_kbuf);
1940 }
1941
1942 return mpt_scsi_hosts;
1943 }
1944
1945 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1946 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1947 /**
1948 * mptscsih_release - Unregister SCSI host from linux scsi mid-layer
1949 * @host: Pointer to Scsi_Host structure
1950 *
1951 * (linux Scsi_Host_Template.release routine)
1952 * This routine releases all resources associated with the SCSI host
1953 * adapter.
1954 *
1955 * Returns 0 for success.
1956 */
1957 int
mptscsih_release(struct Scsi_Host * host)1958 mptscsih_release(struct Scsi_Host *host)
1959 {
1960 MPT_SCSI_HOST *hd;
1961 int count;
1962 unsigned long flags;
1963
1964 hd = (MPT_SCSI_HOST *) host->hostdata;
1965
1966 #ifndef MPT_SCSI_USE_NEW_EH
1967 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
1968 spin_lock_irqsave(&dvtaskQ_lock, flags);
1969 dvtaskQ_release = 1;
1970 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1971 #endif
1972
1973 count = 10 * HZ;
1974 spin_lock_irqsave(&mytaskQ_lock, flags);
1975 if (mytaskQ_bh_active) {
1976 spin_unlock_irqrestore(&mytaskQ_lock, flags);
1977 dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n"));
1978 clean_taskQ(hd);
1979
1980 while(mytaskQ_bh_active && --count) {
1981 set_current_state(TASK_INTERRUPTIBLE);
1982 schedule_timeout(1);
1983 }
1984 } else {
1985 spin_unlock_irqrestore(&mytaskQ_lock, flags);
1986 }
1987 if (!count)
1988 printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!\n");
1989
1990 #endif
1991
1992 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
1993 /* Check DV thread active */
1994 count = 10 * HZ;
1995 spin_lock_irqsave(&dvtaskQ_lock, flags);
1996 if (dvtaskQ_active) {
1997 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1998 while(dvtaskQ_active && --count) {
1999 set_current_state(TASK_INTERRUPTIBLE);
2000 schedule_timeout(1);
2001 }
2002 } else {
2003 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
2004 }
2005 if (!count)
2006 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
2007 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
2008 else
2009 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
2010 #endif
2011 #endif
2012
2013 unregister_reboot_notifier(&mptscsih_notifier);
2014
2015 if (hd != NULL) {
2016 int sz1, sz2, sz3, sztarget=0;
2017 int szr2chain = 0;
2018 int szc2chain = 0;
2019 int szchain = 0;
2020 int szQ = 0;
2021
2022 /* Synchronize disk caches
2023 */
2024 (void) mptscsih_synchronize_cache(hd, 0);
2025
2026 sz1 = sz2 = sz3 = 0;
2027
2028 if (hd->ScsiLookup != NULL) {
2029 sz1 = hd->ioc->req_depth * sizeof(void *);
2030 kfree(hd->ScsiLookup);
2031 hd->ScsiLookup = NULL;
2032 }
2033
2034 if (hd->ReqToChain != NULL) {
2035 szr2chain = hd->ioc->req_depth * sizeof(int);
2036 kfree(hd->ReqToChain);
2037 hd->ReqToChain = NULL;
2038 }
2039
2040 if (hd->ChainToChain != NULL) {
2041 szc2chain = hd->num_chain * sizeof(int);
2042 kfree(hd->ChainToChain);
2043 hd->ChainToChain = NULL;
2044 }
2045
2046 if (hd->ChainBuffer != NULL) {
2047 sz2 = hd->num_chain * hd->ioc->req_sz;
2048 szchain = szr2chain + szc2chain + sz2;
2049
2050 pci_free_consistent(hd->ioc->pcidev, sz2,
2051 hd->ChainBuffer, hd->ChainBufferDMA);
2052 hd->ChainBuffer = NULL;
2053 }
2054
2055 if (hd->memQ != NULL) {
2056 szQ = host->can_queue * sizeof(MPT_DONE_Q);
2057 kfree(hd->memQ);
2058 hd->memQ = NULL;
2059 }
2060
2061 if (hd->Targets != NULL) {
2062 int max, ii;
2063
2064 /*
2065 * Free any target structures that were allocated.
2066 */
2067 if (hd->is_spi) {
2068 max = MPT_MAX_SCSI_DEVICES;
2069 } else {
2070 max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
2071 }
2072 for (ii=0; ii < max; ii++) {
2073 if (hd->Targets[ii]) {
2074 kfree(hd->Targets[ii]);
2075 hd->Targets[ii] = NULL;
2076 sztarget += sizeof(VirtDevice);
2077 }
2078 }
2079
2080 /*
2081 * Free pointer array.
2082 */
2083 sz3 = max * sizeof(void *);
2084 kfree(hd->Targets);
2085 hd->Targets = NULL;
2086 }
2087
2088 dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
2089 hd->ioc->name, sz1, szchain, sz3, sztarget));
2090 dprintk(("Free'd done and free Q (%d) memory\n", szQ));
2091 }
2092 /* NULL the Scsi_Host pointer
2093 */
2094 hd->ioc->sh = NULL;
2095 scsi_unregister(host);
2096
2097 if (mpt_scsi_hosts) {
2098 if (--mpt_scsi_hosts == 0) {
2099 mpt_reset_deregister(ScsiDoneCtx);
2100 dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));
2101
2102 mpt_event_deregister(ScsiDoneCtx);
2103 dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));
2104
2105 mpt_deregister(ScsiScanDvCtx);
2106 mpt_deregister(ScsiTaskCtx);
2107 mpt_deregister(ScsiDoneCtx);
2108
2109 if (info_kbuf != NULL)
2110 kfree(info_kbuf);
2111 }
2112 }
2113
2114 return 0;
2115 }
2116
2117 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2118 /**
2119 * mptscsih_halt - Process the reboot notification
2120 * @nb: Pointer to a struct notifier_block (ignored)
2121 * @event: event (SYS_HALT, SYS_RESTART, SYS_POWER_OFF)
2122 * @buf: Pointer to a data buffer (ignored)
2123 *
2124 * This routine called if a system shutdown or reboot is to occur.
2125 *
2126 * Return NOTIFY_DONE if this is something other than a reboot message.
2127 * NOTIFY_OK if this is a reboot message.
2128 */
2129 static int
mptscsih_halt(struct notifier_block * nb,ulong event,void * buf)2130 mptscsih_halt(struct notifier_block *nb, ulong event, void *buf)
2131 {
2132 MPT_ADAPTER *ioc;
2133 MPT_SCSI_HOST *hd;
2134
2135 /* Ignore all messages other than reboot message
2136 */
2137 if ((event != SYS_RESTART) && (event != SYS_HALT)
2138 && (event != SYS_POWER_OFF))
2139 return (NOTIFY_DONE);
2140
2141 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
2142 /* Flush the cache of this adapter
2143 */
2144 if (ioc->sh) {
2145 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2146 if (hd) {
2147 mptscsih_synchronize_cache(hd, 0);
2148 }
2149 }
2150 }
2151
2152 unregister_reboot_notifier(&mptscsih_notifier);
2153 return NOTIFY_OK;
2154 }
2155
2156 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2157 /**
2158 * mptscsih_info - Return information about MPT adapter
2159 * @SChost: Pointer to Scsi_Host structure
2160 *
2161 * (linux Scsi_Host_Template.info routine)
2162 *
2163 * Returns pointer to buffer where information was written.
2164 */
2165 const char *
mptscsih_info(struct Scsi_Host * SChost)2166 mptscsih_info(struct Scsi_Host *SChost)
2167 {
2168 MPT_SCSI_HOST *h;
2169 int size = 0;
2170
2171 if (info_kbuf == NULL)
2172 if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
2173 return info_kbuf;
2174
2175 h = (MPT_SCSI_HOST *)SChost->hostdata;
2176 info_kbuf[0] = '\0';
2177 if (h) {
2178 mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
2179 info_kbuf[size-1] = '\0';
2180 }
2181
2182 return info_kbuf;
2183 }
2184
2185 struct info_str {
2186 char *buffer;
2187 int length;
2188 int offset;
2189 int pos;
2190 };
2191
copy_mem_info(struct info_str * info,char * data,int len)2192 static void copy_mem_info(struct info_str *info, char *data, int len)
2193 {
2194 if (info->pos + len > info->length)
2195 len = info->length - info->pos;
2196
2197 if (info->pos + len < info->offset) {
2198 info->pos += len;
2199 return;
2200 }
2201
2202 if (info->pos < info->offset) {
2203 data += (info->offset - info->pos);
2204 len -= (info->offset - info->pos);
2205 }
2206
2207 if (len > 0) {
2208 memcpy(info->buffer + info->pos, data, len);
2209 info->pos += len;
2210 }
2211 }
2212
copy_info(struct info_str * info,char * fmt,...)2213 static int copy_info(struct info_str *info, char *fmt, ...)
2214 {
2215 va_list args;
2216 char buf[81];
2217 int len;
2218
2219 va_start(args, fmt);
2220 len = vsprintf(buf, fmt, args);
2221 va_end(args);
2222
2223 copy_mem_info(info, buf, len);
2224 return len;
2225 }
2226
mptscsih_host_info(MPT_ADAPTER * ioc,char * pbuf,off_t offset,int len)2227 static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
2228 {
2229 struct info_str info;
2230
2231 info.buffer = pbuf;
2232 info.length = len;
2233 info.offset = offset;
2234 info.pos = 0;
2235
2236 copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
2237 copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
2238 copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
2239 copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
2240
2241 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
2242 }
2243
2244 #ifndef MPTSCSIH_DBG_TIMEOUT
mptscsih_user_command(MPT_ADAPTER * ioc,char * pbuf,int len)2245 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len)
2246 {
2247 /* Not yet implemented */
2248 return len;
2249 }
2250 #else
2251 #define is_digit(c) ((c) >= '0' && (c) <= '9')
2252 #define digit_to_bin(c) ((c) - '0')
2253 #define is_space(c) ((c) == ' ' || (c) == '\t')
2254
2255 #define UC_DBG_TIMEOUT 0x01
2256 #define UC_DBG_HARDRESET 0x02
2257
skip_spaces(char * ptr,int len)2258 static int skip_spaces(char *ptr, int len)
2259 {
2260 int cnt, c;
2261
2262 for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --);
2263
2264 return (len - cnt);
2265 }
2266
get_int_arg(char * ptr,int len,ulong * pv)2267 static int get_int_arg(char *ptr, int len, ulong *pv)
2268 {
2269 int cnt, c;
2270 ulong v;
2271 for (v = 0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) {
2272 v = (v * 10) + digit_to_bin(c);
2273 }
2274
2275 if (pv)
2276 *pv = v;
2277
2278 return (len - cnt);
2279 }
2280
2281
is_keyword(char * ptr,int len,char * verb)2282 static int is_keyword(char *ptr, int len, char *verb)
2283 {
2284 int verb_len = strlen(verb);
2285
2286 if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
2287 return verb_len;
2288 else
2289 return 0;
2290 }
2291
2292 #define SKIP_SPACES(min_spaces) \
2293 if ((arg_len = skip_spaces(ptr,len)) < (min_spaces)) \
2294 return -EINVAL; \
2295 ptr += arg_len; \
2296 len -= arg_len;
2297
2298 #define GET_INT_ARG(v) \
2299 if (!(arg_len = get_int_arg(ptr,len, &(v)))) \
2300 return -EINVAL; \
2301 ptr += arg_len; \
2302 len -= arg_len;
2303
mptscsih_user_command(MPT_ADAPTER * ioc,char * buffer,int length)2304 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length)
2305 {
2306 char *ptr = buffer;
2307 char btmp[24]; /* REMOVE */
2308 int arg_len;
2309 int len = length;
2310 int cmd;
2311 ulong number = 1;
2312 ulong delta = 10;
2313
2314 if ((len > 0) && (ptr[len -1] == '\n'))
2315 --len;
2316
2317 if (len < 22) {
2318 strncpy(btmp, buffer, len);
2319 btmp[len+1]='\0';
2320 } else {
2321 strncpy(btmp, buffer, 22);
2322 btmp[23]='\0';
2323 }
2324 printk("user_command: ioc %d, buffer %s, length %d\n",
2325 ioc->id, btmp, length);
2326
2327 if ((arg_len = is_keyword(ptr, len, "timeout")) != 0)
2328 cmd = UC_DBG_TIMEOUT;
2329 else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0)
2330 cmd = UC_DBG_HARDRESET;
2331 else
2332 return -EINVAL;
2333
2334 ptr += arg_len;
2335 len -= arg_len;
2336
2337 switch(cmd) {
2338 case UC_DBG_TIMEOUT:
2339 SKIP_SPACES(1);
2340 GET_INT_ARG(number);
2341 SKIP_SPACES(1);
2342 GET_INT_ARG(delta);
2343 break;
2344 }
2345
2346 printk("user_command: cnt=%ld delta=%ld\n", number, delta);
2347
2348 if (len)
2349 return -EINVAL;
2350 else {
2351 if (cmd == UC_DBG_HARDRESET) {
2352 ioc->timeout_hard = 1;
2353 } else if (cmd == UC_DBG_TIMEOUT) {
2354 /* process this command ...
2355 */
2356 ioc->timeout_maxcnt = 0;
2357 ioc->timeout_delta = delta < 2 ? 2 : delta;
2358 ioc->timeout_cnt = 0;
2359 ioc->timeout_maxcnt = number < 8 ? number: 8;
2360 }
2361 }
2362 /* Not yet implemented */
2363 return length;
2364 }
2365 #endif
2366
2367
2368 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2369 /**
2370 * mptscsih_proc_info - Return information about MPT adapter
2371 *
2372 * (linux Scsi_Host_Template.info routine)
2373 *
2374 * buffer: if write, user data; if read, buffer for user
2375 * length: if write, return length;
2376 * offset: if write, 0; if read, the current offset into the buffer from
2377 * the previous read.
2378 * hostno: scsi host number
2379 * func: if write = 1; if read = 0
2380 */
mptscsih_proc_info(char * buffer,char ** start,off_t offset,int length,int hostno,int func)2381 int mptscsih_proc_info(char *buffer, char **start, off_t offset,
2382 int length, int hostno, int func)
2383 {
2384 MPT_ADAPTER *ioc;
2385 MPT_SCSI_HOST *hd = NULL;
2386 int size = 0;
2387
2388 dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", hostno, func));
2389 dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n",
2390 buffer, start, *start, offset, length));
2391
2392 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
2393 if ((ioc->sh) && (ioc->sh->host_no == hostno)) {
2394 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2395 break;
2396 }
2397 }
2398 if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL))
2399 return 0;
2400
2401 if (func) {
2402 size = mptscsih_user_command(ioc, buffer, length);
2403 } else {
2404 if (start)
2405 *start = buffer;
2406
2407 size = mptscsih_host_info(ioc, buffer, offset, length);
2408 }
2409
2410 return size;
2411 }
2412
2413
2414 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2415 #if 0
2416 static int index_log[128];
2417 static int index_ent = 0;
2418 static __inline__ void ADD_INDEX_LOG(int req_ent)
2419 {
2420 int i = index_ent++;
2421
2422 index_log[i & (128 - 1)] = req_ent;
2423 }
2424 #else
2425 #define ADD_INDEX_LOG(req_ent) do { } while(0)
2426 #endif
2427
2428
2429 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2430 /**
2431 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
2432 * @SCpnt: Pointer to Scsi_Cmnd structure
2433 * @done: Pointer SCSI mid-layer IO completion function
2434 *
2435 * (linux Scsi_Host_Template.queuecommand routine)
2436 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
2437 * from a linux Scsi_Cmnd request and send it to the IOC.
2438 *
2439 * Returns 0. (rtn value discarded by linux scsi mid-layer)
2440 */
2441 int
mptscsih_qcmd(Scsi_Cmnd * SCpnt,void (* done)(Scsi_Cmnd *))2442 mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2443 {
2444 MPT_SCSI_HOST *hd;
2445 MPT_FRAME_HDR *mf;
2446 SCSIIORequest_t *pScsiReq;
2447 VirtDevice *pTarget;
2448 MPT_DONE_Q *buffer;
2449 unsigned long flags;
2450 int target;
2451 int lun;
2452 int datadir;
2453 u32 datalen;
2454 u32 scsictl;
2455 u32 scsidir;
2456 u32 cmd_len;
2457 int my_idx;
2458 int ii;
2459 int rc;
2460 int did_errcode;
2461 int issueCmd;
2462
2463 did_errcode = 0;
2464 hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
2465 target = SCpnt->target;
2466 lun = SCpnt->lun;
2467 SCpnt->scsi_done = done;
2468
2469 pTarget = hd->Targets[target];
2470
2471 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
2472 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
2473
2474 if (hd->resetPending) {
2475 /* Prevent new commands from being issued
2476 * while reloading the FW. Reset timer to 60 seconds,
2477 * as the FW can take some time to come ready.
2478 * For New EH, cmds on doneQ posted to FW.
2479 */
2480 did_errcode = 1;
2481 mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
2482 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
2483 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2484 goto did_error;
2485 }
2486
2487 /*
2488 * Put together a MPT SCSI request...
2489 */
2490 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
2491 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
2492 hd->ioc->name));
2493 did_errcode = 2;
2494 goto did_error;
2495 }
2496
2497 pScsiReq = (SCSIIORequest_t *) mf;
2498
2499 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2500
2501 ADD_INDEX_LOG(my_idx);
2502
2503 /*
2504 * The scsi layer should be handling this stuff
2505 * (In 2.3.x it does -DaveM)
2506 */
2507
2508 /* BUG FIX! 19991030 -sralston
2509 * TUR's being issued with scsictl=0x02000000 (DATA_IN)!
2510 * Seems we may receive a buffer (datalen>0) even when there
2511 * will be no data transfer! GRRRRR...
2512 */
2513 datadir = mptscsih_io_direction(SCpnt);
2514 if (datadir == SCSI_DATA_READ) {
2515 datalen = SCpnt->request_bufflen;
2516 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
2517 } else if (datadir == SCSI_DATA_WRITE) {
2518 datalen = SCpnt->request_bufflen;
2519 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
2520 } else {
2521 datalen = 0;
2522 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
2523 }
2524
2525 /* Default to untagged. Once a target structure has been allocated,
2526 * use the Inquiry data to determine if device supports tagged.
2527 */
2528 if ( pTarget
2529 && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
2530 && (SCpnt->device->tagged_supported)) {
2531 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
2532 } else {
2533 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
2534 }
2535
2536 /* Use the above information to set up the message frame
2537 */
2538 pScsiReq->TargetID = (u8) target;
2539 pScsiReq->Bus = (u8) SCpnt->channel;
2540 pScsiReq->ChainOffset = 0;
2541 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
2542 pScsiReq->CDBLength = SCpnt->cmd_len;
2543 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2544 pScsiReq->Reserved = 0;
2545 pScsiReq->MsgFlags = mpt_msg_flags();
2546 pScsiReq->LUN[0] = 0;
2547 pScsiReq->LUN[1] = lun;
2548 pScsiReq->LUN[2] = 0;
2549 pScsiReq->LUN[3] = 0;
2550 pScsiReq->LUN[4] = 0;
2551 pScsiReq->LUN[5] = 0;
2552 pScsiReq->LUN[6] = 0;
2553 pScsiReq->LUN[7] = 0;
2554 pScsiReq->Control = cpu_to_le32(scsictl);
2555
2556 /*
2557 * Write SCSI CDB into the message
2558 */
2559 cmd_len = SCpnt->cmd_len;
2560 for (ii=0; ii < cmd_len; ii++)
2561 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
2562
2563 for (ii=cmd_len; ii < 16; ii++)
2564 pScsiReq->CDB[ii] = 0;
2565
2566 /* DataLength */
2567 pScsiReq->DataLength = cpu_to_le32(datalen);
2568
2569 /* SenseBuffer low address */
2570 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
2571 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
2572
2573 /* Now add the SG list
2574 * Always have a SGE even if null length.
2575 */
2576 rc = SUCCESS;
2577 if (datalen == 0) {
2578 /* Add a NULL SGE */
2579 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
2580 (dma_addr_t) -1);
2581 } else {
2582 /* Add a 32 or 64 bit SGE */
2583 rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
2584 }
2585
2586
2587 if (rc == SUCCESS) {
2588 hd->ScsiLookup[my_idx] = SCpnt;
2589 SCpnt->host_scribble = NULL;
2590
2591 /* SCSI specific processing */
2592 issueCmd = 1;
2593 if (hd->is_spi) {
2594 int dvStatus = hd->ioc->spi_data.dvStatus[target];
2595
2596 if (dvStatus || hd->ioc->spi_data.forceDv) {
2597
2598 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
2599 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
2600 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
2601 unsigned long lflags;
2602 /* Schedule DV if necessary */
2603 spin_lock_irqsave(&dvtaskQ_lock, lflags);
2604 if (!dvtaskQ_active) {
2605 dvtaskQ_active = 1;
2606 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2607 MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
2608
2609 SCHEDULE_TASK(&mptscsih_dvTask);
2610 } else {
2611 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2612 }
2613 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
2614 }
2615
2616 /* Trying to do DV to this target, extend timeout.
2617 * Wait to issue intil flag is clear
2618 */
2619 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
2620 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
2621 issueCmd = 0;
2622 }
2623
2624 /* Set the DV flags.
2625 */
2626 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
2627 mptscsih_set_dvflags(hd, pScsiReq);
2628 #endif
2629 }
2630 }
2631
2632 #ifdef MPTSCSIH_DBG_TIMEOUT
2633 if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) {
2634 foo_to[hd->ioc->timeout_cnt] = SCpnt;
2635 hd->ioc->timeout_cnt++;
2636 //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta);
2637 issueCmd = 0;
2638 printk(MYIOC_s_WARN_FMT
2639 "to pendingQ: (sc=%p, mf=%p, time=%ld)\n",
2640 hd->ioc->name, SCpnt, mf, jiffies);
2641 }
2642 #endif
2643
2644 if (issueCmd) {
2645 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2646 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
2647 hd->ioc->name, SCpnt, mf, my_idx));
2648 } else {
2649 ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
2650 hd->ioc->name, SCpnt, my_idx));
2651 /* Place this command on the pendingQ if possible */
2652 spin_lock_irqsave(&hd->freedoneQlock, flags);
2653 if (!Q_IS_EMPTY(&hd->freeQ)) {
2654 buffer = hd->freeQ.head;
2655 Q_DEL_ITEM(buffer);
2656
2657 /* Save the mf pointer
2658 */
2659 buffer->argp = (void *)mf;
2660
2661 /* Add to the pendingQ
2662 */
2663 Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
2664 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2665 } else {
2666 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2667 SCpnt->result = (DID_BUS_BUSY << 16);
2668 SCpnt->scsi_done(SCpnt);
2669 }
2670 }
2671 } else {
2672 mptscsih_freeChainBuffers(hd, my_idx);
2673 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2674 did_errcode = 3;
2675 goto did_error;
2676 }
2677
2678 return 0;
2679
2680 did_error:
2681 dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",
2682 hd->ioc->name, did_errcode, SCpnt));
2683 /* Just wish OS to issue a retry */
2684 SCpnt->result = (DID_BUS_BUSY << 16);
2685 spin_lock_irqsave(&hd->freedoneQlock, flags);
2686 if (!Q_IS_EMPTY(&hd->freeQ)) {
2687 dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",
2688 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2689 buffer = hd->freeQ.head;
2690 Q_DEL_ITEM(buffer);
2691
2692 /* Set the Scsi_Cmnd pointer
2693 */
2694 buffer->argp = (void *)SCpnt;
2695
2696 /* Add to the doneQ
2697 */
2698 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
2699 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2700 } else {
2701 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2702 SCpnt->scsi_done(SCpnt);
2703 }
2704
2705 return 0;
2706 }
2707
2708 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2709 /*
2710 * mptscsih_freeChainBuffers - Function to free chain buffers associated
2711 * with a SCSI IO request
2712 * @hd: Pointer to the MPT_SCSI_HOST instance
2713 * @req_idx: Index of the SCSI IO request frame.
2714 *
2715 * Called if SG chain buffer allocation fails and mptscsih callbacks.
2716 * No return.
2717 */
2718 static void
mptscsih_freeChainBuffers(MPT_SCSI_HOST * hd,int req_idx)2719 mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
2720 {
2721 MPT_FRAME_HDR *chain;
2722 unsigned long flags;
2723 int chain_idx;
2724 int next;
2725
2726 /* Get the first chain index and reset
2727 * tracker state.
2728 */
2729 chain_idx = hd->ReqToChain[req_idx];
2730 hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
2731
2732 while (chain_idx != MPT_HOST_NO_CHAIN) {
2733
2734 /* Save the next chain buffer index */
2735 next = hd->ChainToChain[chain_idx];
2736
2737 /* Free this chain buffer and reset
2738 * tracker
2739 */
2740 hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
2741
2742 chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
2743 + (chain_idx * hd->ioc->req_sz));
2744 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2745 Q_ADD_TAIL(&hd->FreeChainQ.head,
2746 &chain->u.frame.linkage, MPT_FRAME_HDR);
2747 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2748
2749 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
2750 hd->ioc->name, chain_idx));
2751
2752 /* handle next */
2753 chain_idx = next;
2754 }
2755 return;
2756 }
2757
2758 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2759 /*
2760 * Reset Handling
2761 */
2762
2763 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2764 /*
2765 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
2766 * Fall through to mpt_HardResetHandler if: not operational, too many
2767 * failed TM requests or handshake failure.
2768 *
2769 * @ioc: Pointer to MPT_ADAPTER structure
2770 * @type: Task Management type
2771 * @target: Logical Target ID for reset (if appropriate)
2772 * @lun: Logical Unit for reset (if appropriate)
2773 * @ctx2abort: Context for the task to be aborted (if appropriate)
2774 * @sleepFlag: If set, use udelay instead of schedule in handshake code.
2775 *
2776 * Remark: Currently invoked from a non-interrupt thread (_bh).
2777 *
2778 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
2779 * will be active.
2780 *
2781 * Returns 0 for SUCCESS or -1 if FAILED.
2782 */
2783 static int
mptscsih_TMHandler(MPT_SCSI_HOST * hd,u8 type,u8 channel,u8 target,u8 lun,int ctx2abort,int sleepFlag)2784 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag)
2785 {
2786 MPT_ADAPTER *ioc;
2787 int rc = -1;
2788 int doTask = 1;
2789 u32 ioc_raw_state;
2790 unsigned long flags;
2791
2792 /* If FW is being reloaded currently, return success to
2793 * the calling function.
2794 */
2795 if (hd == NULL)
2796 return 0;
2797
2798 ioc = hd->ioc;
2799 if (ioc == NULL) {
2800 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
2801 return FAILED;
2802 }
2803 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
2804
2805 // SJR - CHECKME - Can we avoid this here?
2806 // (mpt_HardResetHandler has this check...)
2807 spin_lock_irqsave(&ioc->diagLock, flags);
2808 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
2809 spin_unlock_irqrestore(&ioc->diagLock, flags);
2810 return FAILED;
2811 }
2812 spin_unlock_irqrestore(&ioc->diagLock, flags);
2813
2814 /* Do not do a Task Management if there are
2815 * too many failed TMs on this adapter.
2816 */
2817 if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
2818 doTask = 0;
2819
2820 #ifdef MPT_SCSI_USE_NEW_EH
2821 /* Wait a fixed amount of time for the TM pending flag to be cleared.
2822 * If we time out and not bus reset, then we return a FAILED status to the caller.
2823 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
2824 * successful. Otherwise, reload the FW.
2825 */
2826 if (mptscsih_tm_pending_wait(hd) == FAILED) {
2827 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
2828 nehprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
2829 "Timed out waiting for last TM (%d) to complete! \n",
2830 hd->ioc->name, hd->tmPending));
2831 return FAILED;
2832 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
2833 nehprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
2834 "Timed out waiting for last TM (%d) to complete! \n",
2835 hd->ioc->name, hd->tmPending));
2836 return FAILED;
2837 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2838 nehprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
2839 "Timed out waiting for last TM (%d) to complete! \n",
2840 hd->ioc->name, hd->tmPending));
2841 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
2842 return FAILED;
2843
2844 doTask = 0;
2845 }
2846 } else {
2847 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2848 hd->tmPending |= (1 << type);
2849 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2850 }
2851 #endif
2852
2853 /* Is operational?
2854 */
2855 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
2856
2857 #ifdef MPT_DEBUG_RESET
2858 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
2859 printk(MYIOC_s_WARN_FMT
2860 "TM Handler: IOC Not operational(0x%x)!\n",
2861 hd->ioc->name, ioc_raw_state);
2862 }
2863 #endif
2864
2865 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
2866 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
2867
2868 /* Isse the Task Mgmt request.
2869 */
2870 if (hd->hard_resets < -1)
2871 hd->hard_resets++;
2872 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, sleepFlag);
2873 if (rc) {
2874 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
2875 } else {
2876 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
2877 }
2878 }
2879 #ifdef MPTSCSIH_DBG_TIMEOUT
2880 if (hd->ioc->timeout_hard)
2881 rc = 1;
2882 #endif
2883
2884 /* Only fall through to the HRH if this is a bus reset
2885 */
2886 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
2887 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
2888 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
2889 hd->ioc->name));
2890 rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
2891 }
2892
2893 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
2894 #ifndef MPT_SCSI_USE_NEW_EH
2895 dtmprintk((MYIOC_s_INFO_FMT "TMHandler: _bh_handler state (%d) taskQ count (%d)\n",
2896 ioc->name, mytaskQ_bh_active, hd->taskQcnt));
2897 #endif
2898
2899 return rc;
2900 }
2901
2902 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2903 /*
2904 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
2905 * @hd: Pointer to MPT_SCSI_HOST structure
2906 * @type: Task Management type
2907 * @target: Logical Target ID for reset (if appropriate)
2908 * @lun: Logical Unit for reset (if appropriate)
2909 * @ctx2abort: Context for the task to be aborted (if appropriate)
2910 * @sleepFlag: If set, use udelay instead of schedule in handshake code.
2911 *
2912 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
2913 * or a non-interrupt thread. In the former, must not call schedule().
2914 *
2915 * Not all fields are meaningfull for all task types.
2916 *
2917 * Returns 0 for SUCCESS, -999 for "no msg frames",
2918 * else other non-zero value returned.
2919 */
2920 static int
mptscsih_IssueTaskMgmt(MPT_SCSI_HOST * hd,u8 type,u8 channel,u8 target,u8 lun,int ctx2abort,int sleepFlag)2921 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag)
2922 {
2923 MPT_FRAME_HDR *mf;
2924 SCSITaskMgmt_t *pScsiTm;
2925 int ii;
2926 int retval;
2927
2928 /* Return Fail to calling function if no message frames available.
2929 */
2930 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
2931 dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
2932 hd->ioc->name));
2933 //return FAILED;
2934 return -999;
2935 }
2936 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
2937 hd->ioc->name, mf));
2938
2939 /* Format the Request
2940 */
2941 pScsiTm = (SCSITaskMgmt_t *) mf;
2942 pScsiTm->TargetID = target;
2943 pScsiTm->Bus = channel;
2944 pScsiTm->ChainOffset = 0;
2945 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
2946
2947 pScsiTm->Reserved = 0;
2948 pScsiTm->TaskType = type;
2949 pScsiTm->Reserved1 = 0;
2950 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
2951 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
2952
2953 for (ii= 0; ii < 8; ii++) {
2954 pScsiTm->LUN[ii] = 0;
2955 }
2956 pScsiTm->LUN[1] = lun;
2957
2958 for (ii=0; ii < 7; ii++)
2959 pScsiTm->Reserved2[ii] = 0;
2960
2961 pScsiTm->TaskMsgContext = ctx2abort;
2962 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n",
2963 hd->ioc->name, ctx2abort, type));
2964
2965 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
2966 mpt_put_msg_frame(hd->ioc->id, mf);
2967 * Save the MF pointer in case the request times out.
2968 */
2969 hd->tmPtr = mf;
2970 hd->numTMrequests++;
2971 hd->TMtimer.expires = jiffies + HZ*20; /* 20 seconds */
2972 add_timer(&hd->TMtimer);
2973
2974 if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
2975 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
2976 != 0) {
2977 dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
2978 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
2979 hd->numTMrequests--;
2980 hd->tmPtr = NULL;
2981 del_timer(&hd->TMtimer);
2982 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
2983 }
2984
2985 return retval;
2986 }
2987
2988 #ifdef MPT_SCSI_USE_NEW_EH /* { */
2989 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2990 /**
2991 * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
2992 * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
2993 *
2994 * (linux Scsi_Host_Template.eh_abort_handler routine)
2995 *
2996 * Returns SUCCESS or FAILED.
2997 */
2998 int
mptscsih_abort(Scsi_Cmnd * SCpnt)2999 mptscsih_abort(Scsi_Cmnd * SCpnt)
3000 {
3001 MPT_SCSI_HOST *hd;
3002 MPT_FRAME_HDR *mf;
3003 u32 ctx2abort;
3004 int scpnt_idx;
3005
3006 /* If we can't locate our host adapter structure, return FAILED status.
3007 */
3008 if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
3009 SCpnt->result = DID_RESET << 16;
3010 SCpnt->scsi_done(SCpnt);
3011 nehprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
3012 "Can't locate host! (sc=%p)\n",
3013 SCpnt));
3014 return FAILED;
3015 }
3016
3017 if (hd->resetPending)
3018 return FAILED;
3019
3020 printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
3021 hd->ioc->name, SCpnt);
3022
3023 if (hd->timeouts < -1)
3024 hd->timeouts++;
3025
3026 /* Find this command
3027 */
3028 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
3029 /* Cmd not found in ScsiLookup. If found in
3030 * doneQ, delete from Q. Do OS callback.
3031 */
3032 search_doneQ_for_cmd(hd, SCpnt);
3033
3034 SCpnt->result = DID_RESET << 16;
3035 nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
3036 "Command not in the active list! (sc=%p)\n",
3037 hd->ioc->name, SCpnt));
3038 return SUCCESS;
3039 }
3040
3041 /* If this command is pended, then timeout/hang occurred
3042 * during DV. Post command and flush pending Q
3043 * and then following up with the reset request.
3044 */
3045 if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
3046 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
3047 post_pendingQ_commands(hd);
3048 nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
3049 "Posting pended cmd! (sc=%p)\n",
3050 hd->ioc->name, SCpnt));
3051 }
3052
3053 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
3054 * (the IO to be ABORT'd)
3055 *
3056 * NOTE: Since we do not byteswap MsgContext, we do not
3057 * swap it here either. It is an opaque cookie to
3058 * the controller, so it does not matter. -DaveM
3059 */
3060 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
3061 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
3062
3063 hd->abortSCpnt = SCpnt;
3064 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
3065 SCpnt->channel, SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP)
3066 < 0) {
3067
3068 /* The TM request failed and the subsequent FW-reload failed!
3069 * Fatal error case.
3070 */
3071 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
3072 hd->ioc->name, SCpnt);
3073
3074 /* We must clear our pending flag before clearing our state.
3075 */
3076 hd->tmPending = 0;
3077 hd->tmState = TM_STATE_NONE;
3078
3079 return FAILED;
3080 }
3081 return FAILED;
3082
3083 }
3084
3085 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3086 /**
3087 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
3088 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
3089 *
3090 * (linux Scsi_Host_Template.eh_dev_reset_handler routine)
3091 *
3092 * Returns SUCCESS or FAILED.
3093 */
3094 int
mptscsih_dev_reset(Scsi_Cmnd * SCpnt)3095 mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
3096 {
3097 MPT_SCSI_HOST *hd;
3098
3099 /* If we can't locate our host adapter structure, return FAILED status.
3100 */
3101 if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
3102 nehprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
3103 "Can't locate host! (sc=%p)\n",
3104 SCpnt));
3105 return FAILED;
3106 }
3107
3108 if (hd->resetPending)
3109 return FAILED;
3110
3111 printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
3112 hd->ioc->name, SCpnt);
3113
3114 /* Unsupported for SCSI. Supported for FCP
3115 */
3116 if (hd->is_spi)
3117 return FAILED;
3118
3119 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
3120 SCpnt->channel, SCpnt->target, 0, 0, NO_SLEEP)
3121 < 0){
3122 /* The TM request failed and the subsequent FW-reload failed!
3123 * Fatal error case.
3124 */
3125 printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
3126 hd->ioc->name, SCpnt);
3127 hd->tmPending = 0;
3128 hd->tmState = TM_STATE_NONE;
3129 return FAILED;
3130 }
3131 return SUCCESS;
3132
3133 }
3134
3135 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3136 /**
3137 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
3138 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
3139 *
3140 * (linux Scsi_Host_Template.eh_bus_reset_handler routine)
3141 *
3142 * Returns SUCCESS or FAILED.
3143 */
3144 int
mptscsih_bus_reset(Scsi_Cmnd * SCpnt)3145 mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
3146 {
3147 MPT_SCSI_HOST *hd;
3148
3149 /* If we can't locate our host adapter structure, return FAILED status.
3150 */
3151 if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
3152 nehprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
3153 "Can't locate host! (sc=%p)\n",
3154 SCpnt ) );
3155 return FAILED;
3156 }
3157
3158 printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
3159 hd->ioc->name, SCpnt);
3160
3161 if (hd->timeouts < -1)
3162 hd->timeouts++;
3163
3164 /* We are now ready to execute the task management request. */
3165 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
3166 SCpnt->channel, 0, 0, 0, NO_SLEEP)
3167 < 0){
3168
3169 /* The TM request failed and the subsequent FW-reload failed!
3170 * Fatal error case.
3171 */
3172 printk(MYIOC_s_WARN_FMT
3173 "Error processing TaskMgmt request (sc=%p)\n",
3174 hd->ioc->name, SCpnt);
3175 hd->tmPending = 0;
3176 hd->tmState = TM_STATE_NONE;
3177 return FAILED;
3178 }
3179
3180 return SUCCESS;
3181 }
3182
3183 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3184 /**
3185 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
3186 * new_eh variant
3187 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
3188 *
3189 * (linux Scsi_Host_Template.eh_host_reset_handler routine)
3190 *
3191 * Returns SUCCESS or FAILED.
3192 */
3193 int
mptscsih_host_reset(Scsi_Cmnd * SCpnt)3194 mptscsih_host_reset(Scsi_Cmnd *SCpnt)
3195 {
3196 MPT_SCSI_HOST * hd;
3197 int status = SUCCESS;
3198
3199 /* If we can't locate the host to reset, then we failed. */
3200 if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
3201 nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3202 "Can't locate host! (sc=%p)\n",
3203 SCpnt ) );
3204 return FAILED;
3205 }
3206
3207 printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
3208 hd->ioc->name, SCpnt);
3209
3210 /* If our attempts to reset the host failed, then return a failed
3211 * status. The host will be taken off line by the SCSI mid-layer.
3212 */
3213 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0){
3214 status = FAILED;
3215 } else {
3216 /* Make sure TM pending is cleared and TM state is set to
3217 * NONE.
3218 */
3219 hd->tmPending = 0;
3220 hd->tmState = TM_STATE_NONE;
3221 }
3222
3223
3224 nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3225 "Status = %s\n",
3226 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
3227
3228 return status;
3229 }
3230
3231 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3232 /**
3233 * mptscsih_tm_pending_wait - wait for pending task management request to
3234 * complete.
3235 * @hd: Pointer to MPT host structure.
3236 *
3237 * Returns {SUCCESS,FAILED}.
3238 */
3239 static int
mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)3240 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
3241 {
3242 unsigned long flags;
3243 int loop_count = 2 * 10 * 4; /* Wait 2 seconds */
3244 int status = FAILED;
3245
3246 do {
3247 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
3248 if (hd->tmState == TM_STATE_NONE) {
3249 hd->tmState = TM_STATE_IN_PROGRESS;
3250 hd->tmPending = 1;
3251 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3252 status = SUCCESS;
3253 break;
3254 }
3255 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3256 //set_current_state(TASK_INTERRUPTIBLE);
3257 //schedule_timeout(HZ/4);
3258 mdelay(250);
3259 } while (--loop_count);
3260
3261 return status;
3262 }
3263
3264 #else /* MPT_SCSI old EH stuff... */
3265 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3266 /**
3267 * mptscsih_old_abort - Abort linux Scsi_Cmnd routine
3268 * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
3269 *
3270 * (linux Scsi_Host_Template.abort routine)
3271 *
3272 * Returns SCSI_ABORT_{SUCCESS,BUSY,PENDING}.
3273 */
3274 int
mptscsih_old_abort(Scsi_Cmnd * SCpnt)3275 mptscsih_old_abort(Scsi_Cmnd *SCpnt)
3276 {
3277 MPT_SCSI_HOST *hd;
3278 MPT_FRAME_HDR *mf;
3279 struct mpt_work_struct *ptaskfoo;
3280 unsigned long flags;
3281 int scpnt_idx;
3282
3283 printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)\n", (void *) SCpnt);
3284
3285 if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
3286 printk(KERN_WARNING " WARNING - OldAbort, NULL hostdata ptr!!\n");
3287 SCpnt->result = DID_ERROR << 16;
3288 return SCSI_ABORT_NOT_RUNNING;
3289 }
3290
3291 if (hd->timeouts < -1)
3292 hd->timeouts++;
3293
3294 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
3295 /* Cmd not found in ScsiLookup.
3296 * If found in doneQ, delete from Q.
3297 * Do OS callback.
3298 */
3299 search_doneQ_for_cmd(hd, SCpnt);
3300
3301 SCpnt->result = DID_ABORT << 16;
3302 return SCSI_ABORT_SUCCESS;
3303 } else {
3304 /* If this command is pended, then timeout/hang occurred
3305 * during DV. Force bus reset by posting command to F/W
3306 * and then following up with the reset request.
3307 */
3308 #ifndef MPTSCSIH_DBG_TIMEOUT
3309 if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
3310 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
3311 post_pendingQ_commands(hd);
3312 }
3313 #endif
3314 }
3315
3316 /*
3317 * Check to see if there's already an ABORT queued for this guy.
3318 */
3319 mf = search_taskQ(0, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
3320 if (mf != NULL) {
3321 dtmprintk((MYIOC_s_INFO_FMT "OldAbort:Abort Task PENDING cmd (%p) taskQ depth (%d)\n",
3322 hd->ioc->name, SCpnt, hd->taskQcnt));
3323 return SCSI_ABORT_PENDING;
3324 }
3325
3326 // SJR - CHECKME - Can we avoid this here?
3327 // (mpt_HardResetHandler has this check...)
3328 /* If IOC is reloading FW, return PENDING.
3329 */
3330 spin_lock_irqsave(&hd->ioc->diagLock, flags);
3331 if (hd->ioc->diagPending) {
3332 spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
3333 return SCSI_ABORT_PENDING;
3334 }
3335 spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
3336
3337 /* If there are no message frames what should we do?
3338 */
3339 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
3340 printk((KERN_WARNING " WARNING - OldAbort, no msg frames!!\n"));
3341 /* We are out of message frames!
3342 * Call the reset handler to do a FW reload.
3343 */
3344 printk((KERN_WARNING " Reloading Firmware!!\n"));
3345 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3346 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
3347 }
3348 return SCSI_ABORT_PENDING;
3349 }
3350
3351 /*
3352 * Add ourselves to (end of) taskQ .
3353 * Check to see if our _bh is running. If NOT, schedule it.
3354 */
3355 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
3356 Q_ADD_TAIL(&hd->taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
3357 hd->taskQcnt++;
3358 atomic_inc(&mpt_taskQdepth);
3359 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3360
3361 spin_lock_irqsave(&mytaskQ_lock, flags);
3362
3363 /* Save the original SCpnt mf pointer
3364 */
3365 SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx);
3366
3367 /* For the time being, force bus reset on any abort
3368 * requests for the 1030/1035 FW.
3369 */
3370 if (hd->is_spi)
3371 mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
3372 else
3373 mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
3374
3375 mf->u.frame.linkage.argp1 = SCpnt;
3376 mf->u.frame.linkage.argp2 = (void *) hd;
3377
3378 dtmprintk((MYIOC_s_INFO_FMT "OldAbort:_bh_handler state (%d) taskQ count (%d)\n",
3379 hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt));
3380
3381 if (! mytaskQ_bh_active) {
3382 mytaskQ_bh_active = 1;
3383 spin_unlock_irqrestore(&mytaskQ_lock, flags);
3384
3385 ptaskfoo = (struct mpt_work_struct *) &mptscsih_ptaskfoo;
3386 MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt);
3387
3388 SCHEDULE_TASK(ptaskfoo);
3389 } else {
3390 spin_unlock_irqrestore(&mytaskQ_lock, flags);
3391 }
3392
3393 return SCSI_ABORT_PENDING;
3394 }
3395
3396 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3397 /**
3398 * mptscsih_old_reset - Perform a SCSI BUS_RESET!
3399 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
3400 * @reset_flags: (not used?)
3401 *
3402 * (linux Scsi_Host_Template.reset routine)
3403 *
3404 * Returns SCSI_RESET_{SUCCESS,PUNT,PENDING}.
3405 */
3406 int
mptscsih_old_reset(Scsi_Cmnd * SCpnt,unsigned int reset_flags)3407 mptscsih_old_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
3408 {
3409 MPT_SCSI_HOST *hd;
3410 MPT_FRAME_HDR *mf;
3411 struct mpt_work_struct *ptaskfoo;
3412 unsigned long flags;
3413 int scpnt_idx;
3414
3415 printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)\n", (void *) SCpnt);
3416
3417 if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
3418 SCpnt->result = DID_ERROR << 16;
3419 return SCSI_RESET_SUCCESS;
3420 }
3421
3422 if (hd->timeouts < -1)
3423 hd->timeouts++;
3424
3425 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
3426 /* Cmd not found in ScsiLookup.
3427 * If found in doneQ, delete from Q.
3428 * Do OS callback.
3429 */
3430 search_doneQ_for_cmd(hd, SCpnt);
3431
3432 SCpnt->result = DID_RESET << 16;
3433 return SCSI_RESET_SUCCESS;
3434 } else {
3435 /* If this command is pended, then timeout/hang occurred
3436 * during DV. Force bus reset by posting command to F/W
3437 * and then following up with the reset request.
3438 */
3439 #ifndef MPTSCSIH_DBG_TIMEOUT
3440 if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
3441 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
3442 post_pendingQ_commands(hd);
3443 }
3444 #endif
3445 }
3446
3447 /*
3448 * Check to see if there's an ABORT_TASK queued for this guy.
3449 * If so, delete.
3450 */
3451 search_taskQ(1, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
3452
3453 /*
3454 * Check to see if there's already a BUS_RESET queued for this guy.
3455 */
3456 mf = search_taskQ(0, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS);
3457 if (mf != NULL) {
3458 dtmprintk((MYIOC_s_INFO_FMT "OldReset:Reset Task PENDING cmd (%p) taskQ depth (%d)\n",
3459 hd->ioc->name, SCpnt, hd->taskQcnt));
3460 return SCSI_RESET_PENDING;
3461 }
3462
3463 // SJR - CHECKME - Can we avoid this here?
3464 // (mpt_HardResetHandler has this check...)
3465 /* If IOC is reloading FW, return PENDING.
3466 */
3467 spin_lock_irqsave(&hd->ioc->diagLock, flags);
3468 if (hd->ioc->diagPending) {
3469 spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
3470 return SCSI_RESET_PENDING;
3471 }
3472 spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
3473
3474 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
3475 /* We are out of message frames!
3476 * Call the reset handler to do a FW reload.
3477 */
3478 printk((KERN_WARNING " Reloading Firmware!!\n"));
3479 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3480 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
3481 }
3482 return SCSI_RESET_PENDING;
3483 }
3484
3485 /*
3486 * Add ourselves to (end of) taskQ.
3487 * Check to see if our _bh is running. If NOT, schedule it.
3488 */
3489 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
3490 Q_ADD_TAIL(&hd->taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
3491 hd->taskQcnt++;
3492 atomic_inc(&mpt_taskQdepth);
3493 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3494
3495
3496 dtmprintk((MYIOC_s_INFO_FMT "OldReset: _bh_handler state (%d) taskQ count (%d)\n",
3497 hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt));
3498
3499 spin_lock_irqsave(&mytaskQ_lock, flags);
3500 /* Save the original SCpnt mf pointer
3501 */
3502 SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx);
3503
3504 mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
3505 mf->u.frame.linkage.argp1 = SCpnt;
3506 mf->u.frame.linkage.argp2 = (void *) hd;
3507
3508 if (! mytaskQ_bh_active) {
3509 mytaskQ_bh_active = 1;
3510 spin_unlock_irqrestore(&mytaskQ_lock, flags);
3511 /*
3512 * Oh how cute, no alloc/free/mgmt needed if we use
3513 * (bottom/unused portion of) MPT request frame.
3514 */
3515 ptaskfoo = (struct mpt_work_struct *) &mptscsih_ptaskfoo;
3516 MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt);
3517
3518 SCHEDULE_TASK(ptaskfoo);
3519 } else {
3520 spin_unlock_irqrestore(&mytaskQ_lock, flags);
3521 }
3522 return SCSI_RESET_PENDING;
3523 }
3524
3525 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3526 /*
3527 * mptscsih_taskmgmt_bh - SCSI task mgmt bottom half handler
3528 * @sc: (unused)
3529 *
3530 * This routine (thread) is active whenever there are any outstanding
3531 * SCSI task management requests for a SCSI host adapter.
3532 * IMPORTANT! This routine is scheduled therefore should never be
3533 * running in ISR context. i.e., it's safe to sleep here.
3534 */
3535 void
mptscsih_taskmgmt_bh(void * sc)3536 mptscsih_taskmgmt_bh(void *sc)
3537 {
3538 MPT_ADAPTER *ioc;
3539 Scsi_Cmnd *SCpnt;
3540 MPT_FRAME_HDR *mf = NULL;
3541 MPT_SCSI_HOST *hd;
3542 u32 ctx2abort = 0;
3543 unsigned long flags;
3544 int scpnt_idx;
3545 int did;
3546 u8 task_type;
3547
3548 spin_lock_irqsave(&mytaskQ_lock, flags);
3549 mytaskQ_bh_active = 1;
3550 spin_unlock_irqrestore(&mytaskQ_lock, flags);
3551
3552 do {
3553 set_current_state(TASK_INTERRUPTIBLE);
3554 schedule_timeout(HZ/4);
3555 did = 0;
3556
3557 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
3558 if (ioc->sh) {
3559 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3560 if (hd == NULL) {
3561 printk(KERN_ERR MYNAM
3562 ": ERROR - TaskMgmt NULL SCSI Host!"
3563 "(ioc=%p, sh=%p hd=%p)\n",
3564 (void *) ioc, (void *) ioc->sh, (void *) hd);
3565 continue;
3566 }
3567
3568 #ifdef MPTSCSIH_DBG_TIMEOUT
3569 if (ioc->timeout_hard == 1) {
3570 mptscsih_TMHandler(hd,
3571 MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
3572 0, 0, 0, 0, CAN_SLEEP);
3573
3574 }
3575 #endif
3576
3577 spin_lock_irqsave(&ioc->FreeQlock, flags);
3578 if (Q_IS_EMPTY(&hd->taskQ)) {
3579 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3580 continue;
3581 }
3582
3583 /* If we ever find a non-empty queue,
3584 * keep the handler alive
3585 */
3586 did++;
3587
3588 /* tmPending is SMP lock-protected */
3589 if (hd->tmPending || hd->tmPtr) {
3590 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3591 continue;
3592 }
3593 hd->tmPending = 1;
3594
3595 /* Process this request
3596 */
3597 mf = hd->taskQ.head;
3598 Q_DEL_ITEM(&mf->u.frame.linkage);
3599 hd->taskQcnt--;
3600 atomic_dec(&mpt_taskQdepth);
3601 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3602
3603 SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1;
3604 if (SCpnt == NULL) {
3605 printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (mf=%p:sc=%p)\n",
3606 (void *) mf, (void *) SCpnt);
3607 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
3608 spin_lock_irqsave(&ioc->FreeQlock, flags);
3609 hd->tmPending = 0;
3610 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3611 continue;
3612 }
3613
3614 /* Get the ScsiLookup index pointer
3615 * from the SC pointer.
3616 */
3617 if (!SCpnt->host_scribble || ((MPT_SCSI_HOST *)SCpnt->host->hostdata != hd)) {
3618 /* The command associated with the
3619 * abort/reset request must have
3620 * completed and this is a stale
3621 * request. We are done.
3622 * Free the current MF and continue.
3623 */
3624 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
3625 spin_lock_irqsave(&ioc->FreeQlock, flags);
3626 hd->tmPending = 0;
3627 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3628 continue;
3629 }
3630
3631 scpnt_idx = MFPTR_2_MPT_INDEX(hd->ioc, SCpnt->host_scribble);
3632 if (scpnt_idx != SCPNT_TO_LOOKUP_IDX(SCpnt)) {
3633 /* Error! this should never happen!!
3634 */
3635 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
3636 spin_lock_irqsave(&ioc->FreeQlock, flags);
3637 hd->tmPending = 0;
3638 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3639 continue;
3640 }
3641
3642 task_type = mf->u.frame.linkage.arg1;
3643 ctx2abort = 0;
3644 if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
3645 MPT_FRAME_HDR *SCpntMf;
3646
3647 /*
3648 * Most important! Set TaskMsgContext to SCpnt's MsgContext!
3649 * (the IO to be ABORT'd)
3650 *
3651 * NOTE: Since we do not byteswap MsgContext, we do not
3652 * swap it here either. It is an opaque cookie to
3653 * the controller, so it does not matter. -DaveM
3654 */
3655 SCpntMf = (MPT_FRAME_HDR *) SCpnt->host_scribble;
3656 ctx2abort = SCpntMf->u.frame.hwhdr.msgctxu.MsgContext;
3657
3658 hd->abortSCpnt = SCpnt;
3659 printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO! (mf=%p:sc=%p)\n",
3660 (void *) mf, (void *) SCpnt);
3661 }
3662
3663 /* The TM handler will allocate a new mf,
3664 * so free the current mf.
3665 */
3666 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
3667 mf = NULL;
3668
3669 #ifndef MPTSCSIH_DBG_TIMEOUT
3670 post_pendingQ_commands(hd);
3671 #endif
3672 if (mptscsih_TMHandler(hd, task_type, SCpnt->channel,
3673 SCpnt->target, SCpnt->lun,
3674 ctx2abort, CAN_SLEEP) < 0) {
3675
3676 /* The TM request failed and the subsequent FW-reload failed!
3677 * Fatal error case.
3678 */
3679 printk(KERN_WARNING MYNAM
3680 ": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)\n", (void *) SCpnt);
3681
3682 if (hd->ScsiLookup[scpnt_idx] != NULL) {
3683 SCpnt->result = DID_SOFT_ERROR << 16;
3684 MPT_HOST_LOCK(flags);
3685 SCpnt->scsi_done(SCpnt);
3686 MPT_HOST_UNLOCK(flags);
3687 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
3688 }
3689 spin_lock_irqsave(&ioc->FreeQlock, flags);
3690 hd->tmPending = 0;
3691 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3692 hd->abortSCpnt = NULL;
3693 }
3694 }
3695 }
3696 if (atomic_read(&mpt_taskQdepth) > 0)
3697 did++;
3698
3699 } while ( did );
3700
3701 spin_lock_irqsave(&mytaskQ_lock, flags);
3702 mytaskQ_bh_active = 0;
3703 spin_unlock_irqrestore(&mytaskQ_lock, flags);
3704
3705 return;
3706 }
3707 #endif /* } */
3708
3709 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3710 /**
3711 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
3712 * @ioc: Pointer to MPT_ADAPTER structure
3713 * @mf: Pointer to SCSI task mgmt request frame
3714 * @mr: Pointer to SCSI task mgmt reply frame
3715 *
3716 * This routine is called from mptbase.c::mpt_interrupt() at the completion
3717 * of any SCSI task management request.
3718 * This routine is registered with the MPT (base) driver at driver
3719 * load/init time via the mpt_register() API call.
3720 *
3721 * Returns 1 indicating alloc'd request frame ptr should be freed.
3722 */
3723 static int
mptscsih_taskmgmt_complete(MPT_ADAPTER * ioc,MPT_FRAME_HDR * mf,MPT_FRAME_HDR * mr)3724 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3725 {
3726 SCSITaskMgmtReply_t *pScsiTmReply;
3727 SCSITaskMgmt_t *pScsiTmReq;
3728 MPT_SCSI_HOST *hd;
3729 unsigned long flags;
3730 u8 tmType = 0;
3731
3732 dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
3733 ioc->name, mf, mr));
3734 if (ioc->sh) {
3735 /* Depending on the thread, a timer is activated for
3736 * the TM request. Delete this timer on completion of TM.
3737 * Decrement count of outstanding TM requests.
3738 */
3739 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
3740 if (hd->tmPtr) {
3741 del_timer(&hd->TMtimer);
3742 }
3743 dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
3744 ioc->name, hd->taskQcnt));
3745 } else {
3746 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
3747 ioc->name));
3748 return 1;
3749 }
3750
3751 if (mr == NULL) {
3752 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
3753 ioc->name, mf));
3754 return 1;
3755 } else {
3756 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
3757 pScsiTmReq = (SCSITaskMgmt_t*)mf;
3758
3759 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
3760 tmType = pScsiTmReq->TaskType;
3761
3762 dtmprintk((KERN_INFO " TaskType = %d, TerminationCount=%d\n",
3763 tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
3764
3765 /* Error? (anything non-zero?) */
3766 if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
3767 u16 iocstatus;
3768
3769 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3770 dtmprintk((KERN_INFO " SCSI TaskMgmt (%d) - Oops!\n", tmType));
3771 dtmprintk((KERN_INFO " IOCStatus = %04xh\n", iocstatus));
3772 dtmprintk((KERN_INFO " IOCLogInfo = %08xh\n",
3773 le32_to_cpu(pScsiTmReply->IOCLogInfo)));
3774
3775 /* clear flags and continue.
3776 */
3777 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
3778 hd->abortSCpnt = NULL;
3779
3780 /* If an internal command is present
3781 * or the TM failed - reload the FW.
3782 * FC FW may respond FAILED to an ABORT
3783 */
3784 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
3785 if ((hd->cmdPtr) ||
3786 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
3787 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
3788 printk((KERN_WARNING
3789 " Firmware Reload FAILED!!\n"));
3790 }
3791 }
3792 }
3793 } else {
3794 dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n"));
3795
3796 #ifndef MPT_SCSI_USE_NEW_EH
3797 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
3798 /* clean taskQ - remove tasks associated with
3799 * completed commands.
3800 */
3801 clean_taskQ(hd);
3802 } else if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
3803 /* If taskQ contains another request
3804 * for this SCpnt, delete this request.
3805 */
3806 search_taskQ_for_cmd(hd->abortSCpnt, hd);
3807 }
3808 #endif
3809 hd->numTMrequests--;
3810 hd->abortSCpnt = NULL;
3811 flush_doneQ(hd);
3812
3813 }
3814 }
3815
3816 #ifndef MPT_SCSI_USE_NEW_EH
3817 /*
3818 * Signal to _bh thread that we finished.
3819 * This IOC can now process another TM command.
3820 */
3821 dtmprintk((MYIOC_s_INFO_FMT "taskmgmt_complete: (=%p) done! Num Failed(%d) Task Count (%d)\n",
3822 ioc->name, mf, hd->numTMrequests, hd->taskQcnt));
3823 #endif
3824 hd->tmPtr = NULL;
3825 spin_lock_irqsave(&ioc->FreeQlock, flags);
3826 hd->tmPending = 0;
3827 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3828 #ifdef MPT_SCSI_USE_NEW_EH
3829 hd->tmState = TM_STATE_NONE;
3830 #endif
3831
3832 return 1;
3833 }
3834
3835 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3836 /*
3837 * This is anyones guess quite frankly.
3838 */
3839 int
mptscsih_bios_param(Disk * disk,kdev_t dev,int * ip)3840 mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip)
3841 {
3842 unsigned capacity = disk->capacity;
3843 int size;
3844
3845 size = capacity;
3846 ip[0] = 64; /* heads */
3847 ip[1] = 32; /* sectors */
3848 if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */
3849 ip[0] = 255; /* heads */
3850 ip[1] = 63; /* sectors */
3851 ip[2] = size / (255 * 63); /* cylinders */
3852 }
3853 return 0;
3854 }
3855
3856 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3857 /*
3858 * OS entry point to adjust the queue_depths on a per-device basis.
3859 * Called once per device the bus scan. Use it to force the queue_depth
3860 * member to 1 if a device does not support Q tags.
3861 */
3862 void
mptscsih_select_queue_depths(struct Scsi_Host * sh,Scsi_Device * sdList)3863 mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList)
3864 {
3865 struct scsi_device *device;
3866 VirtDevice *pTarget;
3867 MPT_SCSI_HOST *hd;
3868
3869 for (device = sdList; device != NULL; device = device->next) {
3870
3871 if (device->host != sh)
3872 continue;
3873
3874 hd = (MPT_SCSI_HOST *) sh->hostdata;
3875 if (hd == NULL)
3876 continue;
3877
3878 if (hd->Targets != NULL) {
3879 if (device->id > sh->max_id) {
3880 /* error case, should never happen */
3881 device->queue_depth = 1;
3882 continue;
3883 } else {
3884 pTarget = hd->Targets[device->id];
3885 }
3886
3887 if (pTarget == NULL) {
3888 /* error case - don't know about this device */
3889 device->queue_depth = 1;
3890 } else {
3891 device->queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
3892 if ( hd->is_spi ) {
3893 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
3894 if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
3895 device->queue_depth = 1;
3896 else if (((pTarget->inq_data[0] & 0x1f) == 0x00) && (pTarget->minSyncFactor <= MPT_ULTRA160 )){
3897 device->queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
3898 } else
3899 device->queue_depth = MPT_SCSI_CMD_PER_DEV_LOW;
3900 } else {
3901 /* error case - No Inq. Data */
3902 device->queue_depth = 1;
3903 }
3904 }
3905 }
3906
3907 if (pTarget != NULL) {
3908 dprintk((MYIOC_s_INFO_FMT
3909 "scsi%d: Id=%d Lun=%d: Queue depth=%d tflags=%x\n",
3910 hd->ioc->name, device->id, pTarget->target_id, device->lun, device->queue_depth, pTarget->tflags));
3911
3912 dprintk((MYIOC_s_INFO_FMT
3913 "Id = %d, sync factor = %x\n",
3914 hd->ioc->name, pTarget->target_id,
3915 pTarget->minSyncFactor));
3916 }
3917 }
3918 }
3919 }
3920
3921 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3922 /*
3923 * Private routines...
3924 */
3925
3926 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3927 /* Utility function to copy sense data from the scsi_cmnd buffer
3928 * to the FC and SCSI target structures.
3929 *
3930 */
3931 static void
copy_sense_data(Scsi_Cmnd * sc,MPT_SCSI_HOST * hd,MPT_FRAME_HDR * mf,SCSIIOReply_t * pScsiReply)3932 copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
3933 {
3934 VirtDevice *target;
3935 SCSIIORequest_t *pReq;
3936 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
3937 int index;
3938 char devFoo[96];
3939 IO_Info_t thisIo;
3940
3941 /* Get target structure
3942 */
3943 pReq = (SCSIIORequest_t *) mf;
3944 index = (int) pReq->TargetID;
3945 target = hd->Targets[index];
3946 if (hd->is_multipath && sc->device->hostdata)
3947 target = (VirtDevice *) sc->device->hostdata;
3948
3949 if (sense_count) {
3950 u8 *sense_data;
3951 int req_index;
3952
3953 /* Copy the sense received into the scsi command block. */
3954 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3955 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
3956 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
3957
3958 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
3959 */
3960 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
3961 if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
3962 int idx;
3963 MPT_ADAPTER *ioc = hd->ioc;
3964
3965 idx = ioc->eventContext % ioc->eventLogSize;
3966 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
3967 ioc->events[idx].eventContext = ioc->eventContext;
3968
3969 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
3970 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
3971 (pReq->Bus << 8) || pReq->TargetID;
3972
3973 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
3974
3975 ioc->eventContext++;
3976 }
3977 }
3978
3979 /* Print an error report for the user.
3980 */
3981 thisIo.cdbPtr = sc->cmnd;
3982 thisIo.sensePtr = sc->sense_buffer;
3983 thisIo.SCSIStatus = pScsiReply->SCSIStatus;
3984 thisIo.DoDisplay = 1;
3985 if (hd->is_multipath)
3986 sprintf(devFoo, "%d:%d:%d",
3987 hd->ioc->id,
3988 pReq->TargetID,
3989 pReq->LUN[1]);
3990 else
3991 sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->target, sc->lun);
3992 thisIo.DevIDStr = devFoo;
3993 /* fubar */
3994 thisIo.dataPtr = NULL;
3995 thisIo.inqPtr = NULL;
3996 if (sc->device) {
3997 thisIo.inqPtr = sc->device->vendor-8; /* FIXME!!! */
3998 }
3999 (void) mpt_ScsiHost_ErrorReport(&thisIo);
4000
4001 } else {
4002 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
4003 hd->ioc->name));
4004 }
4005
4006 return;
4007 }
4008
4009 static u32
SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd * sc)4010 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
4011 {
4012 MPT_SCSI_HOST *hd;
4013 int i;
4014
4015 hd = (MPT_SCSI_HOST *) sc->host->hostdata;
4016
4017 for (i = 0; i < hd->ioc->req_depth; i++) {
4018 if (hd->ScsiLookup[i] == sc) {
4019 return i;
4020 }
4021 }
4022
4023 return -1;
4024 }
4025
4026 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4027
4028 /* see mptscsih.h */
4029
4030 #ifdef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS
4031 static Scsi_Host_Template driver_template = MPT_SCSIHOST;
4032 # include "../../scsi/scsi_module.c"
4033 #endif
4034
4035 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4036 /* Search the pendingQ for a command with specific index.
4037 * If found, delete and return mf pointer
4038 * If not found, return NULL
4039 */
4040 static MPT_FRAME_HDR *
mptscsih_search_pendingQ(MPT_SCSI_HOST * hd,int scpnt_idx)4041 mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx)
4042 {
4043 unsigned long flags;
4044 MPT_DONE_Q *buffer;
4045 MPT_FRAME_HDR *mf = NULL;
4046 MPT_FRAME_HDR *cmdMfPtr;
4047
4048 ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
4049 cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
4050 spin_lock_irqsave(&hd->freedoneQlock, flags);
4051 if (!Q_IS_EMPTY(&hd->pendingQ)) {
4052 buffer = hd->pendingQ.head;
4053 do {
4054 mf = (MPT_FRAME_HDR *) buffer->argp;
4055 if (mf == cmdMfPtr) {
4056 Q_DEL_ITEM(buffer);
4057
4058 /* clear the arg pointer
4059 */
4060 buffer->argp = NULL;
4061
4062 /* Add to the freeQ
4063 */
4064 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
4065 break;
4066 }
4067 mf = NULL;
4068 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ);
4069 }
4070 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
4071 ddvtprintk((" ...return %p\n", mf));
4072 return mf;
4073 }
4074
4075 /* Post all commands on the pendingQ to the FW.
4076 * Lock Q when deleting/adding members
4077 * Lock io_request_lock for OS callback.
4078 */
4079 static void
post_pendingQ_commands(MPT_SCSI_HOST * hd)4080 post_pendingQ_commands(MPT_SCSI_HOST *hd)
4081 {
4082 MPT_FRAME_HDR *mf;
4083 MPT_DONE_Q *buffer;
4084 unsigned long flags;
4085
4086 /* Flush the pendingQ.
4087 */
4088 ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
4089 while (1) {
4090 spin_lock_irqsave(&hd->freedoneQlock, flags);
4091 if (Q_IS_EMPTY(&hd->pendingQ)) {
4092 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
4093 break;
4094 }
4095
4096 buffer = hd->pendingQ.head;
4097 /* Delete from Q
4098 */
4099 Q_DEL_ITEM(buffer);
4100
4101 mf = (MPT_FRAME_HDR *) buffer->argp;
4102 buffer->argp = NULL;
4103
4104 /* Add to the freeQ
4105 */
4106 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
4107 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
4108
4109 if (!mf) {
4110 /* This should never happen */
4111 printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
4112 continue;
4113 }
4114
4115 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
4116
4117 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
4118 {
4119 u16 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4120 Scsi_Cmnd *sc = hd->ScsiLookup[req_idx];
4121 printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
4122 hd->ioc->name, sc, req_idx, mf);
4123 }
4124 #endif
4125 }
4126
4127 return;
4128 }
4129
4130 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4131 static int
mptscsih_ioc_reset(MPT_ADAPTER * ioc,int reset_phase)4132 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
4133 {
4134 MPT_SCSI_HOST *hd;
4135 unsigned long flags;
4136
4137 dtmprintk((KERN_WARNING MYNAM
4138 ": IOC %s_reset routed to SCSI host driver!\n",
4139 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
4140 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
4141
4142 /* If a FW reload request arrives after base installed but
4143 * before all scsi hosts have been attached, then an alt_ioc
4144 * may have a NULL sh pointer.
4145 */
4146 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
4147 return 0;
4148 else
4149 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4150
4151 if (reset_phase == MPT_IOC_SETUP_RESET) {
4152 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
4153 /* Clean Up:
4154 * 1. Set Hard Reset Pending Flag
4155 * All new commands go to doneQ
4156 */
4157 hd->resetPending = 1;
4158
4159 /* 2. Reset timeouts on all running commands
4160 */
4161 mptscsih_reset_timeouts (hd);
4162
4163 } else if (reset_phase == MPT_IOC_PRE_RESET) {
4164 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
4165
4166 /* 2. Flush running commands
4167 * Clean ScsiLookup (and associated memory)
4168 * AND clean mytaskQ
4169 */
4170
4171 /* 2b. Reply to OS all known outstanding I/O commands.
4172 */
4173 mptscsih_flush_running_cmds(hd);
4174
4175 /* 2c. If there was an internal command that
4176 * has not completed, configuration or io request,
4177 * free these resources.
4178 */
4179 if (hd->cmdPtr) {
4180 del_timer(&hd->timer);
4181 mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr);
4182 }
4183
4184 /* 2d. If a task management has not completed,
4185 * free resources associated with this request.
4186 */
4187 if (hd->tmPtr) {
4188 del_timer(&hd->TMtimer);
4189 mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr);
4190 }
4191
4192 #ifndef MPT_SCSI_USE_NEW_EH
4193 /* 2e. Delete all commands on taskQ
4194 * Should be superfluous - as this taskQ should
4195 * be empty.
4196 */
4197 clean_taskQ(hd);
4198 #endif
4199
4200 #ifdef MPTSCSIH_DBG_TIMEOUT
4201 ioc->timeout_hard = 0;
4202 #endif
4203
4204 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
4205 } else {
4206 ScsiCfgData *pSpi;
4207
4208 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
4209
4210 /* Once a FW reload begins, all new OS commands are
4211 * redirected to the doneQ w/ a reset status.
4212 * Init all control structures.
4213 */
4214
4215 /* ScsiLookup initialization
4216 */
4217 {
4218 int ii;
4219 for (ii=0; ii < hd->ioc->req_depth; ii++)
4220 hd->ScsiLookup[ii] = NULL;
4221 }
4222
4223 /* 2. Chain Buffer initialization
4224 */
4225 mptscsih_initChainBuffers(hd, 0);
4226
4227 /* 3. tmPtr clear
4228 */
4229 if (hd->tmPtr) {
4230 hd->tmPtr = NULL;
4231 }
4232
4233 /* 4. Renegotiate to all devices, if SCSI
4234 */
4235 if (hd->is_spi)
4236 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
4237
4238 /* 5. Enable new commands to be posted
4239 */
4240 spin_lock_irqsave(&ioc->FreeQlock, flags);
4241 hd->tmPending = 0;
4242 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4243 hd->resetPending = 0;
4244 hd->numTMrequests = 0;
4245 #ifdef MPT_SCSI_USE_NEW_EH
4246 hd->tmState = TM_STATE_NONE;
4247 #endif
4248
4249 /* 6. If there was an internal command,
4250 * wake this process up.
4251 */
4252 if (hd->cmdPtr) {
4253 /*
4254 * Wake up the original calling thread
4255 */
4256 hd->pLocal = &hd->localReply;
4257 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
4258 scandv_wait_done = 1;
4259 wake_up(&scandv_waitq);
4260 hd->cmdPtr = NULL;
4261 }
4262
4263 /* 7. Flush doneQ
4264 */
4265 flush_doneQ(hd);
4266
4267 /* 8. Set flag to force DV and re-read IOC Page 3
4268 */
4269 if (hd->is_spi) {
4270 pSpi = &ioc->spi_data;
4271 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
4272 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
4273 }
4274
4275 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
4276 }
4277
4278 return 1; /* currently means nothing really */
4279 }
4280
4281 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4282 static int
mptscsih_event_process(MPT_ADAPTER * ioc,EventNotificationReply_t * pEvReply)4283 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
4284 {
4285 MPT_SCSI_HOST *hd;
4286 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
4287
4288 dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
4289 ioc->name, event));
4290
4291 switch (event) {
4292 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
4293 /* FIXME! */
4294 break;
4295 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
4296 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
4297 hd = NULL;
4298 if (ioc->sh) {
4299 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4300 if (hd && (hd->is_spi) && (hd->soft_resets < -1))
4301 hd->soft_resets++;
4302 }
4303 break;
4304 case MPI_EVENT_LOGOUT: /* 09 */
4305 /* FIXME! */
4306 break;
4307
4308 /*
4309 * CHECKME! Don't think we need to do
4310 * anything for these, but...
4311 */
4312 case MPI_EVENT_RESCAN: /* 06 */
4313 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
4314 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
4315 /*
4316 * CHECKME! Falling thru...
4317 */
4318 break;
4319
4320 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
4321 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
4322 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
4323 * if DV disabled. Need to check for target mode.
4324 */
4325 hd = NULL;
4326 if (ioc->sh)
4327 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4328
4329 if (hd && (hd->is_spi) && (hd->negoNvram == 0)) {
4330 ScsiCfgData *pSpi;
4331 Ioc3PhysDisk_t *pPDisk;
4332 int numPDisk;
4333 u8 reason;
4334 u8 physDiskNum;
4335
4336 reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
4337 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4338 /* New or replaced disk.
4339 * Set DV flag and schedule DV.
4340 */
4341 pSpi = &ioc->spi_data;
4342 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
4343 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
4344 if (pSpi->pIocPg3) {
4345 pPDisk = pSpi->pIocPg3->PhysDisk;
4346 numPDisk =pSpi->pIocPg3->NumPhysDisks;
4347
4348 while (numPDisk) {
4349 if (physDiskNum == pPDisk->PhysDiskNum) {
4350 pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
4351 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
4352 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
4353 break;
4354 }
4355 pPDisk++;
4356 numPDisk--;
4357 }
4358
4359 if (numPDisk == 0) {
4360 /* The physical disk that needs DV was not found
4361 * in the stored IOC Page 3. The driver must reload
4362 * this page. DV routine will set the NEED_DV flag for
4363 * all phys disks that have DV_NOT_DONE set.
4364 */
4365 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
4366 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
4367 }
4368 }
4369 }
4370 }
4371 #endif
4372
4373 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
4374 printk("Raid Event RF: ");
4375 {
4376 u32 *m = (u32 *)pEvReply;
4377 int ii;
4378 int n = (int)pEvReply->MsgLength;
4379 for (ii=6; ii < n; ii++)
4380 printk(" %08x", le32_to_cpu(m[ii]));
4381 printk("\n");
4382 }
4383 #endif
4384 break;
4385
4386 case MPI_EVENT_NONE: /* 00 */
4387 case MPI_EVENT_LOG_DATA: /* 01 */
4388 case MPI_EVENT_STATE_CHANGE: /* 02 */
4389 case MPI_EVENT_EVENT_CHANGE: /* 0A */
4390 default:
4391 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
4392 break;
4393 }
4394
4395 return 1; /* currently means nothing really */
4396 }
4397
4398 #if 0 /* { */
4399 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4400 /*
4401 * scsiherr.c - Fusion MPT SCSI Host driver error handling/reporting.
4402 *
4403 * drivers/message/fusion/scsiherr.c
4404 */
4405
4406 //extern const char **mpt_ScsiOpcodesPtr; /* needed by mptscsih.c */
4407 //extern ASCQ_Table_t *mpt_ASCQ_TablePtr;
4408 //extern int mpt_ASCQ_TableSz;
4409
4410 #define MYNAM "mptscsih"
4411
4412 #endif /* } */
4413
4414 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4415 /*
4416 * Private data...
4417 */
4418 static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
4419
4420 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4421 /* old symsense.c stuff... */
4422 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4423 /*
4424 * Private data...
4425 * To protect ourselves against those that would pass us bogus pointers
4426 */
4427 static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
4428 = { 0x1F, 0x00, 0x00, 0x00,
4429 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
4433 static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
4434 = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
4435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4436 0x00, 0x00 };
4437 static u8 dummyCDB[16]
4438 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
4440 static u8 dummyScsiData[16]
4441 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
4443
4444 #if 0
4445 static const char *PeripheralDeviceTypeString[32] = {
4446 "Direct-access", /* 00h */
4447 "Sequential-access", /* 01h */
4448 "Printer", /* 02h */
4449 "Processor", /* 03h */
4450 /*"Write-Once-Read-Multiple",*/ /* 04h */
4451 "WORM", /* 04h */
4452 "CD-ROM", /* 05h */
4453 "Scanner", /* 06h */
4454 "Optical memory", /* 07h */
4455 "Media Changer", /* 08h */
4456 "Communications", /* 09h */
4457 "(Graphics arts pre-press)", /* 0Ah */
4458 "(Graphics arts pre-press)", /* 0Bh */
4459 "Array controller", /* 0Ch */
4460 "Enclosure services", /* 0Dh */
4461 "Simplified direct-access", /* 0Eh */
4462 "Reserved-0Fh", /* 0Fh */
4463 "Reserved-10h", /* 10h */
4464 "Reserved-11h", /* 11h */
4465 "Reserved-12h", /* 12h */
4466 "Reserved-13h", /* 13h */
4467 "Reserved-14h", /* 14h */
4468 "Reserved-15h", /* 15h */
4469 "Reserved-16h", /* 16h */
4470 "Reserved-17h", /* 17h */
4471 "Reserved-18h", /* 18h */
4472 "Reserved-19h", /* 19h */
4473 "Reserved-1Ah", /* 1Ah */
4474 "Reserved-1Bh", /* 1Bh */
4475 "Reserved-1Ch", /* 1Ch */
4476 "Reserved-1Dh", /* 1Dh */
4477 "Reserved-1Eh", /* 1Eh */
4478 "Unknown" /* 1Fh */
4479 };
4480 #endif
4481
4482 static char *ScsiStatusString[] = {
4483 "GOOD", /* 00h */
4484 NULL, /* 01h */
4485 "CHECK CONDITION", /* 02h */
4486 NULL, /* 03h */
4487 "CONDITION MET", /* 04h */
4488 NULL, /* 05h */
4489 NULL, /* 06h */
4490 NULL, /* 07h */
4491 "BUSY", /* 08h */
4492 NULL, /* 09h */
4493 NULL, /* 0Ah */
4494 NULL, /* 0Bh */
4495 NULL, /* 0Ch */
4496 NULL, /* 0Dh */
4497 NULL, /* 0Eh */
4498 NULL, /* 0Fh */
4499 "INTERMEDIATE", /* 10h */
4500 NULL, /* 11h */
4501 NULL, /* 12h */
4502 NULL, /* 13h */
4503 "INTERMEDIATE-CONDITION MET", /* 14h */
4504 NULL, /* 15h */
4505 NULL, /* 16h */
4506 NULL, /* 17h */
4507 "RESERVATION CONFLICT", /* 18h */
4508 NULL, /* 19h */
4509 NULL, /* 1Ah */
4510 NULL, /* 1Bh */
4511 NULL, /* 1Ch */
4512 NULL, /* 1Dh */
4513 NULL, /* 1Eh */
4514 NULL, /* 1Fh */
4515 NULL, /* 20h */
4516 NULL, /* 21h */
4517 "COMMAND TERMINATED", /* 22h */
4518 NULL, /* 23h */
4519 NULL, /* 24h */
4520 NULL, /* 25h */
4521 NULL, /* 26h */
4522 NULL, /* 27h */
4523 "TASK SET FULL", /* 28h */
4524 NULL, /* 29h */
4525 NULL, /* 2Ah */
4526 NULL, /* 2Bh */
4527 NULL, /* 2Ch */
4528 NULL, /* 2Dh */
4529 NULL, /* 2Eh */
4530 NULL, /* 2Fh */
4531 "ACA ACTIVE", /* 30h */
4532 NULL
4533 };
4534
4535 static const char *ScsiCommonOpString[] = {
4536 "TEST UNIT READY", /* 00h */
4537 "REZERO UNIT (REWIND)", /* 01h */
4538 NULL, /* 02h */
4539 "REQUEST_SENSE", /* 03h */
4540 "FORMAT UNIT (MEDIUM)", /* 04h */
4541 "READ BLOCK LIMITS", /* 05h */
4542 NULL, /* 06h */
4543 "REASSIGN BLOCKS", /* 07h */
4544 "READ(6)", /* 08h */
4545 NULL, /* 09h */
4546 "WRITE(6)", /* 0Ah */
4547 "SEEK(6)", /* 0Bh */
4548 NULL, /* 0Ch */
4549 NULL, /* 0Dh */
4550 NULL, /* 0Eh */
4551 "READ REVERSE", /* 0Fh */
4552 "WRITE_FILEMARKS", /* 10h */
4553 "SPACE(6)", /* 11h */
4554 "INQUIRY", /* 12h */
4555 NULL
4556 };
4557
4558 static const char *SenseKeyString[] = {
4559 "NO SENSE", /* 0h */
4560 "RECOVERED ERROR", /* 1h */
4561 "NOT READY", /* 2h */
4562 "MEDIUM ERROR", /* 3h */
4563 "HARDWARE ERROR", /* 4h */
4564 "ILLEGAL REQUEST", /* 5h */
4565 "UNIT ATTENTION", /* 6h */
4566 "DATA PROTECT", /* 7h */
4567 "BLANK CHECK", /* 8h */
4568 "VENDOR-SPECIFIC", /* 9h */
4569 "ABORTED COPY", /* Ah */
4570 "ABORTED COMMAND", /* Bh */
4571 "EQUAL (obsolete)", /* Ch */
4572 "VOLUME OVERFLOW", /* Dh */
4573 "MISCOMPARE", /* Eh */
4574 "RESERVED", /* Fh */
4575 NULL
4576 };
4577
4578 #define SPECIAL_ASCQ(c,q) \
4579 (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
4580
4581 #if 0
4582 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4583 /*
4584 * Sense_Key_Specific() - If Sense_Key_Specific_Valid bit is set,
4585 * then print additional information via
4586 * a call to SDMS_SystemAlert().
4587 */
4588 static void Sense_Key_Specific(IO_Info_t *ioop, char *msg1)
4589 {
4590 u8 *sd;
4591 u8 BadValue;
4592 u8 SenseKey;
4593 int Offset;
4594 int len = strlen(msg1);
4595
4596 sd = ioop->sensePtr;
4597 if (SD_Additional_Sense_Length(sd) < 8)
4598 return;
4599
4600 SenseKey = SD_Sense_Key(sd);
4601
4602 if (SD_Sense_Key_Specific_Valid(sd)) {
4603 if (SenseKey == SK_ILLEGAL_REQUEST) {
4604 Offset = SD_Bad_Byte(sd);
4605 if (SD_Was_Illegal_Request(sd)) {
4606 BadValue = ioop->cdbPtr[Offset];
4607 len += sprintf(msg1+len, "\n Illegal CDB value=%02Xh found at CDB ",
4608 BadValue);
4609 } else {
4610 BadValue = ioop->dataPtr[Offset];
4611 len += sprintf(msg1+len, "\n Illegal DATA value=%02Xh found at DATA ",
4612 BadValue);
4613 }
4614 len += sprintf(msg1+len, "byte=%02Xh", Offset);
4615 if (SD_SKS_Bit_Pointer_Valid(sd))
4616 len += sprintf(msg1+len, "/bit=%1Xh", SD_SKS_Bit_Pointer(sd));
4617 } else if ((SenseKey == SK_RECOVERED_ERROR) ||
4618 (SenseKey == SK_HARDWARE_ERROR) ||
4619 (SenseKey == SK_MEDIUM_ERROR)) {
4620 len += sprintf(msg1+len, "\n Recovery algorithm Actual_Retry_Count=%02Xh",
4621 SD_Actual_Retry_Count(sd));
4622 }
4623 }
4624 }
4625 #endif
4626
4627 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
dump_cdb(char * foo,unsigned char * cdb)4628 static int dump_cdb(char *foo, unsigned char *cdb)
4629 {
4630 int i, grpCode, cdbLen;
4631 int l = 0;
4632
4633 grpCode = cdb[0] >> 5;
4634 if (grpCode < 1)
4635 cdbLen = 6;
4636 else if (grpCode < 3)
4637 cdbLen = 10;
4638 else if (grpCode == 5)
4639 cdbLen = 12;
4640 else
4641 cdbLen = 16;
4642
4643 for (i=0; i < cdbLen; i++)
4644 l += sprintf(foo+l, " %02X", cdb[i]);
4645
4646 return l;
4647 }
4648
4649 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4650 #if 0
4651 static int dump_sd(char *foo, unsigned char *sd)
4652 {
4653 int snsLen = 8 + SD_Additional_Sense_Length(sd);
4654 int l = 0;
4655 int i;
4656
4657 for (i=0; i < MIN(snsLen,18); i++)
4658 l += sprintf(foo+l, " %02X", sd[i]);
4659 l += sprintf(foo+l, "%s", snsLen>18 ? " ..." : "");
4660
4661 return l;
4662 }
4663 #endif
4664
4665 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4666 /* Do ASC/ASCQ lookup/grindage to English readable string(s) */
ascq_set_strings_4max(u8 ASC,u8 ASCQ,const char ** s1,const char ** s2,const char ** s3,const char ** s4)4667 static const char * ascq_set_strings_4max(
4668 u8 ASC, u8 ASCQ,
4669 const char **s1, const char **s2, const char **s3, const char **s4)
4670 {
4671 static const char *asc_04_part1_string = "LOGICAL UNIT ";
4672 static const char *asc_04_part2a_string = "NOT READY, ";
4673 static const char *asc_04_part2b_string = "IS ";
4674 static const char *asc_04_ascq_NN_part3_strings[] = { /* ASC ASCQ (hex) */
4675 "CAUSE NOT REPORTABLE", /* 04 00 */
4676 "IN PROCESS OF BECOMING READY", /* 04 01 */
4677 "INITIALIZING CMD. REQUIRED", /* 04 02 */
4678 "MANUAL INTERVENTION REQUIRED", /* 04 03 */
4679 /* Add " IN PROGRESS" to all the following... */
4680 "FORMAT", /* 04 04 */
4681 "REBUILD", /* 04 05 */
4682 "RECALCULATION", /* 04 06 */
4683 "OPERATION", /* 04 07 */
4684 "LONG WRITE", /* 04 08 */
4685 "SELF-TEST", /* 04 09 */
4686 NULL
4687 };
4688 static char *asc_04_part4_string = " IN PROGRESS";
4689
4690 static char *asc_29_ascq_NN_strings[] = { /* ASC ASCQ (hex) */
4691 "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED", /* 29 00 */
4692 "POWER ON OCCURRED", /* 29 01 */
4693 "SCSI BUS RESET OCCURRED", /* 29 02 */
4694 "BUS DEVICE RESET FUNCTION OCCURRED", /* 29 03 */
4695 "DEVICE INTERNAL RESET", /* 29 04 */
4696 "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED", /* 29 05 */
4697 "TRANSCEIVER MODE CHANGED TO LVD", /* 29 06 */
4698 NULL
4699 };
4700 static char *ascq_vendor_uniq = "(Vendor Unique)";
4701 static char *ascq_noone = "(no matching ASC/ASCQ description found)";
4702 int idx;
4703
4704 *s1 = *s2 = *s3 = *s4 = ""; /* set'em all to the empty "" string */
4705
4706 /* CHECKME! Need lock/sem?
4707 * Update and examine for isense module presense.
4708 */
4709 mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
4710
4711 if (mptscsih_ASCQ_TablePtr == NULL) {
4712 /* 2nd chances... */
4713 if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
4714 *s1 = asc_04_part1_string;
4715 *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
4716 *s3 = asc_04_ascq_NN_part3_strings[ASCQ];
4717 /* check for " IN PROGRESS" ones */
4718 if (ASCQ >= 0x04)
4719 *s4 = asc_04_part4_string;
4720 } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
4721 *s1 = asc_29_ascq_NN_strings[ASCQ];
4722 /*
4723 * Else { leave all *s[1-4] values pointing to the empty "" string }
4724 */
4725 return *s1;
4726 }
4727
4728 /*
4729 * Need to check ASC here; if it is "special," then
4730 * the ASCQ is variable, and indicates failed component number.
4731 * We must treat the ASCQ as a "don't care" while searching the
4732 * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
4733 * on when we actually need to identify the failed component.
4734 */
4735 if (SPECIAL_ASCQ(ASC,ASCQ))
4736 ASCQ = 0xFF;
4737
4738 /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
4739 for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
4740 if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) {
4741 *s1 = mptscsih_ASCQ_TablePtr[idx].Description;
4742 return *s1;
4743 }
4744
4745 if ((ASC >= 0x80) || (ASCQ >= 0x80))
4746 *s1 = ascq_vendor_uniq;
4747 else
4748 *s1 = ascq_noone;
4749
4750 return *s1;
4751 }
4752
4753 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4754 /*
4755 * SCSI Information Report; desired output format...
4756 *---
4757 SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION)
4758 Key=6h (UNIT ATTENTION); FRU=03h
4759 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4760 CDB: 00 00 00 00 00 00 - TestUnitReady
4761 *---
4762 */
4763 /*
4764 * SCSI Error Report; desired output format...
4765 *---
4766 SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
4767 SCSI_Status=02h (CHECK CONDITION)
4768 Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
4769 SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
4770 SenseKey=6h (UNIT ATTENTION); FRU=03h
4771 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4772 *---
4773 */
4774
mpt_ScsiHost_ErrorReport(IO_Info_t * ioop)4775 int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
4776 {
4777 char foo[512];
4778 char buf2[32];
4779 char *statstr;
4780 const char *opstr;
4781 int sk = SD_Sense_Key(ioop->sensePtr);
4782 const char *skstr = SenseKeyString[sk];
4783 unsigned char asc = SD_ASC(ioop->sensePtr);
4784 unsigned char ascq = SD_ASCQ(ioop->sensePtr);
4785 int l;
4786
4787 /* Change the error logging to only report errors on
4788 * read and write commands. Ignore errors on other commands.
4789 * Should this be configurable via proc?
4790 */
4791 switch (ioop->cdbPtr[0]) {
4792 case READ_6:
4793 case WRITE_6:
4794 case READ_10:
4795 case WRITE_10:
4796 case READ_12:
4797 case WRITE_12:
4798 break;
4799 default:
4800 return 0;
4801 }
4802
4803 /*
4804 * More quiet mode.
4805 * Filter out common, repetitive, warning-type errors... like:
4806 * POWER ON (06,29/00 or 06,29/01),
4807 * SPINNING UP (02,04/01),
4808 * LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
4809 */
4810 if (sk == SK_NO_SENSE) {
4811 return 0;
4812 }
4813
4814 if ( (sk==SK_UNIT_ATTENTION && asc==0x29 && (ascq==0x00 || ascq==0x01))
4815 || (sk==SK_NOT_READY && asc==0x04 && (ascq==0x01 || ascq==0x02))
4816 || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
4817 )
4818 {
4819 /* Do nothing! */
4820 return 0;
4821 }
4822
4823 /* Prevent the system from continually writing to the log
4824 * if a medium is not found: 02 3A 00
4825 * Changer issues: TUR, Read Capacity, Table of Contents continually
4826 */
4827 if (sk==SK_NOT_READY && asc==0x3A) {
4828 if (ioop->cdbPtr == NULL) {
4829 return 0;
4830 } else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
4831 (ioop->cdbPtr[0] == CMD_ReadCapacity) ||
4832 (ioop->cdbPtr[0] == 0x43)) {
4833 return 0;
4834 }
4835 }
4836 if (sk==SK_UNIT_ATTENTION) {
4837 if (ioop->cdbPtr == NULL)
4838 return 0;
4839 else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
4840 return 0;
4841 }
4842
4843 /*
4844 * Protect ourselves...
4845 */
4846 if (ioop->cdbPtr == NULL)
4847 ioop->cdbPtr = dummyCDB;
4848 if (ioop->sensePtr == NULL)
4849 ioop->sensePtr = dummySenseData;
4850 if (ioop->inqPtr == NULL)
4851 ioop->inqPtr = dummyInqData;
4852 if (ioop->dataPtr == NULL)
4853 ioop->dataPtr = dummyScsiData;
4854
4855 statstr = NULL;
4856 if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
4857 ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
4858 (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
4859 statstr = buf2;
4860 }
4861
4862 opstr = NULL;
4863 if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
4864 opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
4865 else if (mpt_ScsiOpcodesPtr)
4866 opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
4867
4868 l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n",
4869 ioop->DevIDStr,
4870 ioop->SCSIStatus,
4871 statstr);
4872 l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
4873 sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
4874 {
4875 const char *x1, *x2, *x3, *x4;
4876 x1 = x2 = x3 = x4 = "";
4877 x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
4878 if (x1 != NULL) {
4879 if (x1[0] != '(')
4880 l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
4881 else
4882 l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
4883 }
4884 }
4885 l += sprintf(foo+l, "\n CDB:");
4886 l += dump_cdb(foo+l, ioop->cdbPtr);
4887 if (opstr)
4888 l += sprintf(foo+l, " - \"%s\"", opstr);
4889 l += sprintf(foo+l, "\n");
4890
4891 PrintF(("%s\n", foo));
4892
4893 return l;
4894 }
4895
4896 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4897
4898 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4899 /*
4900 * mptscsih_initTarget - Target, LUN alloc/free functionality.
4901 * @hd: Pointer to MPT_SCSI_HOST structure
4902 * @bus_id: Bus number (?)
4903 * @target_id: SCSI target id
4904 * @lun: SCSI LUN id
4905 * @data: Pointer to data
4906 * @dlen: Number of INQUIRY bytes
4907 *
4908 * NOTE: It's only SAFE to call this routine if data points to
4909 * sane & valid STANDARD INQUIRY data!
4910 *
4911 * Allocate and initialize memory for this target.
4912 * Save inquiry data.
4913 *
4914 */
4915 static void
mptscsih_initTarget(MPT_SCSI_HOST * hd,int bus_id,int target_id,u8 lun,char * data,int dlen)4916 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
4917 {
4918 int indexed_lun, lun_index;
4919 VirtDevice *vdev;
4920 char data_56;
4921
4922 dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
4923 hd->ioc->name, bus_id, target_id, lun, hd));
4924
4925 /* Is LUN supported? If so, upper 3 bits will be 0
4926 * in first byte of inquiry data.
4927 */
4928 if (data[0] & 0xe0)
4929 return;
4930
4931 if ((vdev = hd->Targets[target_id]) == NULL) {
4932 if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
4933 printk(MYIOC_s_ERR_FMT "initTarget kmalloc(%d) FAILED!\n",
4934 hd->ioc->name, (int)sizeof(VirtDevice));
4935 return;
4936 }
4937 memset(vdev, 0, sizeof(VirtDevice));
4938 rwlock_init(&vdev->VdevLock);
4939 Q_INIT(&vdev->WaitQ, void);
4940 Q_INIT(&vdev->SentQ, void);
4941 Q_INIT(&vdev->DoneQ, void);
4942 vdev->tflags = 0;
4943 vdev->ioc_id = hd->ioc->id;
4944 vdev->target_id = target_id;
4945 vdev->bus_id = bus_id;
4946
4947 hd->Targets[target_id] = vdev;
4948 dprintk((KERN_INFO " *NEW* Target structure (id %d) @ %p\n",
4949 target_id, vdev));
4950 }
4951
4952 lun_index = (lun >> 5); /* 32 luns per lun_index */
4953 indexed_lun = (lun % 32);
4954 vdev->luns[lun_index] |= (1 << indexed_lun);
4955
4956 vdev->raidVolume = 0;
4957 if (hd->is_spi) {
4958 if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
4959 vdev->raidVolume = 1;
4960 ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
4961 }
4962 }
4963
4964 if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
4965 if ( dlen > 8 ) {
4966 memcpy (vdev->inq_data, data, 8);
4967 } else {
4968 memcpy (vdev->inq_data, data, dlen);
4969 }
4970 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4971
4972 /* If LUN 0, tape and have not done DV, set the DV flag.
4973 */
4974 if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
4975 ScsiCfgData *pSpi = &hd->ioc->spi_data;
4976 if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
4977 pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
4978 }
4979
4980 if ( (data[0] == SCSI_TYPE_PROC) &&
4981 !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
4982 if ( dlen > 49 ) {
4983 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4984 if ( data[44] == 'S' &&
4985 data[45] == 'A' &&
4986 data[46] == 'F' &&
4987 data[47] == '-' &&
4988 data[48] == 'T' &&
4989 data[49] == 'E' ) {
4990 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4991 mptscsih_writeIOCPage4(hd, target_id, bus_id);
4992 }
4993 } else {
4994 /* Treat all Processors as SAF-TE if
4995 * command line option is set */
4996 if ( hd->ioc->spi_data.Saf_Te ) {
4997 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4998 mptscsih_writeIOCPage4(hd, target_id, bus_id);
4999 }
5000 }
5001 }
5002
5003 data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
5004 if (dlen > 56) {
5005 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
5006 /* Update the target capabilities
5007 */
5008 data_56 = data[56];
5009 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
5010 }
5011 }
5012 mptscsih_setTargetNegoParms(hd, vdev, data_56);
5013 }
5014
5015 dprintk((KERN_INFO " target = %p\n", vdev));
5016 return;
5017 }
5018
5019 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5020 /*
5021 * Update the target negotiation parameters based on the
5022 * the Inquiry data, adapter capabilities, and NVRAM settings.
5023 *
5024 */
mptscsih_setTargetNegoParms(MPT_SCSI_HOST * hd,VirtDevice * target,char byte56)5025 void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
5026 {
5027 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
5028 int id = (int) target->target_id;
5029 int nvram;
5030 char canQ = 0;
5031 VirtDevice *vdev;
5032 int ii;
5033 u8 width = MPT_NARROW;
5034 u8 factor = MPT_ASYNC;
5035 u8 offset = 0;
5036 u8 version, nfactor;
5037 u8 noQas = 1;
5038
5039 if (!hd->is_spi) {
5040 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
5041 if (target->inq_data[7] & 0x02)
5042 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
5043 }
5044 return;
5045 }
5046
5047 target->negoFlags = pspi_data->noQas;
5048
5049 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
5050 * support. If available, default QAS to off and allow enabling.
5051 * If not available, default QAS to on, turn off for non-disks.
5052 */
5053
5054 /* Set flags based on Inquiry data
5055 */
5056 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
5057 version = target->inq_data[2] & 0x07;
5058 if (version < 2) {
5059 width = 0;
5060 factor = MPT_ULTRA2;
5061 offset = pspi_data->maxSyncOffset;
5062 } else {
5063 if (target->inq_data[7] & 0x20) {
5064 width = 1;
5065 }
5066
5067 if (target->inq_data[7] & 0x10) {
5068 /* bits 2 & 3 show Clocking support
5069 */
5070 if ((byte56 & 0x0C) == 0)
5071 factor = MPT_ULTRA2;
5072 else {
5073 if ((byte56 & 0x03) == 0)
5074 factor = MPT_ULTRA160;
5075 else
5076 factor = MPT_ULTRA320;
5077 }
5078 offset = pspi_data->maxSyncOffset;
5079
5080 /* If RAID, never disable QAS
5081 * else if non RAID, do not disable
5082 * QAS if bit 1 is set
5083 * bit 1 QAS support, non-raid only
5084 * bit 0 IU support
5085 */
5086 if ((target->raidVolume == 1) || (byte56 & 0x02)) {
5087 noQas = 0;
5088 }
5089 } else {
5090 factor = MPT_ASYNC;
5091 offset = 0;
5092 }
5093 }
5094
5095 if (target->inq_data[7] & 0x02) {
5096 canQ = 1;
5097 }
5098
5099 /* Update tflags based on NVRAM settings. (SCSI only)
5100 */
5101 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5102 nvram = pspi_data->nvram[id];
5103 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
5104
5105 if (width)
5106 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5107
5108 if (offset > 0) {
5109 /* Ensure factor is set to the
5110 * maximum of: adapter, nvram, inquiry
5111 */
5112 if (nfactor) {
5113 if (nfactor < pspi_data->minSyncFactor )
5114 nfactor = pspi_data->minSyncFactor;
5115
5116 factor = MAX (factor, nfactor);
5117 if (factor == MPT_ASYNC)
5118 offset = 0;
5119 } else {
5120 offset = 0;
5121 factor = MPT_ASYNC;
5122 }
5123 } else {
5124 factor = MPT_ASYNC;
5125 }
5126 }
5127
5128 /* Make sure data is consistent
5129 */
5130 if ((!width) && (factor < MPT_ULTRA2)) {
5131 factor = MPT_ULTRA2;
5132 }
5133
5134 /* Save the data to the target structure.
5135 */
5136 target->minSyncFactor = factor;
5137 target->maxOffset = offset;
5138 target->maxWidth = width;
5139 if (canQ) {
5140 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
5141 }
5142
5143 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
5144
5145 /* Disable unused features.
5146 */
5147 if (!width)
5148 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5149
5150 if (!offset)
5151 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5152
5153 /* GEM, processor WORKAROUND
5154 */
5155 if (((target->inq_data[0] & 0x1F) == 0x03) || ((target->inq_data[0] & 0x1F) > 0x08)) {
5156 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
5157 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
5158 } else {
5159 if (noQas && (pspi_data->noQas == 0)) {
5160 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
5161 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
5162
5163 /* Disable QAS in a mixed configuration case
5164 */
5165
5166 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
5167 for (ii = 0; ii < id; ii++) {
5168 if ( (vdev = hd->Targets[ii]) ) {
5169 vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
5170 }
5171 }
5172 }
5173 }
5174
5175 /* Write SDP1 on this I/O to this target */
5176 if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
5177 mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
5178 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
5179 } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
5180 mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
5181 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
5182 }
5183
5184 }
5185 return;
5186 }
5187
5188 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
5189 * Else set the NEED_DV flag after Read Capacity Issued (disks)
5190 * or Mode Sense (cdroms).
5191 *
5192 * Tapes, initTarget will set this flag on completion of Inquiry command.
5193 * Called only if DV_NOT_DONE flag is set
5194 */
mptscsih_set_dvflags(MPT_SCSI_HOST * hd,SCSIIORequest_t * pReq)5195 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
5196 {
5197 u8 cmd;
5198
5199 if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
5200 return;
5201
5202 cmd = pReq->CDB[0];
5203
5204 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
5205 ScsiCfgData *pSpi = &hd->ioc->spi_data;
5206 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
5207 /* Set NEED_DV for all hidden disks
5208 */
5209 Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk;
5210 int numPDisk = pSpi->pIocPg3->NumPhysDisks;
5211
5212 while (numPDisk) {
5213 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
5214 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
5215 pPDisk++;
5216 numPDisk--;
5217 }
5218 }
5219 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
5220 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
5221 }
5222 }
5223
5224 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5225 /*
5226 * If no Target, bus reset on 1st I/O. Set the flag to
5227 * prevent any future negotiations to this device.
5228 */
mptscsih_no_negotiate(MPT_SCSI_HOST * hd,int target_id)5229 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
5230 {
5231
5232 if ((hd->Targets) && (hd->Targets[target_id] == NULL))
5233 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
5234
5235 return;
5236 }
5237
5238 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5239 /*
5240 * SCSI Config Page functionality ...
5241 */
5242 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5243 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
5244 * based on width, factor and offset parameters.
5245 * @width: bus width
5246 * @factor: sync factor
5247 * @offset: sync offset
5248 * @requestedPtr: pointer to requested values (updated)
5249 * @configurationPtr: pointer to configuration values (updated)
5250 * @flags: flags to block WDTR or SDTR negotiation
5251 *
5252 * Return: None.
5253 *
5254 * Remark: Called by writeSDP1 and _dv_params
5255 */
5256 static void
mptscsih_setDevicePage1Flags(u8 width,u8 factor,u8 offset,int * requestedPtr,int * configurationPtr,u8 flags)5257 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
5258 {
5259 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
5260 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
5261
5262 *configurationPtr = 0;
5263 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
5264 *requestedPtr |= (offset << 16) | (factor << 8);
5265
5266 if (width && offset && !nowide && !nosync) {
5267 if (factor < MPT_ULTRA160) {
5268 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
5269 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
5270 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
5271 } else if (factor < MPT_ULTRA2) {
5272 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
5273 }
5274 }
5275
5276 if (nowide)
5277 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
5278
5279 if (nosync)
5280 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
5281
5282 return;
5283 }
5284
5285 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5286 /* mptscsih_writeSDP1 - write SCSI Device Page 1
5287 * @hd: Pointer to a SCSI Host Strucutre
5288 * @portnum: IOC port number
5289 * @target_id: writeSDP1 for single ID
5290 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
5291 *
5292 * Return: -EFAULT if read of config page header fails
5293 * or 0 if success.
5294 *
5295 * Remark: If a target has been found, the settings from the
5296 * target structure are used, else the device is set
5297 * to async/narrow.
5298 *
5299 * Remark: Called during init and after a FW reload.
5300 * Remark: We do not wait for a return, write pages sequentially.
5301 */
5302 static int
mptscsih_writeSDP1(MPT_SCSI_HOST * hd,int portnum,int target_id,int flags)5303 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
5304 {
5305 MPT_ADAPTER *ioc = hd->ioc;
5306 Config_t *pReq;
5307 SCSIDevicePage1_t *pData;
5308 VirtDevice *pTarget;
5309 MPT_FRAME_HDR *mf;
5310 dma_addr_t dataDma;
5311 u16 req_idx;
5312 u32 frameOffset;
5313 u32 requested, configuration, flagsLength;
5314 int ii, nvram;
5315 int id = 0, maxid = 0;
5316 u8 width;
5317 u8 factor;
5318 u8 offset;
5319 u8 bus = 0;
5320 u8 negoFlags;
5321 u8 maxwidth, maxoffset, maxfactor;
5322
5323 if (ioc->spi_data.sdp1length == 0)
5324 return 0;
5325
5326 if (flags & MPT_SCSICFG_ALL_IDS) {
5327 id = 0;
5328 maxid = ioc->sh->max_id - 1;
5329 } else if (ioc->sh) {
5330 id = target_id;
5331 maxid = MIN(id, ioc->sh->max_id - 1);
5332 }
5333
5334 for (; id <= maxid; id++) {
5335
5336 if (id == ioc->pfacts[portnum].PortSCSIID)
5337 continue;
5338
5339 /* Use NVRAM to get adapter and target maximums
5340 * Data over-riden by target structure information, if present
5341 */
5342 maxwidth = ioc->spi_data.maxBusWidth;
5343 maxoffset = ioc->spi_data.maxSyncOffset;
5344 maxfactor = ioc->spi_data.minSyncFactor;
5345 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5346 nvram = ioc->spi_data.nvram[id];
5347
5348 if (maxwidth)
5349 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5350
5351 if (maxoffset > 0) {
5352 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
5353 if (maxfactor == 0) {
5354 /* Key for async */
5355 maxfactor = MPT_ASYNC;
5356 maxoffset = 0;
5357 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
5358 maxfactor = ioc->spi_data.minSyncFactor;
5359 }
5360 } else
5361 maxfactor = MPT_ASYNC;
5362 }
5363
5364 /* Set the negotiation flags.
5365 */
5366 negoFlags = ioc->spi_data.noQas;
5367 if (!maxwidth)
5368 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5369
5370 if (!maxoffset)
5371 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5372
5373 if (flags & MPT_SCSICFG_USE_NVRAM) {
5374 width = maxwidth;
5375 factor = maxfactor;
5376 offset = maxoffset;
5377 } else {
5378 width = 0;
5379 factor = MPT_ASYNC;
5380 offset = 0;
5381 //negoFlags = 0;
5382 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
5383 }
5384
5385 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
5386 /* Force to async and narrow if DV has not been executed
5387 * for this ID
5388 */
5389 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
5390 width = 0;
5391 factor = MPT_ASYNC;
5392 offset = 0;
5393 }
5394 #endif
5395
5396 /* If id is not a raid volume, get the updated
5397 * transmission settings from the target structure.
5398 */
5399 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
5400 width = pTarget->maxWidth;
5401 factor = pTarget->minSyncFactor;
5402 offset = pTarget->maxOffset;
5403 negoFlags = pTarget->negoFlags;
5404 }
5405
5406 if (flags & MPT_SCSICFG_BLK_NEGO)
5407 negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
5408
5409 mptscsih_setDevicePage1Flags(width, factor, offset,
5410 &requested, &configuration, negoFlags);
5411
5412 /* Get a MF for this command.
5413 */
5414 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
5415 dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
5416 ioc->name));
5417 return -EAGAIN;
5418 }
5419
5420 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
5421 hd->ioc->name, mf, id, requested, configuration));
5422
5423
5424 /* Set the request and the data pointers.
5425 * Request takes: 36 bytes (32 bit SGE)
5426 * SCSI Device Page 1 requires 16 bytes
5427 * 40 + 16 <= size of SCSI IO Request = 56 bytes
5428 * and MF size >= 64 bytes.
5429 * Place data at end of MF.
5430 */
5431 pReq = (Config_t *)mf;
5432
5433 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5434 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
5435
5436 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
5437 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
5438
5439 /* Complete the request frame (same for all requests).
5440 */
5441 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5442 pReq->Reserved = 0;
5443 pReq->ChainOffset = 0;
5444 pReq->Function = MPI_FUNCTION_CONFIG;
5445 pReq->ExtPageLength = 0;
5446 pReq->ExtPageType = 0;
5447 pReq->MsgFlags = 0;
5448 for (ii=0; ii < 8; ii++) {
5449 pReq->Reserved2[ii] = 0;
5450 }
5451 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
5452 pReq->Header.PageLength = ioc->spi_data.sdp1length;
5453 pReq->Header.PageNumber = 1;
5454 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5455 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
5456
5457 /* Add a SGE to the config request.
5458 */
5459 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
5460
5461 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
5462
5463 /* Set up the common data portion
5464 */
5465 pData->Header.PageVersion = pReq->Header.PageVersion;
5466 pData->Header.PageLength = pReq->Header.PageLength;
5467 pData->Header.PageNumber = pReq->Header.PageNumber;
5468 pData->Header.PageType = pReq->Header.PageType;
5469 pData->RequestedParameters = cpu_to_le32(requested);
5470 pData->Reserved = 0;
5471 pData->Configuration = cpu_to_le32(configuration);
5472
5473 dprintk((MYIOC_s_INFO_FMT
5474 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
5475 ioc->name, id, (id | (bus<<8)),
5476 requested, configuration));
5477
5478 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
5479 }
5480
5481 return 0;
5482 }
5483
5484 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5485 /* mptscsih_writeIOCPage4 - write IOC Page 4
5486 * @hd: Pointer to a SCSI Host Structure
5487 * @target_id: write IOC Page4 for this ID & Bus
5488 *
5489 * Return: -EAGAIN if unable to obtain a Message Frame
5490 * or 0 if success.
5491 *
5492 * Remark: We do not wait for a return, write pages sequentially.
5493 */
5494 static int
mptscsih_writeIOCPage4(MPT_SCSI_HOST * hd,int target_id,int bus)5495 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
5496 {
5497 MPT_ADAPTER *ioc = hd->ioc;
5498 Config_t *pReq;
5499 IOCPage4_t *IOCPage4Ptr;
5500 MPT_FRAME_HDR *mf;
5501 dma_addr_t dataDma;
5502 u16 req_idx;
5503 u32 frameOffset;
5504 u32 flagsLength;
5505 int ii;
5506
5507 /* Get a MF for this command.
5508 */
5509 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
5510 dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
5511 ioc->name));
5512 return -EAGAIN;
5513 }
5514
5515 ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
5516 ioc->name, mf, target_id));
5517
5518 /* Set the request and the data pointers.
5519 * Place data at end of MF.
5520 */
5521 pReq = (Config_t *)mf;
5522
5523 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5524 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
5525
5526 /* Complete the request frame (same for all requests).
5527 */
5528 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5529 pReq->Reserved = 0;
5530 pReq->ChainOffset = 0;
5531 pReq->Function = MPI_FUNCTION_CONFIG;
5532 pReq->ExtPageLength = 0;
5533 pReq->ExtPageType = 0;
5534 pReq->MsgFlags = 0;
5535 for (ii=0; ii < 8; ii++) {
5536 pReq->Reserved2[ii] = 0;
5537 }
5538
5539 IOCPage4Ptr = ioc->spi_data.pIocPg4;
5540 dataDma = ioc->spi_data.IocPg4_dma;
5541 ii = IOCPage4Ptr->ActiveSEP++;
5542 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
5543 IOCPage4Ptr->SEP[ii].SEPBus = bus;
5544 pReq->Header = IOCPage4Ptr->Header;
5545 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
5546
5547 /* Add a SGE to the config request.
5548 */
5549 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
5550 (IOCPage4Ptr->Header.PageLength + ii) * 4;
5551
5552 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
5553
5554 dsprintk((MYIOC_s_INFO_FMT
5555 "writeIOCPage4: pgaddr 0x%x\n",
5556 ioc->name, (target_id | (bus<<8))));
5557
5558 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
5559
5560 return 0;
5561 }
5562
5563 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5564 /* mptscsih_taskmgmt_timeout - Call back for timeout on a
5565 * task management request.
5566 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5567 *
5568 */
mptscsih_taskmgmt_timeout(unsigned long data)5569 static void mptscsih_taskmgmt_timeout(unsigned long data)
5570 {
5571 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
5572
5573 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
5574 "TM request timed out!\n", hd->ioc->name));
5575
5576 /* Delete the timer that triggered this callback.
5577 * Remark: del_timer checks to make sure timer is active
5578 * before deleting.
5579 */
5580 del_timer(&hd->TMtimer);
5581
5582 /* Call the reset handler. Already had a TM request
5583 * timeout - so issue a diagnostic reset
5584 */
5585 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
5586 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
5587 }
5588 #ifdef MPT_SCSI_USE_NEW_EH
5589 else {
5590 /* Because we have reset the IOC, no TM requests can be
5591 * pending. So let's make sure the tmPending flag is reset.
5592 */
5593 nehprintk((KERN_WARNING MYNAM
5594 ": %s: mptscsih_taskmgmt_timeout\n",
5595 hd->ioc->name));
5596 hd->tmPending = 0;
5597 }
5598 #endif
5599
5600 return;
5601 }
5602
5603 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5604 /*
5605 * Bus Scan and Domain Validation functionality ...
5606 */
5607
5608 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5609 /*
5610 * mptscsih_scandv_complete - Scan and DV callback routine registered
5611 * to Fustion MPT (base) driver.
5612 *
5613 * @ioc: Pointer to MPT_ADAPTER structure
5614 * @mf: Pointer to original MPT request frame
5615 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
5616 *
5617 * This routine is called from mpt.c::mpt_interrupt() at the completion
5618 * of any SCSI IO request.
5619 * This routine is registered with the Fusion MPT (base) driver at driver
5620 * load/init time via the mpt_register() API call.
5621 *
5622 * Returns 1 indicating alloc'd request frame ptr should be freed.
5623 *
5624 * Remark: Sets a completion code and (possibly) saves sense data
5625 * in the IOC member localReply structure.
5626 * Used ONLY for DV and other internal commands.
5627 */
5628 static int
mptscsih_scandv_complete(MPT_ADAPTER * ioc,MPT_FRAME_HDR * mf,MPT_FRAME_HDR * mr)5629 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
5630 {
5631 MPT_SCSI_HOST *hd;
5632 SCSIIORequest_t *pReq;
5633 int completionCode;
5634 u16 req_idx;
5635
5636 if ((mf == NULL) ||
5637 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
5638 printk(MYIOC_s_ERR_FMT
5639 "ScanDvComplete, %s req frame ptr! (=%p)\n",
5640 ioc->name, mf?"BAD":"NULL", (void *) mf);
5641 goto wakeup;
5642 }
5643
5644 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5645 del_timer(&hd->timer);
5646 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5647 hd->ScsiLookup[req_idx] = NULL;
5648 pReq = (SCSIIORequest_t *) mf;
5649
5650 if (mf != hd->cmdPtr) {
5651 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
5652 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
5653 }
5654 hd->cmdPtr = NULL;
5655
5656 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
5657 hd->ioc->name, mf, mr, req_idx));
5658
5659 hd->pLocal = &hd->localReply;
5660 hd->pLocal->scsiStatus = 0;
5661
5662 /* If target struct exists, clear sense valid flag.
5663 */
5664 if (mr == NULL) {
5665 completionCode = MPT_SCANDV_GOOD;
5666 } else {
5667 SCSIIOReply_t *pReply;
5668 u16 status;
5669
5670 pReply = (SCSIIOReply_t *) mr;
5671
5672 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
5673
5674 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
5675 status, pReply->SCSIState, pReply->SCSIStatus,
5676 le32_to_cpu(pReply->IOCLogInfo)));
5677
5678 switch(status) {
5679
5680 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
5681 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
5682 break;
5683
5684 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
5685 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
5686 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
5687 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
5688 completionCode = MPT_SCANDV_DID_RESET;
5689 break;
5690
5691 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
5692 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
5693 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
5694 if (pReply->Function == MPI_FUNCTION_CONFIG) {
5695 ConfigReply_t *pr = (ConfigReply_t *)mr;
5696 completionCode = MPT_SCANDV_GOOD;
5697 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
5698 hd->pLocal->header.PageLength = pr->Header.PageLength;
5699 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
5700 hd->pLocal->header.PageType = pr->Header.PageType;
5701
5702 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
5703 /* If the RAID Volume request is successful,
5704 * return GOOD, else indicate that
5705 * some type of error occurred.
5706 */
5707 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
5708 if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
5709 completionCode = MPT_SCANDV_GOOD;
5710 else
5711 completionCode = MPT_SCANDV_SOME_ERROR;
5712
5713 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
5714 u8 *sense_data;
5715 int sz;
5716
5717 /* save sense data in global structure
5718 */
5719 completionCode = MPT_SCANDV_SENSE;
5720 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5721 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
5722 (req_idx * MPT_SENSE_BUFFER_ALLOC));
5723
5724 sz = MIN (pReq->SenseBufferLength,
5725 SCSI_STD_SENSE_BYTES);
5726 memcpy(hd->pLocal->sense, sense_data, sz);
5727
5728 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
5729 sense_data));
5730 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
5731 if (pReq->CDB[0] == CMD_Inquiry)
5732 completionCode = MPT_SCANDV_ISSUE_SENSE;
5733 else
5734 completionCode = MPT_SCANDV_DID_RESET;
5735 }
5736 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
5737 completionCode = MPT_SCANDV_DID_RESET;
5738 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5739 completionCode = MPT_SCANDV_DID_RESET;
5740 else {
5741 /* If no error, this will be equivalent
5742 * to MPT_SCANDV_GOOD
5743 */
5744 completionCode = MPT_SCANDV_GOOD;
5745 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5746 }
5747 break;
5748
5749 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
5750 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5751 completionCode = MPT_SCANDV_DID_RESET;
5752 else
5753 completionCode = MPT_SCANDV_SOME_ERROR;
5754 break;
5755
5756 default:
5757 completionCode = MPT_SCANDV_SOME_ERROR;
5758 break;
5759
5760 } /* switch(status) */
5761
5762 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
5763 completionCode));
5764 } /* end of address reply case */
5765
5766 hd->pLocal->completion = completionCode;
5767
5768 /* MF and RF are freed in mpt_interrupt
5769 */
5770 wakeup:
5771 /* Free Chain buffers (will never chain) in scan or dv */
5772 //mptscsih_freeChainBuffers(hd, req_idx);
5773
5774 /*
5775 * Wake up the original calling thread
5776 */
5777 scandv_wait_done = 1;
5778 wake_up(&scandv_waitq);
5779
5780 return 1;
5781 }
5782
5783 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5784 /* mptscsih_timer_expired - Call back for timer process.
5785 * Used only for dv functionality.
5786 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5787 *
5788 */
mptscsih_timer_expired(unsigned long data)5789 static void mptscsih_timer_expired(unsigned long data)
5790 {
5791 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
5792 #ifndef MPT_SCSI_USE_NEW_EH
5793 unsigned long flags;
5794 #endif
5795
5796
5797 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
5798
5799 if (hd->cmdPtr) {
5800 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
5801
5802 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
5803 /* Desire to issue a task management request here.
5804 * TM requests MUST be single threaded.
5805 * If old eh code and no TM current, issue request.
5806 * If new eh code, do nothing. Wait for OS cmd timeout
5807 * for bus reset.
5808 */
5809 #ifndef MPT_SCSI_USE_NEW_EH
5810 SCSIIORequest_t *pReq = (SCSIIORequest_t *) hd->cmdPtr;
5811
5812 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
5813 if (hd->tmPending) {
5814 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
5815 return;
5816 } else
5817 hd->tmPending = 1;
5818 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
5819 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
5820 pReq->Bus, 0, 0, 0, NO_SLEEP) < 0) {
5821 printk(MYIOC_s_WARN_FMT "TM FAILED!\n", hd->ioc->name);
5822 }
5823 #else
5824 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
5825 #endif
5826 } else {
5827 /* Perform a FW reload */
5828 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
5829 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
5830 }
5831 }
5832 } else {
5833 /* This should NEVER happen */
5834 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
5835 }
5836
5837 /* No more processing.
5838 * TM call will generate an interrupt for SCSI TM Management.
5839 * The FW will reply to all outstanding commands, callback will finish cleanup.
5840 * Hard reset clean-up will free all resources.
5841 */
5842 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
5843
5844 return;
5845 }
5846
5847 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
5848 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5849 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
5850 * @hd: Pointer to scsi host structure
5851 * @action: What do be done.
5852 * @id: Logical target id.
5853 * @bus: Target locations bus.
5854 *
5855 * Returns: < 0 on a fatal error
5856 * 0 on success
5857 *
5858 * Remark: Wait to return until reply processed by the ISR.
5859 */
5860 static int
mptscsih_do_raid(MPT_SCSI_HOST * hd,u8 action,INTERNAL_CMD * io)5861 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
5862 {
5863 MpiRaidActionRequest_t *pReq;
5864 MPT_FRAME_HDR *mf;
5865 int in_isr;
5866
5867 in_isr = in_interrupt();
5868 if (in_isr) {
5869 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
5870 hd->ioc->name));
5871 return -EPERM;
5872 }
5873
5874 /* Get and Populate a free Frame
5875 */
5876 if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5877 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
5878 hd->ioc->name));
5879 return -EAGAIN;
5880 }
5881 pReq = (MpiRaidActionRequest_t *)mf;
5882 pReq->Action = action;
5883 pReq->Reserved1 = 0;
5884 pReq->ChainOffset = 0;
5885 pReq->Function = MPI_FUNCTION_RAID_ACTION;
5886 pReq->VolumeID = io->id;
5887 pReq->VolumeBus = io->bus;
5888 pReq->PhysDiskNum = io->physDiskNum;
5889 pReq->MsgFlags = 0;
5890 pReq->Reserved2 = 0;
5891 pReq->ActionDataWord = 0; /* Reserved for this action */
5892 //pReq->ActionDataSGE = 0;
5893
5894 mpt_add_sge((char *)&pReq->ActionDataSGE,
5895 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
5896
5897 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
5898 hd->ioc->name, action, io->id));
5899
5900 hd->pLocal = NULL;
5901 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
5902 scandv_wait_done = 0;
5903
5904 /* Save cmd pointer, for resource free if timeout or
5905 * FW reload occurs
5906 */
5907 hd->cmdPtr = mf;
5908
5909 add_timer(&hd->timer);
5910 mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5911 wait_event(scandv_waitq, scandv_wait_done);
5912
5913 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
5914 return -1;
5915
5916 return 0;
5917 }
5918 #endif /* ~MPTSCSIH_DISABLE_DOMAIN_VALIDATION */
5919
5920 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5921 /**
5922 * mptscsih_do_cmd - Do internal command.
5923 * @hd: MPT_SCSI_HOST pointer
5924 * @io: INTERNAL_CMD pointer.
5925 *
5926 * Issue the specified internally generated command and do command
5927 * specific cleanup. For bus scan / DV only.
5928 * NOTES: If command is Inquiry and status is good,
5929 * initialize a target structure, save the data
5930 *
5931 * Remark: Single threaded access only.
5932 *
5933 * Return:
5934 * < 0 if an illegal command or no resources
5935 *
5936 * 0 if good
5937 *
5938 * > 0 if command complete but some type of completion error.
5939 */
5940 static int
mptscsih_do_cmd(MPT_SCSI_HOST * hd,INTERNAL_CMD * io)5941 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
5942 {
5943 MPT_FRAME_HDR *mf;
5944 SCSIIORequest_t *pScsiReq;
5945 SCSIIORequest_t ReqCopy;
5946 int my_idx, ii, dir;
5947 int rc, cmdTimeout;
5948 int in_isr;
5949 char cmdLen;
5950 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
5951 char cmd = io->cmd;
5952
5953 in_isr = in_interrupt();
5954 if (in_isr) {
5955 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
5956 hd->ioc->name));
5957 return -EPERM;
5958 }
5959
5960
5961 /* Set command specific information
5962 */
5963 switch (cmd) {
5964 case CMD_Inquiry:
5965 cmdLen = 6;
5966 dir = MPI_SCSIIO_CONTROL_READ;
5967 CDB[0] = cmd;
5968 CDB[4] = io->size;
5969 cmdTimeout = 10;
5970 break;
5971
5972 case CMD_TestUnitReady:
5973 cmdLen = 6;
5974 dir = MPI_SCSIIO_CONTROL_READ;
5975 cmdTimeout = 10;
5976 break;
5977
5978 case CMD_StartStopUnit:
5979 cmdLen = 6;
5980 dir = MPI_SCSIIO_CONTROL_READ;
5981 CDB[0] = cmd;
5982 CDB[4] = 1; /*Spin up the disk */
5983 cmdTimeout = 15;
5984 break;
5985
5986 case CMD_RequestSense:
5987 cmdLen = 6;
5988 CDB[0] = cmd;
5989 CDB[4] = io->size;
5990 dir = MPI_SCSIIO_CONTROL_READ;
5991 cmdTimeout = 10;
5992 break;
5993
5994 case CMD_ReadBuffer:
5995 cmdLen = 10;
5996 dir = MPI_SCSIIO_CONTROL_READ;
5997 CDB[0] = cmd;
5998 if (io->flags & MPT_ICFLAG_ECHO) {
5999 CDB[1] = 0x0A;
6000 } else {
6001 CDB[1] = 0x02;
6002 }
6003
6004 if (io->flags & MPT_ICFLAG_BUF_CAP) {
6005 CDB[1] |= 0x01;
6006 }
6007 CDB[6] = (io->size >> 16) & 0xFF;
6008 CDB[7] = (io->size >> 8) & 0xFF;
6009 CDB[8] = io->size & 0xFF;
6010 cmdTimeout = 10;
6011 break;
6012
6013 case CMD_WriteBuffer:
6014 cmdLen = 10;
6015 dir = MPI_SCSIIO_CONTROL_WRITE;
6016 CDB[0] = cmd;
6017 if (io->flags & MPT_ICFLAG_ECHO) {
6018 CDB[1] = 0x0A;
6019 } else {
6020 CDB[1] = 0x02;
6021 }
6022 CDB[6] = (io->size >> 16) & 0xFF;
6023 CDB[7] = (io->size >> 8) & 0xFF;
6024 CDB[8] = io->size & 0xFF;
6025 cmdTimeout = 10;
6026 break;
6027
6028 case CMD_Reserve6:
6029 cmdLen = 6;
6030 dir = MPI_SCSIIO_CONTROL_READ;
6031 CDB[0] = cmd;
6032 cmdTimeout = 10;
6033 break;
6034
6035 case CMD_Release6:
6036 cmdLen = 6;
6037 dir = MPI_SCSIIO_CONTROL_READ;
6038 CDB[0] = cmd;
6039 cmdTimeout = 10;
6040 break;
6041
6042 case CMD_SynchronizeCache:
6043 cmdLen = 10;
6044 dir = MPI_SCSIIO_CONTROL_READ;
6045 CDB[0] = cmd;
6046 // CDB[1] = 0x02; /* set immediate bit */
6047 cmdTimeout = 10;
6048 break;
6049
6050 default:
6051 /* Error Case */
6052 return -EFAULT;
6053 }
6054
6055 /* Get and Populate a free Frame
6056 */
6057 if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
6058 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
6059 hd->ioc->name));
6060 return -EBUSY;
6061 }
6062
6063 pScsiReq = (SCSIIORequest_t *) mf;
6064
6065 /* Get the request index */
6066 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
6067 ADD_INDEX_LOG(my_idx); /* for debug */
6068
6069 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
6070 pScsiReq->TargetID = io->physDiskNum;
6071 pScsiReq->Bus = 0;
6072 pScsiReq->ChainOffset = 0;
6073 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
6074 } else {
6075 pScsiReq->TargetID = io->id;
6076 pScsiReq->Bus = io->bus;
6077 pScsiReq->ChainOffset = 0;
6078 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
6079 }
6080
6081 pScsiReq->CDBLength = cmdLen;
6082 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
6083
6084 pScsiReq->Reserved = 0;
6085
6086 pScsiReq->MsgFlags = mpt_msg_flags();
6087 /* MsgContext set in mpt_get_msg_fram call */
6088
6089 for (ii=0; ii < 8; ii++)
6090 pScsiReq->LUN[ii] = 0;
6091 pScsiReq->LUN[1] = io->lun;
6092
6093 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
6094 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
6095 else
6096 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
6097
6098 if (cmd == CMD_RequestSense) {
6099 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
6100 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
6101 hd->ioc->name, cmd));
6102 }
6103
6104 for (ii=0; ii < 16; ii++)
6105 pScsiReq->CDB[ii] = CDB[ii];
6106
6107 pScsiReq->DataLength = cpu_to_le32(io->size);
6108 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
6109 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
6110
6111 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
6112 hd->ioc->name, cmd, io->bus, io->id, io->lun));
6113
6114 if (dir == MPI_SCSIIO_CONTROL_READ) {
6115 mpt_add_sge((char *) &pScsiReq->SGL,
6116 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
6117 io->data_dma);
6118 } else {
6119 mpt_add_sge((char *) &pScsiReq->SGL,
6120 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
6121 io->data_dma);
6122 }
6123
6124 /* The ISR will free the request frame, but we need
6125 * the information to initialize the target. Duplicate.
6126 */
6127 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
6128
6129 /* Issue this command after:
6130 * finish init
6131 * add timer
6132 * Wait until the reply has been received
6133 * ScsiScanDvCtx callback function will
6134 * set hd->pLocal;
6135 * set scandv_wait_done and call wake_up
6136 */
6137 hd->pLocal = NULL;
6138 hd->timer.expires = jiffies + HZ*cmdTimeout;
6139 scandv_wait_done = 0;
6140
6141 /* Save cmd pointer, for resource free if timeout or
6142 * FW reload occurs
6143 */
6144 hd->cmdPtr = mf;
6145
6146 add_timer(&hd->timer);
6147 mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
6148 wait_event(scandv_waitq, scandv_wait_done);
6149
6150 if (hd->pLocal) {
6151 rc = hd->pLocal->completion;
6152 hd->pLocal->skip = 0;
6153
6154 /* Always set fatal error codes in some cases.
6155 */
6156 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
6157 rc = -ENXIO;
6158 else if (rc == MPT_SCANDV_SOME_ERROR)
6159 rc = -rc;
6160 } else {
6161 rc = -EFAULT;
6162 /* This should never happen. */
6163 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
6164 hd->ioc->name));
6165 }
6166
6167 return rc;
6168 }
6169
6170 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6171 /**
6172 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
6173 * @hd: Pointer to MPT_SCSI_HOST structure
6174 * @portnum: IOC port number
6175 *
6176 * Uses the ISR, but with special processing.
6177 * MUST be single-threaded.
6178 *
6179 * Return: 0 on completion
6180 */
6181 static int
mptscsih_synchronize_cache(MPT_SCSI_HOST * hd,int portnum)6182 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
6183 {
6184 MPT_ADAPTER *ioc= hd->ioc;
6185 VirtDevice *pTarget;
6186 SCSIDevicePage1_t *pcfg1Data = NULL;
6187 INTERNAL_CMD iocmd;
6188 CONFIGPARMS cfg;
6189 dma_addr_t cfg1_dma_addr = -1;
6190 ConfigPageHeader_t header1;
6191 int bus = 0;
6192 int id = 0;
6193 int lun;
6194 int indexed_lun, lun_index;
6195 int hostId = ioc->pfacts[portnum].PortSCSIID;
6196 int max_id;
6197 int requested, configuration, data;
6198 int doConfig = 0;
6199 u8 flags, factor;
6200
6201 max_id = ioc->sh->max_id - 1;
6202
6203 /* Following parameters will not change
6204 * in this routine.
6205 */
6206 iocmd.cmd = CMD_SynchronizeCache;
6207 iocmd.flags = 0;
6208 iocmd.physDiskNum = -1;
6209 iocmd.data = NULL;
6210 iocmd.data_dma = -1;
6211 iocmd.size = 0;
6212 iocmd.rsvd = iocmd.rsvd2 = 0;
6213
6214 /* No SCSI hosts
6215 */
6216 if (hd->Targets == NULL)
6217 return 0;
6218
6219 /* Skip the host
6220 */
6221 if (id == hostId)
6222 id++;
6223
6224 /* Write SDP1 for all SCSI devices
6225 * Alloc memory and set up config buffer
6226 */
6227 if (hd->is_spi) {
6228 if (ioc->spi_data.sdp1length > 0) {
6229 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
6230 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
6231
6232 if (pcfg1Data != NULL) {
6233 doConfig = 1;
6234 header1.PageVersion = ioc->spi_data.sdp1version;
6235 header1.PageLength = ioc->spi_data.sdp1length;
6236 header1.PageNumber = 1;
6237 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6238 cfg.hdr = &header1;
6239 cfg.physAddr = cfg1_dma_addr;
6240 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6241 cfg.dir = 1;
6242 cfg.timeout = 0;
6243 }
6244 }
6245 }
6246
6247 /* loop through all devices on this port
6248 */
6249 while (bus < MPT_MAX_BUS) {
6250 iocmd.bus = bus;
6251 iocmd.id = id;
6252 pTarget = hd->Targets[(int)id];
6253
6254 if (doConfig) {
6255
6256 /* Set the negotiation flags */
6257 if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
6258 flags = pTarget->negoFlags;
6259 } else {
6260 flags = hd->ioc->spi_data.noQas;
6261 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6262 data = hd->ioc->spi_data.nvram[id];
6263
6264 if (data & MPT_NVRAM_WIDE_DISABLE)
6265 flags |= MPT_TARGET_NO_NEGO_WIDE;
6266
6267 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
6268 if ((factor == 0) || (factor == MPT_ASYNC))
6269 flags |= MPT_TARGET_NO_NEGO_SYNC;
6270 }
6271 }
6272
6273 /* Force to async, narrow */
6274 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
6275 &configuration, flags);
6276 pcfg1Data->RequestedParameters = le32_to_cpu(requested);
6277 pcfg1Data->Reserved = 0;
6278 pcfg1Data->Configuration = le32_to_cpu(configuration);
6279 cfg.pageAddr = (bus<<8) | id;
6280 mpt_config(hd->ioc, &cfg);
6281 }
6282
6283 /* If target Ptr NULL or if this target is NOT a disk, skip.
6284 */
6285 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
6286 for (lun=0; lun <= MPT_LAST_LUN; lun++) {
6287 /* If LUN present, issue the command
6288 */
6289 lun_index = (lun >> 5); /* 32 luns per lun_index */
6290 indexed_lun = (lun % 32);
6291 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
6292 iocmd.lun = lun;
6293 (void) mptscsih_do_cmd(hd, &iocmd);
6294 }
6295 }
6296 }
6297
6298 /* get next relevant device */
6299 id++;
6300
6301 if (id == hostId)
6302 id++;
6303
6304 if (id > max_id) {
6305 id = 0;
6306 bus++;
6307 }
6308 }
6309
6310 if (pcfg1Data) {
6311 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
6312 }
6313
6314 return 0;
6315 }
6316
6317 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
6318 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6319 /**
6320 * mptscsih_domainValidation - Top level handler for domain validation.
6321 * @hd: Pointer to MPT_SCSI_HOST structure.
6322 *
6323 * Uses the ISR, but with special processing.
6324 * Called from schedule, should not be in interrupt mode.
6325 * While thread alive, do dv for all devices needing dv
6326 *
6327 * Return: None.
6328 */
6329 static void
mptscsih_domainValidation(void * arg)6330 mptscsih_domainValidation(void *arg)
6331 {
6332 MPT_SCSI_HOST *hd;
6333 MPT_ADAPTER *ioc;
6334 unsigned long flags;
6335 int id, maxid, dvStatus, did;
6336 int ii, isPhysDisk;
6337
6338 spin_lock_irqsave(&dvtaskQ_lock, flags);
6339 dvtaskQ_active = 1;
6340 if (dvtaskQ_release) {
6341 dvtaskQ_active = 0;
6342 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
6343 return;
6344 }
6345 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
6346
6347 /* For this ioc, loop through all devices and do dv to each device.
6348 * When complete with this ioc, search through the ioc list, and
6349 * for each scsi ioc found, do dv for all devices. Exit when no
6350 * device needs dv.
6351 */
6352 did = 1;
6353 while (did) {
6354 did = 0;
6355 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
6356 spin_lock_irqsave(&dvtaskQ_lock, flags);
6357 if (dvtaskQ_release) {
6358 dvtaskQ_active = 0;
6359 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
6360 return;
6361 }
6362 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
6363
6364 set_current_state(TASK_INTERRUPTIBLE);
6365 schedule_timeout(HZ/4);
6366
6367 /* DV only to SCSI adapters */
6368 if ((int)ioc->chip_type <= (int)FC929)
6369 continue;
6370
6371 /* Make sure everything looks ok */
6372 if (ioc->sh == NULL)
6373 continue;
6374
6375 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
6376 if (hd == NULL)
6377 continue;
6378
6379 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
6380 mpt_read_ioc_pg_3(ioc);
6381 if (ioc->spi_data.pIocPg3) {
6382 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
6383 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
6384
6385 while (numPDisk) {
6386 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
6387 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
6388
6389 pPDisk++;
6390 numPDisk--;
6391 }
6392 }
6393 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
6394 }
6395
6396 maxid = MIN (ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
6397
6398 for (id = 0; id < maxid; id++) {
6399 spin_lock_irqsave(&dvtaskQ_lock, flags);
6400 if (dvtaskQ_release) {
6401 dvtaskQ_active = 0;
6402 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
6403 return;
6404 }
6405 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
6406 dvStatus = hd->ioc->spi_data.dvStatus[id];
6407
6408 if (dvStatus & MPT_SCSICFG_NEED_DV) {
6409 did++;
6410 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
6411 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
6412
6413 set_current_state(TASK_INTERRUPTIBLE);
6414 schedule_timeout(HZ/4);
6415
6416 /* If hidden phys disk, block IO's to all
6417 * raid volumes
6418 * else, process normally
6419 */
6420 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
6421 if (isPhysDisk) {
6422 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
6423 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
6424 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
6425 }
6426 }
6427 }
6428
6429 if (mptscsih_doDv(hd, 0, id) == 1) {
6430 /* Untagged device was busy, try again
6431 */
6432 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
6433 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
6434 } else {
6435 /* DV is complete. Clear flags.
6436 */
6437 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
6438 }
6439
6440 if (isPhysDisk) {
6441 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
6442 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
6443 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
6444 }
6445 }
6446 }
6447
6448 /* Post OS IOs that were pended while
6449 * DV running.
6450 */
6451 post_pendingQ_commands(hd);
6452
6453 if (hd->ioc->spi_data.noQas)
6454 mptscsih_qas_check(hd, id);
6455 }
6456 }
6457 }
6458 }
6459
6460 spin_lock_irqsave(&dvtaskQ_lock, flags);
6461 dvtaskQ_active = 0;
6462 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
6463
6464 return;
6465 }
6466
6467 /* Search IOC page 3 to determine if this is hidden physical disk
6468 */
mptscsih_is_phys_disk(MPT_ADAPTER * ioc,int id)6469 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
6470 {
6471 if (ioc->spi_data.pIocPg3) {
6472 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
6473 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
6474
6475 while (numPDisk) {
6476 if (pPDisk->PhysDiskID == id) {
6477 return 1;
6478 }
6479 pPDisk++;
6480 numPDisk--;
6481 }
6482 }
6483 return 0;
6484 }
6485
6486 /* Write SDP1 if no QAS has been enabled
6487 */
mptscsih_qas_check(MPT_SCSI_HOST * hd,int id)6488 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
6489 {
6490 VirtDevice *pTarget;
6491 int ii;
6492
6493 if (hd->Targets == NULL)
6494 return;
6495
6496 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
6497 if (ii == id)
6498 continue;
6499
6500 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
6501 continue;
6502
6503 pTarget = hd->Targets[ii];
6504
6505 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
6506 if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
6507 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
6508 mptscsih_writeSDP1(hd, 0, ii, 0);
6509 }
6510 } else {
6511 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
6512 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
6513 }
6514 }
6515 return;
6516 }
6517
6518
6519
6520 #define MPT_GET_NVRAM_VALS 0x01
6521 #define MPT_UPDATE_MAX 0x02
6522 #define MPT_SET_MAX 0x04
6523 #define MPT_SET_MIN 0x08
6524 #define MPT_FALLBACK 0x10
6525 #define MPT_SAVE 0x20
6526
6527 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6528 /**
6529 * mptscsih_doDv - Perform domain validation to a target.
6530 * @hd: Pointer to MPT_SCSI_HOST structure.
6531 * @portnum: IOC port number.
6532 * @target: Physical ID of this target
6533 *
6534 * Uses the ISR, but with special processing.
6535 * MUST be single-threaded.
6536 * Test will exit if target is at async & narrow.
6537 *
6538 * Return: None.
6539 */
6540 static int
mptscsih_doDv(MPT_SCSI_HOST * hd,int bus_number,int id)6541 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
6542 {
6543 MPT_ADAPTER *ioc = hd->ioc;
6544 VirtDevice *pTarget;
6545 SCSIDevicePage1_t *pcfg1Data;
6546 SCSIDevicePage0_t *pcfg0Data;
6547 u8 *pbuf1;
6548 u8 *pbuf2;
6549 u8 *pDvBuf;
6550 dma_addr_t dvbuf_dma = -1;
6551 dma_addr_t buf1_dma = -1;
6552 dma_addr_t buf2_dma = -1;
6553 dma_addr_t cfg1_dma_addr = -1;
6554 dma_addr_t cfg0_dma_addr = -1;
6555 ConfigPageHeader_t header1;
6556 ConfigPageHeader_t header0;
6557 DVPARAMETERS dv;
6558 INTERNAL_CMD iocmd;
6559 CONFIGPARMS cfg;
6560 int dv_alloc = 0;
6561 int rc, sz = 0;
6562 int bufsize = 0;
6563 int dataBufSize = 0;
6564 int echoBufSize = 0;
6565 int notDone;
6566 int patt;
6567 int repeat;
6568 int retcode = 0;
6569 int nfactor = MPT_ULTRA320;
6570 char firstPass = 1;
6571 char doFallback = 0;
6572 char readPage0;
6573 char bus, lun;
6574 char inq0 = 0;
6575
6576 if (ioc->spi_data.sdp1length == 0)
6577 return 0;
6578
6579 if (ioc->spi_data.sdp0length == 0)
6580 return 0;
6581
6582 /* If multiple buses are used, require that the initiator
6583 * id be the same on all buses.
6584 */
6585 if (id == ioc->pfacts[0].PortSCSIID)
6586 return 0;
6587
6588 lun = 0;
6589 bus = (u8) bus_number;
6590 ddvtprintk((MYIOC_s_NOTE_FMT
6591 "DV started: bus=%d, id %d dv @ %p\n",
6592 ioc->name, bus, id, &dv));
6593
6594 /* Prep DV structure
6595 */
6596 memset (&dv, 0, sizeof(DVPARAMETERS));
6597 dv.id = id;
6598
6599 /* Populate tmax with the current maximum
6600 * transfer parameters for this target.
6601 * Exit if narrow and async.
6602 */
6603 dv.cmd = MPT_GET_NVRAM_VALS;
6604 mptscsih_dv_parms(hd, &dv, NULL);
6605 if ((!dv.max.width) && (!dv.max.offset))
6606 return 0;
6607
6608 /* Prep SCSI IO structure
6609 */
6610 iocmd.id = id;
6611 iocmd.bus = bus;
6612 iocmd.lun = lun;
6613 iocmd.flags = 0;
6614 iocmd.physDiskNum = -1;
6615 iocmd.rsvd = iocmd.rsvd2 = 0;
6616
6617 pTarget = hd->Targets[id];
6618 if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
6619 /* Another GEM workaround. Check peripheral device type,
6620 * if PROCESSOR, quit DV.
6621 */
6622 if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
6623 pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
6624 return 0;
6625 }
6626 }
6627
6628 /* Use tagged commands if possible.
6629 */
6630 if (pTarget) {
6631 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
6632 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
6633 else {
6634 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
6635 return 0;
6636
6637 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
6638 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
6639 return 0;
6640 }
6641 }
6642
6643 /* Prep cfg structure
6644 */
6645 cfg.pageAddr = (bus<<8) | id;
6646 cfg.hdr = NULL;
6647
6648 /* Prep SDP0 header
6649 */
6650 header0.PageVersion = ioc->spi_data.sdp0version;
6651 header0.PageLength = ioc->spi_data.sdp0length;
6652 header0.PageNumber = 0;
6653 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6654
6655 /* Prep SDP1 header
6656 */
6657 header1.PageVersion = ioc->spi_data.sdp1version;
6658 header1.PageLength = ioc->spi_data.sdp1length;
6659 header1.PageNumber = 1;
6660 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6661
6662 if (header0.PageLength & 1)
6663 dv_alloc = (header0.PageLength * 4) + 4;
6664
6665 dv_alloc += (2048 + (header1.PageLength * 4));
6666
6667 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
6668 if (pDvBuf == NULL)
6669 return 0;
6670
6671 sz = 0;
6672 pbuf1 = (u8 *)pDvBuf;
6673 buf1_dma = dvbuf_dma;
6674 sz +=1024;
6675
6676 pbuf2 = (u8 *) (pDvBuf + sz);
6677 buf2_dma = dvbuf_dma + sz;
6678 sz +=1024;
6679
6680 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
6681 cfg0_dma_addr = dvbuf_dma + sz;
6682 sz += header0.PageLength * 4;
6683
6684 /* 8-byte alignment
6685 */
6686 if (header0.PageLength & 1)
6687 sz += 4;
6688
6689 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
6690 cfg1_dma_addr = dvbuf_dma + sz;
6691
6692 /* Skip this ID? Set cfg.hdr to force config page write
6693 */
6694 {
6695 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
6696 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6697 /* Set the factor from nvram */
6698 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
6699 if (nfactor < pspi_data->minSyncFactor )
6700 nfactor = pspi_data->minSyncFactor;
6701
6702 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
6703 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
6704
6705 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
6706 ioc->name, bus, id, lun));
6707
6708 dv.cmd = MPT_SET_MAX;
6709 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6710 cfg.hdr = &header1;
6711
6712 /* Save the final negotiated settings to
6713 * SCSI device page 1.
6714 */
6715 cfg.physAddr = cfg1_dma_addr;
6716 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6717 cfg.dir = 1;
6718 mpt_config(hd->ioc, &cfg);
6719 goto target_done;
6720 }
6721 }
6722 }
6723
6724 /* Finish iocmd inititialization - hidden or visible disk? */
6725 if (ioc->spi_data.pIocPg3) {
6726 /* Searc IOC page 3 for matching id
6727 */
6728 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
6729 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
6730
6731 while (numPDisk) {
6732 if (pPDisk->PhysDiskID == id) {
6733 /* match */
6734 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
6735 iocmd.physDiskNum = pPDisk->PhysDiskNum;
6736
6737 /* Quiesce the IM
6738 */
6739 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
6740 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
6741 goto target_done;
6742 }
6743 break;
6744 }
6745 pPDisk++;
6746 numPDisk--;
6747 }
6748 }
6749
6750 /* RAID Volume ID's may double for a physical device. If RAID but
6751 * not a physical ID as well, skip DV.
6752 */
6753 if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
6754 goto target_done;
6755
6756
6757 /* Basic Test.
6758 * Async & Narrow - Inquiry
6759 * Async & Narrow - Inquiry
6760 * Maximum transfer rate - Inquiry
6761 * Compare buffers:
6762 * If compare, test complete.
6763 * If miscompare and first pass, repeat
6764 * If miscompare and not first pass, fall back and repeat
6765 */
6766 hd->pLocal = NULL;
6767 readPage0 = 0;
6768 sz = SCSI_STD_INQUIRY_BYTES;
6769 rc = MPT_SCANDV_GOOD;
6770 while (1) {
6771 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
6772 retcode = 0;
6773 dv.cmd = MPT_SET_MIN;
6774 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6775
6776 cfg.hdr = &header1;
6777 cfg.physAddr = cfg1_dma_addr;
6778 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6779 cfg.dir = 1;
6780 if (mpt_config(hd->ioc, &cfg) != 0)
6781 goto target_done;
6782
6783 /* Wide - narrow - wide workaround case
6784 */
6785 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
6786 /* Send an untagged command to reset disk Qs corrupted
6787 * when a parity error occurs on a Request Sense.
6788 */
6789 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
6790 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
6791 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
6792
6793 iocmd.cmd = CMD_RequestSense;
6794 iocmd.data_dma = buf1_dma;
6795 iocmd.data = pbuf1;
6796 iocmd.size = 0x12;
6797 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6798 goto target_done;
6799 else {
6800 if (hd->pLocal == NULL)
6801 goto target_done;
6802 rc = hd->pLocal->completion;
6803 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
6804 dv.max.width = 0;
6805 doFallback = 0;
6806 } else
6807 goto target_done;
6808 }
6809 } else
6810 goto target_done;
6811 }
6812
6813 iocmd.cmd = CMD_Inquiry;
6814 iocmd.data_dma = buf1_dma;
6815 iocmd.data = pbuf1;
6816 iocmd.size = sz;
6817 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6818 goto target_done;
6819 else {
6820 if (hd->pLocal == NULL)
6821 goto target_done;
6822 rc = hd->pLocal->completion;
6823 if (rc == MPT_SCANDV_GOOD) {
6824 if (hd->pLocal->scsiStatus == STS_BUSY) {
6825 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
6826 retcode = 1;
6827 else
6828 retcode = 0;
6829
6830 goto target_done;
6831 }
6832 } else if (rc == MPT_SCANDV_SENSE) {
6833 ;
6834 } else {
6835 /* If first command doesn't complete
6836 * with a good status or with a check condition,
6837 * exit.
6838 */
6839 goto target_done;
6840 }
6841 }
6842
6843 /* Reset the size for disks
6844 */
6845 inq0 = (*pbuf1) & 0x1F;
6846 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
6847 sz = 0x40;
6848 iocmd.size = sz;
6849 }
6850
6851 /* Another GEM workaround. Check peripheral device type,
6852 * if PROCESSOR, quit DV.
6853 */
6854 if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08))
6855 goto target_done;
6856
6857 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6858 goto target_done;
6859
6860 if (sz == 0x40) {
6861 if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
6862 && (pTarget->minSyncFactor > 0x09)) {
6863 if ((pbuf1[56] & 0x04) == 0)
6864 ;
6865 else if ((pbuf1[56] & 0x01) == 1) {
6866 pTarget->minSyncFactor = nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
6867 } else {
6868 pTarget->minSyncFactor = nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
6869 }
6870
6871 dv.max.factor = pTarget->minSyncFactor;
6872
6873 if ((pbuf1[56] & 0x02) == 0) {
6874 pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
6875 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6876 }
6877 }
6878 }
6879
6880 if (doFallback)
6881 dv.cmd = MPT_FALLBACK;
6882 else
6883 dv.cmd = MPT_SET_MAX;
6884
6885 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6886 if (mpt_config(hd->ioc, &cfg) != 0)
6887 goto target_done;
6888
6889 if ((!dv.now.width) && (!dv.now.offset))
6890 goto target_done;
6891
6892 iocmd.cmd = CMD_Inquiry;
6893 iocmd.data_dma = buf2_dma;
6894 iocmd.data = pbuf2;
6895 iocmd.size = sz;
6896 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6897 goto target_done;
6898 else if (hd->pLocal == NULL)
6899 goto target_done;
6900 else {
6901 /* Save the return code.
6902 * If this is the first pass,
6903 * read SCSI Device Page 0
6904 * and update the target max parameters.
6905 */
6906 rc = hd->pLocal->completion;
6907 doFallback = 0;
6908 if (rc == MPT_SCANDV_GOOD) {
6909 if (!readPage0) {
6910 u32 sdp0_info;
6911 u32 sdp0_nego;
6912
6913 cfg.hdr = &header0;
6914 cfg.physAddr = cfg0_dma_addr;
6915 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6916 cfg.dir = 0;
6917
6918 if (mpt_config(hd->ioc, &cfg) != 0)
6919 goto target_done;
6920
6921 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
6922 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
6923
6924 /* Quantum and Fujitsu workarounds.
6925 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
6926 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
6927 * Resetart with a request for U160.
6928 */
6929 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
6930 doFallback = 1;
6931 } else {
6932 dv.cmd = MPT_UPDATE_MAX;
6933 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
6934 /* Update the SCSI device page 1 area
6935 */
6936 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
6937 readPage0 = 1;
6938 }
6939 }
6940
6941 /* Quantum workaround. Restart this test will the fallback
6942 * flag set.
6943 */
6944 if (doFallback == 0) {
6945 if (memcmp(pbuf1, pbuf2, sz) != 0) {
6946 if (!firstPass)
6947 doFallback = 1;
6948 } else
6949 break; /* test complete */
6950 }
6951
6952
6953 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
6954 doFallback = 1; /* set fallback flag */
6955 else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
6956 doFallback = 1; /* set fallback flag */
6957 else
6958 goto target_done;
6959
6960 firstPass = 0;
6961 }
6962 }
6963 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
6964 inq0 = (*pbuf1) & 0x1F;
6965
6966 /* Continue only for disks
6967 */
6968 if (inq0 != 0)
6969 goto target_done;
6970
6971 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
6972 goto target_done;
6973
6974 /* Start the Enhanced Test.
6975 * 0) issue TUR to clear out check conditions
6976 * 1) read capacity of echo (regular) buffer
6977 * 2) reserve device
6978 * 3) do write-read-compare data pattern test
6979 * 4) release
6980 * 5) update nego parms to target struct
6981 */
6982 cfg.hdr = &header1;
6983 cfg.physAddr = cfg1_dma_addr;
6984 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6985 cfg.dir = 1;
6986
6987 iocmd.cmd = CMD_TestUnitReady;
6988 iocmd.data_dma = -1;
6989 iocmd.data = NULL;
6990 iocmd.size = 0;
6991 notDone = 1;
6992 while (notDone) {
6993 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6994 goto target_done;
6995
6996 if (hd->pLocal == NULL)
6997 goto target_done;
6998
6999 rc = hd->pLocal->completion;
7000 if (rc == MPT_SCANDV_GOOD)
7001 notDone = 0;
7002 else if (rc == MPT_SCANDV_SENSE) {
7003 u8 skey = hd->pLocal->sense[2] & 0x0F;
7004 u8 asc = hd->pLocal->sense[12];
7005 u8 ascq = hd->pLocal->sense[13];
7006 ddvprintk((MYIOC_s_INFO_FMT
7007 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
7008 ioc->name, skey, asc, ascq));
7009
7010 if (skey == SK_UNIT_ATTENTION)
7011 notDone++; /* repeat */
7012 else if ((skey == SK_NOT_READY) &&
7013 (asc == 0x04)&&(ascq == 0x01)) {
7014 /* wait then repeat */
7015 mdelay (2000);
7016 notDone++;
7017 } else if ((skey == SK_NOT_READY) && (asc == 0x3A)) {
7018 /* no medium, try read test anyway */
7019 notDone = 0;
7020 } else {
7021 /* All other errors are fatal.
7022 */
7023 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
7024 ioc->name));
7025 goto target_done;
7026 }
7027 } else
7028 goto target_done;
7029 }
7030
7031 iocmd.cmd = CMD_ReadBuffer;
7032 iocmd.data_dma = buf1_dma;
7033 iocmd.data = pbuf1;
7034 iocmd.size = 4;
7035 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
7036
7037 dataBufSize = 0;
7038 echoBufSize = 0;
7039 for (patt = 0; patt < 2; patt++) {
7040 if (patt == 0)
7041 iocmd.flags |= MPT_ICFLAG_ECHO;
7042 else
7043 iocmd.flags &= ~MPT_ICFLAG_ECHO;
7044
7045 notDone = 1;
7046 while (notDone) {
7047 bufsize = 0;
7048
7049 /* If not ready after 8 trials,
7050 * give up on this device.
7051 */
7052 if (notDone > 8)
7053 goto target_done;
7054
7055 if (mptscsih_do_cmd(hd, &iocmd) < 0)
7056 goto target_done;
7057 else if (hd->pLocal == NULL)
7058 goto target_done;
7059 else {
7060 rc = hd->pLocal->completion;
7061 ddvprintk(("ReadBuffer Comp Code %d", rc));
7062 ddvprintk((" buff: %0x %0x %0x %0x\n",
7063 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
7064
7065 if (rc == MPT_SCANDV_GOOD) {
7066 notDone = 0;
7067 if (iocmd.flags & MPT_ICFLAG_ECHO) {
7068 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
7069 } else {
7070 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
7071 }
7072 } else if (rc == MPT_SCANDV_SENSE) {
7073 u8 skey = hd->pLocal->sense[2] & 0x0F;
7074 u8 asc = hd->pLocal->sense[12];
7075 u8 ascq = hd->pLocal->sense[13];
7076 ddvprintk((MYIOC_s_INFO_FMT
7077 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
7078 ioc->name, skey, asc, ascq));
7079 if (skey == SK_ILLEGAL_REQUEST) {
7080 notDone = 0;
7081 } else if (skey == SK_UNIT_ATTENTION) {
7082 notDone++; /* repeat */
7083 } else if ((skey == SK_NOT_READY) &&
7084 (asc == 0x04)&&(ascq == 0x01)) {
7085 /* wait then repeat */
7086 mdelay (2000);
7087 notDone++;
7088 } else {
7089 /* All other errors are fatal.
7090 */
7091 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
7092 ioc->name));
7093 goto target_done;
7094 }
7095 } else {
7096 /* All other errors are fatal
7097 */
7098 goto target_done;
7099 }
7100 }
7101 }
7102
7103 if (iocmd.flags & MPT_ICFLAG_ECHO)
7104 echoBufSize = bufsize;
7105 else
7106 dataBufSize = bufsize;
7107 }
7108 sz = 0;
7109 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
7110
7111 /* Use echo buffers if possible,
7112 * Exit if both buffers are 0.
7113 */
7114 if (echoBufSize > 0) {
7115 iocmd.flags |= MPT_ICFLAG_ECHO;
7116 if (dataBufSize > 0)
7117 bufsize = MIN(echoBufSize, dataBufSize);
7118 else
7119 bufsize = echoBufSize;
7120 } else if (dataBufSize == 0)
7121 goto target_done;
7122
7123 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
7124 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
7125
7126 /* Data buffers for write-read-compare test max 1K.
7127 */
7128 sz = MIN(bufsize, 1024);
7129
7130 /* --- loop ----
7131 * On first pass, always issue a reserve.
7132 * On additional loops, only if a reset has occurred.
7133 * iocmd.flags indicates if echo or regular buffer
7134 */
7135 for (patt = 0; patt < 4; patt++) {
7136 ddvprintk(("Pattern %d\n", patt));
7137 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
7138 iocmd.cmd = CMD_TestUnitReady;
7139 iocmd.data_dma = -1;
7140 iocmd.data = NULL;
7141 iocmd.size = 0;
7142 if (mptscsih_do_cmd(hd, &iocmd) < 0)
7143 goto target_done;
7144
7145 iocmd.cmd = CMD_Release6;
7146 iocmd.data_dma = -1;
7147 iocmd.data = NULL;
7148 iocmd.size = 0;
7149 if (mptscsih_do_cmd(hd, &iocmd) < 0)
7150 goto target_done;
7151 else if (hd->pLocal == NULL)
7152 goto target_done;
7153 else {
7154 rc = hd->pLocal->completion;
7155 ddvprintk(("Release rc %d\n", rc));
7156 if (rc == MPT_SCANDV_GOOD)
7157 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
7158 else
7159 goto target_done;
7160 }
7161 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
7162 }
7163 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
7164
7165 repeat = 5;
7166 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
7167 iocmd.cmd = CMD_Reserve6;
7168 iocmd.data_dma = -1;
7169 iocmd.data = NULL;
7170 iocmd.size = 0;
7171 if (mptscsih_do_cmd(hd, &iocmd) < 0)
7172 goto target_done;
7173 else if (hd->pLocal == NULL)
7174 goto target_done;
7175 else {
7176 rc = hd->pLocal->completion;
7177 if (rc == MPT_SCANDV_GOOD) {
7178 iocmd.flags |= MPT_ICFLAG_RESERVED;
7179 } else if (rc == MPT_SCANDV_SENSE) {
7180 /* Wait if coming ready
7181 */
7182 u8 skey = hd->pLocal->sense[2] & 0x0F;
7183 u8 asc = hd->pLocal->sense[12];
7184 u8 ascq = hd->pLocal->sense[13];
7185 ddvprintk((MYIOC_s_INFO_FMT
7186 "DV: Reserve Failed: ", ioc->name));
7187 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
7188 skey, asc, ascq));
7189
7190 if ((skey == SK_NOT_READY) && (asc == 0x04)&&
7191 (ascq == 0x01)) {
7192 /* wait then repeat */
7193 mdelay (2000);
7194 notDone++;
7195 } else {
7196 ddvprintk((MYIOC_s_INFO_FMT
7197 "DV: Reserved Failed.", ioc->name));
7198 goto target_done;
7199 }
7200 } else {
7201 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
7202 ioc->name));
7203 goto target_done;
7204 }
7205 }
7206 }
7207
7208 mptscsih_fillbuf(pbuf1, sz, patt, 1);
7209 iocmd.cmd = CMD_WriteBuffer;
7210 iocmd.data_dma = buf1_dma;
7211 iocmd.data = pbuf1;
7212 iocmd.size = sz;
7213 if (mptscsih_do_cmd(hd, &iocmd) < 0)
7214 goto target_done;
7215 else if (hd->pLocal == NULL)
7216 goto target_done;
7217 else {
7218 rc = hd->pLocal->completion;
7219 if (rc == MPT_SCANDV_GOOD)
7220 ; /* Issue read buffer */
7221 else if (rc == MPT_SCANDV_DID_RESET) {
7222 /* If using echo buffers, reset to data buffers.
7223 * Else do Fallback and restart
7224 * this test (re-issue reserve
7225 * because of bus reset).
7226 */
7227 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
7228 iocmd.flags &= ~MPT_ICFLAG_ECHO;
7229 } else {
7230 dv.cmd = MPT_FALLBACK;
7231 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
7232
7233 if (mpt_config(hd->ioc, &cfg) != 0)
7234 goto target_done;
7235
7236 if ((!dv.now.width) && (!dv.now.offset))
7237 goto target_done;
7238 }
7239
7240 iocmd.flags |= MPT_ICFLAG_DID_RESET;
7241 patt = -1;
7242 continue;
7243 } else if (rc == MPT_SCANDV_SENSE) {
7244 /* Restart data test if UA, else quit.
7245 */
7246 u8 skey = hd->pLocal->sense[2] & 0x0F;
7247 ddvprintk((MYIOC_s_INFO_FMT
7248 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
7249 hd->pLocal->sense[12], hd->pLocal->sense[13]));
7250 if (skey == SK_UNIT_ATTENTION) {
7251 patt = -1;
7252 continue;
7253 } else if (skey == SK_ILLEGAL_REQUEST) {
7254 if (iocmd.flags & MPT_ICFLAG_ECHO) {
7255 if (dataBufSize >= bufsize) {
7256 iocmd.flags &= ~MPT_ICFLAG_ECHO;
7257 patt = -1;
7258 continue;
7259 }
7260 }
7261 goto target_done;
7262 }
7263 else
7264 goto target_done;
7265 } else {
7266 /* fatal error */
7267 goto target_done;
7268 }
7269 }
7270
7271 iocmd.cmd = CMD_ReadBuffer;
7272 iocmd.data_dma = buf2_dma;
7273 iocmd.data = pbuf2;
7274 iocmd.size = sz;
7275 if (mptscsih_do_cmd(hd, &iocmd) < 0)
7276 goto target_done;
7277 else if (hd->pLocal == NULL)
7278 goto target_done;
7279 else {
7280 rc = hd->pLocal->completion;
7281 if (rc == MPT_SCANDV_GOOD) {
7282 /* If buffers compare,
7283 * go to next pattern,
7284 * else, do a fallback and restart
7285 * data transfer test.
7286 */
7287 if (memcmp (pbuf1, pbuf2, sz) == 0) {
7288 ; /* goto next pattern */
7289 } else {
7290 /* Miscompare with Echo buffer, go to data buffer,
7291 * if that buffer exists.
7292 * Miscompare with Data buffer, check first 4 bytes,
7293 * some devices return capacity. Exit in this case.
7294 */
7295 if (iocmd.flags & MPT_ICFLAG_ECHO) {
7296 if (dataBufSize >= bufsize)
7297 iocmd.flags &= ~MPT_ICFLAG_ECHO;
7298 else
7299 goto target_done;
7300 } else {
7301 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
7302 /* Argh. Device returning wrong data.
7303 * Quit DV for this device.
7304 */
7305 goto target_done;
7306 }
7307
7308 /* Had an actual miscompare. Slow down.*/
7309 dv.cmd = MPT_FALLBACK;
7310 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
7311
7312 if (mpt_config(hd->ioc, &cfg) != 0)
7313 goto target_done;
7314
7315 if ((!dv.now.width) && (!dv.now.offset))
7316 goto target_done;
7317 }
7318
7319 patt = -1;
7320 continue;
7321 }
7322 } else if (rc == MPT_SCANDV_DID_RESET) {
7323 /* Do Fallback and restart
7324 * this test (re-issue reserve
7325 * because of bus reset).
7326 */
7327 dv.cmd = MPT_FALLBACK;
7328 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
7329
7330 if (mpt_config(hd->ioc, &cfg) != 0)
7331 goto target_done;
7332
7333 if ((!dv.now.width) && (!dv.now.offset))
7334 goto target_done;
7335
7336 iocmd.flags |= MPT_ICFLAG_DID_RESET;
7337 patt = -1;
7338 continue;
7339 } else if (rc == MPT_SCANDV_SENSE) {
7340 /* Restart data test if UA, else quit.
7341 */
7342 u8 skey = hd->pLocal->sense[2] & 0x0F;
7343 ddvprintk((MYIOC_s_INFO_FMT
7344 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
7345 hd->pLocal->sense[12], hd->pLocal->sense[13]));
7346 if (skey == SK_UNIT_ATTENTION) {
7347 patt = -1;
7348 continue;
7349 }
7350 else
7351 goto target_done;
7352 } else {
7353 /* fatal error */
7354 goto target_done;
7355 }
7356 }
7357
7358 } /* --- end of patt loop ---- */
7359
7360 target_done:
7361 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
7362 iocmd.cmd = CMD_Release6;
7363 iocmd.data_dma = -1;
7364 iocmd.data = NULL;
7365 iocmd.size = 0;
7366 if (mptscsih_do_cmd(hd, &iocmd) < 0)
7367 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
7368 ioc->name, id);
7369 else if (hd->pLocal) {
7370 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
7371 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
7372 } else {
7373 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
7374 ioc->name, id);
7375 }
7376 }
7377
7378
7379 /* Set if cfg1_dma_addr contents is valid
7380 */
7381 if ((cfg.hdr != NULL) && (retcode == 0)){
7382 /* If disk, not U320, disable QAS
7383 */
7384 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
7385 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
7386
7387 dv.cmd = MPT_SAVE;
7388 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
7389
7390 /* Double writes to SDP1 can cause problems,
7391 * skip save of the final negotiated settings to
7392 * SCSI device page 1.
7393 *
7394 cfg.hdr = &header1;
7395 cfg.physAddr = cfg1_dma_addr;
7396 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
7397 cfg.dir = 1;
7398 mpt_config(hd->ioc, &cfg);
7399 */
7400 }
7401
7402 /* If this is a RAID Passthrough, enable internal IOs
7403 */
7404 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
7405 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
7406 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
7407 }
7408
7409 /* Done with the DV scan of the current target
7410 */
7411 if (pDvBuf)
7412 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
7413
7414 ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
7415 ioc->name));
7416
7417 return retcode;
7418 }
7419
7420 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7421 /* mptscsih_dv_parms - perform a variety of operations on the
7422 * parameters used for negotiation.
7423 * @hd: Pointer to a SCSI host.
7424 * @dv: Pointer to a structure that contains the maximum and current
7425 * negotiated parameters.
7426 */
7427 static void
mptscsih_dv_parms(MPT_SCSI_HOST * hd,DVPARAMETERS * dv,void * pPage)7428 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
7429 {
7430 VirtDevice *pTarget;
7431 SCSIDevicePage0_t *pPage0;
7432 SCSIDevicePage1_t *pPage1;
7433 int val = 0, data, configuration;
7434 u8 width = 0;
7435 u8 offset = 0;
7436 u8 factor = 0;
7437 u8 negoFlags = 0;
7438 u8 cmd = dv->cmd;
7439 u8 id = dv->id;
7440
7441 switch (cmd) {
7442 case MPT_GET_NVRAM_VALS:
7443 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
7444 hd->ioc->name));
7445 /* Get the NVRAM values and save in tmax
7446 * If not an LVD bus, the adapter minSyncFactor has been
7447 * already throttled back.
7448 */
7449 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
7450 width = pTarget->maxWidth;
7451 offset = pTarget->maxOffset;
7452 factor = pTarget->minSyncFactor;
7453 negoFlags = pTarget->negoFlags;
7454 } else {
7455 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
7456 data = hd->ioc->spi_data.nvram[id];
7457 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
7458 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
7459 factor = MPT_ASYNC;
7460 else {
7461 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
7462 if ((factor == 0) || (factor == MPT_ASYNC)){
7463 factor = MPT_ASYNC;
7464 offset = 0;
7465 }
7466 }
7467 } else {
7468 width = MPT_NARROW;
7469 offset = 0;
7470 factor = MPT_ASYNC;
7471 }
7472
7473 /* Set the negotiation flags */
7474 negoFlags = hd->ioc->spi_data.noQas;
7475 if (!width)
7476 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
7477
7478 if (!offset)
7479 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
7480 }
7481
7482 /* limit by adapter capabilities */
7483 width = MIN(width, hd->ioc->spi_data.maxBusWidth);
7484 offset = MIN(offset, hd->ioc->spi_data.maxSyncOffset);
7485 factor = MAX(factor, hd->ioc->spi_data.minSyncFactor);
7486
7487 /* Check Consistency */
7488 if (offset && (factor < MPT_ULTRA2) && !width)
7489 factor = MPT_ULTRA2;
7490
7491 dv->max.width = width;
7492 dv->max.offset = offset;
7493 dv->max.factor = factor;
7494 dv->max.flags = negoFlags;
7495 ddvprintk((" width %d, factor %x, offset %x flags %x\n",
7496 width, factor, offset, negoFlags));
7497 break;
7498
7499 case MPT_UPDATE_MAX:
7500 ddvprintk((MYIOC_s_NOTE_FMT
7501 "Updating with SDP0 Data: ", hd->ioc->name));
7502 /* Update tmax values with those from Device Page 0.*/
7503 pPage0 = (SCSIDevicePage0_t *) pPage;
7504 if (pPage0) {
7505 val = cpu_to_le32(pPage0->NegotiatedParameters);
7506 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
7507 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
7508 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
7509 }
7510
7511 dv->now.width = dv->max.width;
7512 dv->now.offset = dv->max.offset;
7513 dv->now.factor = dv->max.factor;
7514 ddvprintk(("width %d, factor %x, offset %x, flags %x\n",
7515 dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
7516 break;
7517
7518 case MPT_SET_MAX:
7519 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
7520 hd->ioc->name));
7521 /* Set current to the max values. Update the config page.*/
7522 dv->now.width = dv->max.width;
7523 dv->now.offset = dv->max.offset;
7524 dv->now.factor = dv->max.factor;
7525 dv->now.flags = dv->max.flags;
7526
7527 pPage1 = (SCSIDevicePage1_t *)pPage;
7528 if (pPage1) {
7529 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
7530 dv->now.offset, &val, &configuration, dv->now.flags);
7531 pPage1->RequestedParameters = le32_to_cpu(val);
7532 pPage1->Reserved = 0;
7533 pPage1->Configuration = le32_to_cpu(configuration);
7534
7535 }
7536
7537 ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n",
7538 dv->now.width, dv->now.factor, dv->now.offset, val, configuration));
7539 break;
7540
7541 case MPT_SET_MIN:
7542 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
7543 hd->ioc->name));
7544 /* Set page to asynchronous and narrow
7545 * Do not update now, breaks fallback routine. */
7546 width = MPT_NARROW;
7547 offset = 0;
7548 factor = MPT_ASYNC;
7549 negoFlags = dv->max.flags;
7550
7551 pPage1 = (SCSIDevicePage1_t *)pPage;
7552 if (pPage1) {
7553 mptscsih_setDevicePage1Flags (width, factor,
7554 offset, &val, &configuration, negoFlags);
7555 pPage1->RequestedParameters = le32_to_cpu(val);
7556 pPage1->Reserved = 0;
7557 pPage1->Configuration = le32_to_cpu(configuration);
7558 }
7559 ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
7560 width, factor, offset, val, configuration));
7561 break;
7562
7563 case MPT_FALLBACK:
7564 ddvprintk((MYIOC_s_NOTE_FMT
7565 "Fallback: Start: offset %d, factor %x, width %d \n",
7566 hd->ioc->name, dv->now.offset,
7567 dv->now.factor, dv->now.width));
7568 width = dv->now.width;
7569 offset = dv->now.offset;
7570 factor = dv->now.factor;
7571 if ((offset) && (dv->max.width)) {
7572 if (factor < MPT_ULTRA160)
7573 factor = MPT_ULTRA160;
7574 else if (factor < MPT_ULTRA2) {
7575 factor = MPT_ULTRA2;
7576 width = MPT_WIDE;
7577 } else if ((factor == MPT_ULTRA2) && width) {
7578 factor = MPT_ULTRA2;
7579 width = MPT_NARROW;
7580 } else if (factor < MPT_ULTRA) {
7581 factor = MPT_ULTRA;
7582 width = MPT_WIDE;
7583 } else if ((factor == MPT_ULTRA) && width) {
7584 width = MPT_NARROW;
7585 } else if (factor < MPT_FAST) {
7586 factor = MPT_FAST;
7587 width = MPT_WIDE;
7588 } else if ((factor == MPT_FAST) && width) {
7589 factor = MPT_FAST;
7590 width = MPT_NARROW;
7591 } else if (factor < MPT_SCSI) {
7592 factor = MPT_SCSI;
7593 width = MPT_WIDE;
7594 } else if ((factor == MPT_SCSI) && width) {
7595 factor = MPT_SCSI;
7596 width = MPT_NARROW;
7597 } else {
7598 factor = MPT_ASYNC;
7599 offset = 0;
7600 }
7601
7602 } else if (offset) {
7603 width = MPT_NARROW;
7604 if (factor < MPT_ULTRA)
7605 factor = MPT_ULTRA;
7606 else if (factor < MPT_FAST)
7607 factor = MPT_FAST;
7608 else if (factor < MPT_SCSI)
7609 factor = MPT_SCSI;
7610 else {
7611 factor = MPT_ASYNC;
7612 offset = 0;
7613 }
7614
7615 } else {
7616 width = MPT_NARROW;
7617 factor = MPT_ASYNC;
7618 }
7619 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
7620
7621 dv->now.width = width;
7622 dv->now.offset = offset;
7623 dv->now.factor = factor;
7624 dv->now.flags = dv->max.flags;
7625
7626 pPage1 = (SCSIDevicePage1_t *)pPage;
7627 if (pPage1) {
7628 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
7629 &configuration, dv->now.flags);
7630
7631 pPage1->RequestedParameters = le32_to_cpu(val);
7632 pPage1->Reserved = 0;
7633 pPage1->Configuration = le32_to_cpu(configuration);
7634 }
7635
7636 ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n",
7637 dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
7638 break;
7639
7640 case MPT_SAVE:
7641 ddvprintk((MYIOC_s_NOTE_FMT
7642 "Saving to Target structure: ", hd->ioc->name));
7643 ddvprintk(("offset %d, factor %x, width %d \n",
7644 dv->now.offset, dv->now.factor, dv->now.width));
7645
7646 /* Save these values to target structures
7647 * or overwrite nvram (phys disks only).
7648 */
7649
7650 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
7651 pTarget->maxWidth = dv->now.width;
7652 pTarget->maxOffset = dv->now.offset;
7653 pTarget->minSyncFactor = dv->now.factor;
7654 pTarget->negoFlags = dv->now.flags;
7655 } else {
7656 /* Preserv all flags, use
7657 * read-modify-write algorithm
7658 */
7659 if (hd->ioc->spi_data.nvram) {
7660 data = hd->ioc->spi_data.nvram[id];
7661
7662 if (dv->now.width)
7663 data &= ~MPT_NVRAM_WIDE_DISABLE;
7664 else
7665 data |= MPT_NVRAM_WIDE_DISABLE;
7666
7667 if (!dv->now.offset)
7668 factor = MPT_ASYNC;
7669
7670 data &= ~MPT_NVRAM_SYNC_MASK;
7671 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
7672
7673 hd->ioc->spi_data.nvram[id] = data;
7674 }
7675 }
7676 break;
7677 }
7678 }
7679
7680 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7681 /* mptscsih_fillbuf - fill a buffer with a special data pattern
7682 * cleanup. For bus scan only.
7683 *
7684 * @buffer: Pointer to data buffer to be filled.
7685 * @size: Number of bytes to fill
7686 * @index: Pattern index
7687 * @width: bus width, 0 (8 bits) or 1 (16 bits)
7688 */
7689 static void
mptscsih_fillbuf(char * buffer,int size,int index,int width)7690 mptscsih_fillbuf(char *buffer, int size, int index, int width)
7691 {
7692 char *ptr = buffer;
7693 int ii;
7694 char byte;
7695 short val;
7696
7697 switch (index) {
7698 case 0:
7699
7700 if (width) {
7701 /* Pattern: 0000 FFFF 0000 FFFF
7702 */
7703 for (ii=0; ii < size; ii++, ptr++) {
7704 if (ii & 0x02)
7705 *ptr = 0xFF;
7706 else
7707 *ptr = 0x00;
7708 }
7709 } else {
7710 /* Pattern: 00 FF 00 FF
7711 */
7712 for (ii=0; ii < size; ii++, ptr++) {
7713 if (ii & 0x01)
7714 *ptr = 0xFF;
7715 else
7716 *ptr = 0x00;
7717 }
7718 }
7719 break;
7720
7721 case 1:
7722 if (width) {
7723 /* Pattern: 5555 AAAA 5555 AAAA 5555
7724 */
7725 for (ii=0; ii < size; ii++, ptr++) {
7726 if (ii & 0x02)
7727 *ptr = 0xAA;
7728 else
7729 *ptr = 0x55;
7730 }
7731 } else {
7732 /* Pattern: 55 AA 55 AA 55
7733 */
7734 for (ii=0; ii < size; ii++, ptr++) {
7735 if (ii & 0x01)
7736 *ptr = 0xAA;
7737 else
7738 *ptr = 0x55;
7739 }
7740 }
7741 break;
7742
7743 case 2:
7744 /* Pattern: 00 01 02 03 04 05
7745 * ... FE FF 00 01..
7746 */
7747 for (ii=0; ii < size; ii++, ptr++)
7748 *ptr = (char) ii;
7749 break;
7750
7751 case 3:
7752 if (width) {
7753 /* Wide Pattern: FFFE 0001 FFFD 0002
7754 * ... 4000 DFFF 8000 EFFF
7755 */
7756 byte = 0;
7757 for (ii=0; ii < size/2; ii++) {
7758 /* Create the base pattern
7759 */
7760 val = (1 << byte);
7761 /* every 64 (0x40) bytes flip the pattern
7762 * since we fill 2 bytes / iteration,
7763 * test for ii = 0x20
7764 */
7765 if (ii & 0x20)
7766 val = ~(val);
7767
7768 if (ii & 0x01) {
7769 *ptr = (char)( (val & 0xFF00) >> 8);
7770 ptr++;
7771 *ptr = (char)(val & 0xFF);
7772 byte++;
7773 byte &= 0x0F;
7774 } else {
7775 val = ~val;
7776 *ptr = (char)( (val & 0xFF00) >> 8);
7777 ptr++;
7778 *ptr = (char)(val & 0xFF);
7779 }
7780
7781 ptr++;
7782 }
7783 } else {
7784 /* Narrow Pattern: FE 01 FD 02 FB 04
7785 * .. 7F 80 01 FE 02 FD ... 80 7F
7786 */
7787 byte = 0;
7788 for (ii=0; ii < size; ii++, ptr++) {
7789 /* Base pattern - first 32 bytes
7790 */
7791 if (ii & 0x01) {
7792 *ptr = (1 << byte);
7793 byte++;
7794 byte &= 0x07;
7795 } else {
7796 *ptr = (char) (~(1 << byte));
7797 }
7798
7799 /* Flip the pattern every 32 bytes
7800 */
7801 if (ii & 0x20)
7802 *ptr = ~(*ptr);
7803 }
7804 }
7805 break;
7806 }
7807 }
7808 #endif /* ~MPTSCSIH_DISABLE_DOMAIN_VALIDATION */
7809
7810 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7811 /* Commandline Parsing routines and defines.
7812 *
7813 * insmod format:
7814 * insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1"
7815 * boot format:
7816 * mptscsih=width:1,dv:n,factor:0x8,saf-te:1
7817 *
7818 */
7819 #ifdef MODULE
7820 #define ARG_SEP ' '
7821 #else
7822 #define ARG_SEP ','
7823 #endif
7824
7825 static char setup_token[] __initdata =
7826 "dv:"
7827 "width:"
7828 "factor:"
7829 "saf-te:"
7830 ; /* DO NOT REMOVE THIS ';' */
7831
7832 #define OPT_DV 1
7833 #define OPT_MAX_WIDTH 2
7834 #define OPT_MIN_SYNC_FACTOR 3
7835 #define OPT_SAF_TE 4
7836
7837 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7838 static int
get_setup_token(char * p)7839 __init get_setup_token(char *p)
7840 {
7841 char *cur = setup_token;
7842 char *pc;
7843 int i = 0;
7844
7845 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7846 ++pc;
7847 ++i;
7848 if (!strncmp(p, cur, pc - cur))
7849 return i;
7850 cur = pc;
7851 }
7852 return 0;
7853 }
7854
7855 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7856 static int
mptscsih_setup(char * str)7857 __init mptscsih_setup(char *str)
7858 {
7859 char *cur = str;
7860 char *pc, *pv;
7861 unsigned long val;
7862 int c;
7863
7864 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7865 char *pe;
7866
7867 val = 0;
7868 pv = pc;
7869 c = *++pv;
7870
7871 if (c == 'n')
7872 val = 0;
7873 else if (c == 'y')
7874 val = 1;
7875 else
7876 val = (int) simple_strtoul(pv, &pe, 0);
7877
7878 printk("Found Token: %s, value %x\n", cur, (int)val);
7879 switch (get_setup_token(cur)) {
7880 case OPT_DV:
7881 driver_setup.dv = val;
7882 break;
7883
7884 case OPT_MAX_WIDTH:
7885 driver_setup.max_width = val;
7886 break;
7887
7888 case OPT_MIN_SYNC_FACTOR:
7889 driver_setup.min_sync_fac = val;
7890 break;
7891
7892 case OPT_SAF_TE:
7893 driver_setup.saf_te = val;
7894 break;
7895
7896 default:
7897 printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
7898 break;
7899 }
7900
7901 if ((cur = strchr(cur, ARG_SEP)) != NULL)
7902 ++cur;
7903 }
7904 return 1;
7905 }
7906
7907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7908
7909