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