]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/message/fusion/mptscsih.c
[SCSI] fusion: bump version
[mirror_ubuntu-bionic-kernel.git] / drivers / message / fusion / mptscsih.c
CommitLineData
1da177e4
LT
1/*
2 * linux/drivers/message/fusion/mptscsih.c
0d0c7974 3 * For use with LSI Logic PCI chip/adapter(s)
1da177e4
LT
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
0d0c7974 6 * Copyright (c) 1999-2005 LSI Logic Corporation
1da177e4
LT
7 * (mailto:mpt_linux_developer@lsil.com)
8 *
1da177e4
LT
9 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include "linux_compat.h" /* linux-2.6 tweaks */
48#include <linux/module.h>
49#include <linux/kernel.h>
50#include <linux/init.h>
51#include <linux/errno.h>
52#include <linux/kdev_t.h>
53#include <linux/blkdev.h>
54#include <linux/delay.h> /* for mdelay */
55#include <linux/interrupt.h> /* needed for in_interrupt() proto */
56#include <linux/reboot.h> /* notifier code */
57#include <linux/sched.h>
58#include <linux/workqueue.h>
59
60#include <scsi/scsi.h>
61#include <scsi/scsi_cmnd.h>
62#include <scsi/scsi_device.h>
63#include <scsi/scsi_host.h>
64#include <scsi/scsi_tcq.h>
e0fc15be 65#include <scsi/scsi_dbg.h>
1da177e4
LT
66
67#include "mptbase.h"
68#include "mptscsih.h"
69
70/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71#define my_NAME "Fusion MPT SCSI Host driver"
72#define my_VERSION MPT_LINUX_VERSION_COMMON
73#define MYNAM "mptscsih"
74
75MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
78
1da177e4
LT
79/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
80
81typedef struct _BIG_SENSE_BUF {
82 u8 data[MPT_SENSE_BUFFER_ALLOC];
83} BIG_SENSE_BUF;
84
85#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
86#define MPT_SCANDV_DID_RESET (0x00000001)
87#define MPT_SCANDV_SENSE (0x00000002)
88#define MPT_SCANDV_SOME_ERROR (0x00000004)
89#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
90#define MPT_SCANDV_ISSUE_SENSE (0x00000010)
91#define MPT_SCANDV_FALLBACK (0x00000020)
92
93#define MPT_SCANDV_MAX_RETRIES (10)
94
95#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
96#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
466544d8
MED
97#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
98#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
99#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
1da177e4
LT
100#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
101#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
102
103typedef struct _internal_cmd {
104 char *data; /* data pointer */
105 dma_addr_t data_dma; /* data dma address */
106 int size; /* transfer size */
107 u8 cmd; /* SCSI Op Code */
108 u8 bus; /* bus number */
109 u8 id; /* SCSI ID (virtual) */
110 u8 lun;
111 u8 flags; /* Bit Field - See above */
112 u8 physDiskNum; /* Phys disk number, -1 else */
113 u8 rsvd2;
114 u8 rsvd;
115} INTERNAL_CMD;
116
117typedef struct _negoparms {
118 u8 width;
119 u8 offset;
120 u8 factor;
121 u8 flags;
122} NEGOPARMS;
123
124typedef struct _dv_parameters {
125 NEGOPARMS max;
126 NEGOPARMS now;
127 u8 cmd;
128 u8 id;
129 u16 pad1;
130} DVPARAMETERS;
131
1da177e4
LT
132/*
133 * Other private/forward protos...
134 */
0d0c7974 135int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 136static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
0d0c7974 137int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4
LT
138
139static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
140 SCSIIORequest_t *pReq, int req_idx);
141static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
0d0c7974 142static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
1da177e4
LT
143static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
144static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
145static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
146
147static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
148static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
149
0d0c7974
MED
150int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
151int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
1da177e4 152
c7c82987
MED
153static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen);
154static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, char byte56);
1da177e4 155static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
c7c82987 156static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
1da177e4
LT
157static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
158static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
0d0c7974 159int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 160static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
c7c82987
MED
161static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
162static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget);
f2ea8671 163static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
1da177e4
LT
164
165#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
166static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
167static void mptscsih_domainValidation(void *hd);
1da177e4
LT
168static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
169static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
170static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
171static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
466544d8 172static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
c7c82987 173static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
1da177e4 174#endif
1da177e4 175
0d0c7974 176void mptscsih_remove(struct pci_dev *);
d18c3db5 177void mptscsih_shutdown(struct pci_dev *);
1da177e4 178#ifdef CONFIG_PM
0d0c7974
MED
179int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
180int mptscsih_resume(struct pci_dev *pdev);
1da177e4
LT
181#endif
182
1da177e4
LT
183#define SNS_LEN(scp) sizeof((scp)->sense_buffer)
184
185#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
186/*
187 * Domain Validation task structure
188 */
189static DEFINE_SPINLOCK(dvtaskQ_lock);
190static int dvtaskQ_active = 0;
191static int dvtaskQ_release = 0;
0d0c7974 192static struct work_struct dvTaskQ_task;
1da177e4
LT
193#endif
194
1da177e4
LT
195/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
196/**
197 * mptscsih_add_sge - Place a simple SGE at address pAddr.
198 * @pAddr: virtual address for SGE
199 * @flagslength: SGE flags and data transfer length
200 * @dma_addr: Physical address
201 *
202 * This routine places a MPT request frame back on the MPT adapter's
203 * FreeQ.
204 */
205static inline void
206mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
207{
208 if (sizeof(dma_addr_t) == sizeof(u64)) {
209 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
210 u32 tmp = dma_addr & 0xFFFFFFFF;
211
212 pSge->FlagsLength = cpu_to_le32(flagslength);
213 pSge->Address.Low = cpu_to_le32(tmp);
214 tmp = (u32) ((u64)dma_addr >> 32);
215 pSge->Address.High = cpu_to_le32(tmp);
216
217 } else {
218 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
219 pSge->FlagsLength = cpu_to_le32(flagslength);
220 pSge->Address = cpu_to_le32(dma_addr);
221 }
222} /* mptscsih_add_sge() */
223
224/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
225/**
226 * mptscsih_add_chain - Place a chain SGE at address pAddr.
227 * @pAddr: virtual address for SGE
228 * @next: nextChainOffset value (u32's)
229 * @length: length of next SGL segment
230 * @dma_addr: Physical address
231 *
232 * This routine places a MPT request frame back on the MPT adapter's
233 * FreeQ.
234 */
235static inline void
236mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
237{
238 if (sizeof(dma_addr_t) == sizeof(u64)) {
239 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
240 u32 tmp = dma_addr & 0xFFFFFFFF;
241
242 pChain->Length = cpu_to_le16(length);
243 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
244
245 pChain->NextChainOffset = next;
246
247 pChain->Address.Low = cpu_to_le32(tmp);
248 tmp = (u32) ((u64)dma_addr >> 32);
249 pChain->Address.High = cpu_to_le32(tmp);
250 } else {
251 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
252 pChain->Length = cpu_to_le16(length);
253 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
254 pChain->NextChainOffset = next;
255 pChain->Address = cpu_to_le32(dma_addr);
256 }
257} /* mptscsih_add_chain() */
258
259/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
260/*
261 * mptscsih_getFreeChainBuffer - Function to get a free chain
262 * from the MPT_SCSI_HOST FreeChainQ.
263 * @ioc: Pointer to MPT_ADAPTER structure
264 * @req_idx: Index of the SCSI IO request frame. (output)
265 *
266 * return SUCCESS or FAILED
267 */
268static inline int
269mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
270{
271 MPT_FRAME_HDR *chainBuf;
272 unsigned long flags;
273 int rc;
274 int chain_idx;
275
276 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
277 ioc->name));
278 spin_lock_irqsave(&ioc->FreeQlock, flags);
279 if (!list_empty(&ioc->FreeChainQ)) {
280 int offset;
281
282 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
283 u.frame.linkage.list);
284 list_del(&chainBuf->u.frame.linkage.list);
285 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
286 chain_idx = offset / ioc->req_sz;
287 rc = SUCCESS;
c6678e0c
CH
288 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
289 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
1da177e4
LT
290 } else {
291 rc = FAILED;
292 chain_idx = MPT_HOST_NO_CHAIN;
c6678e0c 293 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
1da177e4
LT
294 ioc->name));
295 }
296 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
297
298 *retIndex = chain_idx;
299 return rc;
300} /* mptscsih_getFreeChainBuffer() */
301
302/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
303/*
304 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
305 * SCSIIORequest_t Message Frame.
306 * @ioc: Pointer to MPT_ADAPTER structure
307 * @SCpnt: Pointer to scsi_cmnd structure
308 * @pReq: Pointer to SCSIIORequest_t structure
309 *
310 * Returns ...
311 */
312static int
313mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
314 SCSIIORequest_t *pReq, int req_idx)
315{
316 char *psge;
317 char *chainSge;
318 struct scatterlist *sg;
319 int frm_sz;
320 int sges_left, sg_done;
321 int chain_idx = MPT_HOST_NO_CHAIN;
322 int sgeOffset;
323 int numSgeSlots, numSgeThisFrame;
324 u32 sgflags, sgdir, thisxfer = 0;
325 int chain_dma_off = 0;
326 int newIndex;
327 int ii;
328 dma_addr_t v2;
329 u32 RequestNB;
330
331 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
332 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
333 sgdir = MPT_TRANSFER_HOST_TO_IOC;
334 } else {
335 sgdir = MPT_TRANSFER_IOC_TO_HOST;
336 }
337
338 psge = (char *) &pReq->SGL;
339 frm_sz = ioc->req_sz;
340
341 /* Map the data portion, if any.
342 * sges_left = 0 if no data transfer.
343 */
344 if ( (sges_left = SCpnt->use_sg) ) {
345 sges_left = pci_map_sg(ioc->pcidev,
346 (struct scatterlist *) SCpnt->request_buffer,
347 SCpnt->use_sg,
348 SCpnt->sc_data_direction);
349 if (sges_left == 0)
350 return FAILED;
351 } else if (SCpnt->request_bufflen) {
352 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
353 SCpnt->request_buffer,
354 SCpnt->request_bufflen,
355 SCpnt->sc_data_direction);
356 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
357 ioc->name, SCpnt, SCpnt->request_bufflen));
358 mptscsih_add_sge((char *) &pReq->SGL,
359 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
360 SCpnt->SCp.dma_handle);
361
362 return SUCCESS;
363 }
364
365 /* Handle the SG case.
366 */
367 sg = (struct scatterlist *) SCpnt->request_buffer;
368 sg_done = 0;
369 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
370 chainSge = NULL;
371
372 /* Prior to entering this loop - the following must be set
373 * current MF: sgeOffset (bytes)
374 * chainSge (Null if original MF is not a chain buffer)
375 * sg_done (num SGE done for this MF)
376 */
377
378nextSGEset:
379 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
380 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
381
382 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
383
384 /* Get first (num - 1) SG elements
385 * Skip any SG entries with a length of 0
386 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
387 */
388 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
389 thisxfer = sg_dma_len(sg);
390 if (thisxfer == 0) {
391 sg ++; /* Get next SG element from the OS */
392 sg_done++;
393 continue;
394 }
395
396 v2 = sg_dma_address(sg);
397 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
398
399 sg++; /* Get next SG element from the OS */
400 psge += (sizeof(u32) + sizeof(dma_addr_t));
401 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
402 sg_done++;
403 }
404
405 if (numSgeThisFrame == sges_left) {
406 /* Add last element, end of buffer and end of list flags.
407 */
408 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
409 MPT_SGE_FLAGS_END_OF_BUFFER |
410 MPT_SGE_FLAGS_END_OF_LIST;
411
412 /* Add last SGE and set termination flags.
413 * Note: Last SGE may have a length of 0 - which should be ok.
414 */
415 thisxfer = sg_dma_len(sg);
416
417 v2 = sg_dma_address(sg);
418 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
419 /*
420 sg++;
421 psge += (sizeof(u32) + sizeof(dma_addr_t));
422 */
423 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
424 sg_done++;
425
426 if (chainSge) {
427 /* The current buffer is a chain buffer,
428 * but there is not another one.
429 * Update the chain element
430 * Offset and Length fields.
431 */
432 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
433 } else {
434 /* The current buffer is the original MF
435 * and there is no Chain buffer.
436 */
437 pReq->ChainOffset = 0;
438 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
c6678e0c 439 dsgprintk((MYIOC_s_INFO_FMT
1da177e4
LT
440 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
441 ioc->RequestNB[req_idx] = RequestNB;
442 }
443 } else {
444 /* At least one chain buffer is needed.
445 * Complete the first MF
446 * - last SGE element, set the LastElement bit
447 * - set ChainOffset (words) for orig MF
448 * (OR finish previous MF chain buffer)
449 * - update MFStructPtr ChainIndex
450 * - Populate chain element
451 * Also
452 * Loop until done.
453 */
454
455 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
456 ioc->name, sg_done));
457
458 /* Set LAST_ELEMENT flag for last non-chain element
459 * in the buffer. Since psge points at the NEXT
460 * SGE element, go back one SGE element, update the flags
461 * and reset the pointer. (Note: sgflags & thisxfer are already
462 * set properly).
463 */
464 if (sg_done) {
465 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
466 sgflags = le32_to_cpu(*ptmp);
467 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
468 *ptmp = cpu_to_le32(sgflags);
469 }
470
471 if (chainSge) {
472 /* The current buffer is a chain buffer.
473 * chainSge points to the previous Chain Element.
474 * Update its chain element Offset and Length (must
475 * include chain element size) fields.
476 * Old chain element is now complete.
477 */
478 u8 nextChain = (u8) (sgeOffset >> 2);
479 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
480 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
481 } else {
482 /* The original MF buffer requires a chain buffer -
483 * set the offset.
484 * Last element in this MF is a chain element.
485 */
486 pReq->ChainOffset = (u8) (sgeOffset >> 2);
487 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
488 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
489 ioc->RequestNB[req_idx] = RequestNB;
490 }
491
492 sges_left -= sg_done;
493
494
495 /* NOTE: psge points to the beginning of the chain element
496 * in current buffer. Get a chain buffer.
497 */
c6678e0c
CH
498 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
499 dfailprintk((MYIOC_s_INFO_FMT
500 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
501 ioc->name, pReq->CDB[0], SCpnt));
1da177e4 502 return FAILED;
c6678e0c 503 }
1da177e4
LT
504
505 /* Update the tracking arrays.
506 * If chainSge == NULL, update ReqToChain, else ChainToChain
507 */
508 if (chainSge) {
509 ioc->ChainToChain[chain_idx] = newIndex;
510 } else {
511 ioc->ReqToChain[req_idx] = newIndex;
512 }
513 chain_idx = newIndex;
514 chain_dma_off = ioc->req_sz * chain_idx;
515
516 /* Populate the chainSGE for the current buffer.
517 * - Set chain buffer pointer to psge and fill
518 * out the Address and Flags fields.
519 */
520 chainSge = (char *) psge;
521 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
522 psge, req_idx));
523
524 /* Start the SGE for the next buffer
525 */
526 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
527 sgeOffset = 0;
528 sg_done = 0;
529
530 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
531 psge, chain_idx));
532
533 /* Start the SGE for the next buffer
534 */
535
536 goto nextSGEset;
537 }
538
539 return SUCCESS;
540} /* mptscsih_AddSGE() */
541
542/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
543/*
544 * mptscsih_io_done - Main SCSI IO callback routine registered to
545 * Fusion MPT (base) driver
546 * @ioc: Pointer to MPT_ADAPTER structure
547 * @mf: Pointer to original MPT request frame
548 * @r: Pointer to MPT reply frame (NULL if TurboReply)
549 *
550 * This routine is called from mpt.c::mpt_interrupt() at the completion
551 * of any SCSI IO request.
552 * This routine is registered with the Fusion MPT (base) driver at driver
553 * load/init time via the mpt_register() API call.
554 *
555 * Returns 1 indicating alloc'd request frame ptr should be freed.
556 */
0d0c7974 557int
1da177e4
LT
558mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
559{
560 struct scsi_cmnd *sc;
561 MPT_SCSI_HOST *hd;
562 SCSIIORequest_t *pScsiReq;
563 SCSIIOReply_t *pScsiReply;
564 u16 req_idx;
565
566 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
567
568 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
569 sc = hd->ScsiLookup[req_idx];
570 if (sc == NULL) {
571 MPIHeader_t *hdr = (MPIHeader_t *)mf;
572
573 /* Remark: writeSDP1 will use the ScsiDoneCtx
574 * If a SCSI I/O cmd, device disabled by OS and
575 * completion done. Cannot touch sc struct. Just free mem.
576 */
577 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
578 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
579 ioc->name);
580
581 mptscsih_freeChainBuffers(ioc, req_idx);
582 return 1;
583 }
584
1da177e4
LT
585 sc->result = DID_OK << 16; /* Set default reply as OK */
586 pScsiReq = (SCSIIORequest_t *) mf;
587 pScsiReply = (SCSIIOReply_t *) mr;
588
c6678e0c
CH
589 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
590 dmfprintk((MYIOC_s_INFO_FMT
591 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
592 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
593 }else{
594 dmfprintk((MYIOC_s_INFO_FMT
595 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
596 ioc->name, mf, mr, sc, req_idx));
597 }
598
1da177e4
LT
599 if (pScsiReply == NULL) {
600 /* special context reply handling */
601 ;
602 } else {
603 u32 xfer_cnt;
604 u16 status;
605 u8 scsi_state, scsi_status;
606
607 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
608 scsi_state = pScsiReply->SCSIState;
609 scsi_status = pScsiReply->SCSIStatus;
610 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
611 sc->resid = sc->request_bufflen - xfer_cnt;
612
466544d8
MED
613 /*
614 * if we get a data underrun indication, yet no data was
615 * transferred and the SCSI status indicates that the
616 * command was never started, change the data underrun
617 * to success
618 */
619 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
620 (scsi_status == MPI_SCSI_STATUS_BUSY ||
621 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
622 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
623 status = MPI_IOCSTATUS_SUCCESS;
624 }
625
1da177e4
LT
626 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
627 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
628 "resid=%d bufflen=%d xfer_cnt=%d\n",
c7c82987 629 ioc->id, sc->device->id, sc->device->lun,
466544d8 630 status, scsi_state, scsi_status, sc->resid,
1da177e4
LT
631 sc->request_bufflen, xfer_cnt));
632
633 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
0d0c7974
MED
634 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
635
1da177e4
LT
636 /*
637 * Look for + dump FCP ResponseInfo[]!
638 */
466544d8
MED
639 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
640 pScsiReply->ResponseInfo) {
641 printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
642 "FCP_ResponseInfo=%08xh\n",
c7c82987 643 ioc->id, sc->device->id, sc->device->lun,
1da177e4
LT
644 le32_to_cpu(pScsiReply->ResponseInfo));
645 }
646
647 switch(status) {
648 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
649 /* CHECKME!
650 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
651 * But not: DID_BUS_BUSY lest one risk
652 * killing interrupt handler:-(
653 */
654 sc->result = SAM_STAT_BUSY;
655 break;
656
657 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
658 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
659 sc->result = DID_BAD_TARGET << 16;
660 break;
661
662 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
663 /* Spoof to SCSI Selection Timeout! */
664 sc->result = DID_NO_CONNECT << 16;
665
666 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
667 hd->sel_timeout[pScsiReq->TargetID]++;
668 break;
669
670 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
671 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
672 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
673 /* Linux handles an unsolicited DID_RESET better
674 * than an unsolicited DID_ABORT.
675 */
676 sc->result = DID_RESET << 16;
677
678 /* GEM Workaround. */
a9b2937a 679 if (ioc->bus_type == SPI)
c7c82987 680 mptscsih_no_negotiate(hd, sc);
1da177e4
LT
681 break;
682
683 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
466544d8
MED
684 sc->resid = sc->request_bufflen - xfer_cnt;
685 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
686 sc->result=DID_SOFT_ERROR << 16;
687 else /* Sufficient data transfer occurred */
1da177e4 688 sc->result = (DID_OK << 16) | scsi_status;
466544d8
MED
689 dreplyprintk((KERN_NOTICE
690 "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
1da177e4 691 break;
0d0c7974 692
1da177e4
LT
693 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
694 /*
695 * Do upfront check for valid SenseData and give it
696 * precedence!
697 */
698 sc->result = (DID_OK << 16) | scsi_status;
699 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
700 /* Have already saved the status and sense data
701 */
702 ;
703 } else {
704 if (xfer_cnt < sc->underflow) {
466544d8
MED
705 if (scsi_status == SAM_STAT_BUSY)
706 sc->result = SAM_STAT_BUSY;
707 else
708 sc->result = DID_SOFT_ERROR << 16;
1da177e4
LT
709 }
710 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
711 /* What to do?
712 */
713 sc->result = DID_SOFT_ERROR << 16;
714 }
715 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
716 /* Not real sure here either... */
717 sc->result = DID_RESET << 16;
718 }
719 }
720
721 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
722 sc->underflow));
723 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
724 /* Report Queue Full
725 */
726 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
727 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
0d0c7974 728
1da177e4
LT
729 break;
730
731 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
732 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
466544d8
MED
733 if (scsi_status == MPI_SCSI_STATUS_BUSY)
734 sc->result = (DID_BUS_BUSY << 16) | scsi_status;
735 else
736 sc->result = (DID_OK << 16) | scsi_status;
1da177e4
LT
737 if (scsi_state == 0) {
738 ;
739 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
740 /*
741 * If running against circa 200003dd 909 MPT f/w,
742 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
743 * (QUEUE_FULL) returned from device! --> get 0x0000?128
744 * and with SenseBytes set to 0.
745 */
746 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
747 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
748
749 }
750 else if (scsi_state &
751 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
752 ) {
753 /*
754 * What to do?
755 */
756 sc->result = DID_SOFT_ERROR << 16;
757 }
758 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
759 /* Not real sure here either... */
760 sc->result = DID_RESET << 16;
761 }
762 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
763 /* Device Inq. data indicates that it supports
764 * QTags, but rejects QTag messages.
765 * This command completed OK.
766 *
767 * Not real sure here either so do nothing... */
768 }
769
770 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
771 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
772
773 /* Add handling of:
774 * Reservation Conflict, Busy,
775 * Command Terminated, CHECK
776 */
777 break;
778
779 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
780 sc->result = DID_SOFT_ERROR << 16;
781 break;
782
783 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
784 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
785 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
786 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
787 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
788 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
789 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
790 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
791 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
792 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
793 default:
794 /*
795 * What to do?
796 */
797 sc->result = DID_SOFT_ERROR << 16;
798 break;
799
800 } /* switch(status) */
801
802 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
803 } /* end of address reply case */
804
805 /* Unmap the DMA buffers, if any. */
806 if (sc->use_sg) {
807 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
808 sc->use_sg, sc->sc_data_direction);
809 } else if (sc->request_bufflen) {
810 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
811 sc->request_bufflen, sc->sc_data_direction);
812 }
813
814 hd->ScsiLookup[req_idx] = NULL;
815
816 sc->scsi_done(sc); /* Issue the command callback */
817
818 /* Free Chain buffers */
819 mptscsih_freeChainBuffers(ioc, req_idx);
820 return 1;
821}
822
1da177e4
LT
823/*
824 * mptscsih_flush_running_cmds - For each command found, search
825 * Scsi_Host instance taskQ and reply to OS.
826 * Called only if recovering from a FW reload.
827 * @hd: Pointer to a SCSI HOST structure
828 *
829 * Returns: None.
830 *
831 * Must be called while new I/Os are being queued.
832 */
833static void
834mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
835{
836 MPT_ADAPTER *ioc = hd->ioc;
837 struct scsi_cmnd *SCpnt;
838 MPT_FRAME_HDR *mf;
839 int ii;
840 int max = ioc->req_depth;
841
842 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
843 for (ii= 0; ii < max; ii++) {
844 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
845
846 /* Command found.
847 */
848
849 /* Null ScsiLookup index
850 */
851 hd->ScsiLookup[ii] = NULL;
852
853 mf = MPT_INDEX_2_MFPTR(ioc, ii);
854 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
855 mf, SCpnt));
856
857 /* Set status, free OS resources (SG DMA buffers)
858 * Do OS callback
859 * Free driver resources (chain, msg buffers)
860 */
0d0c7974
MED
861 if (SCpnt->use_sg) {
862 pci_unmap_sg(ioc->pcidev,
863 (struct scatterlist *) SCpnt->request_buffer,
864 SCpnt->use_sg,
865 SCpnt->sc_data_direction);
866 } else if (SCpnt->request_bufflen) {
867 pci_unmap_single(ioc->pcidev,
868 SCpnt->SCp.dma_handle,
869 SCpnt->request_bufflen,
870 SCpnt->sc_data_direction);
1da177e4
LT
871 }
872 SCpnt->result = DID_RESET << 16;
873 SCpnt->host_scribble = NULL;
874
875 /* Free Chain buffers */
876 mptscsih_freeChainBuffers(ioc, ii);
877
878 /* Free Message frames */
879 mpt_free_msg_frame(ioc, mf);
880
881 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
882 }
883 }
884
885 return;
886}
887
888/*
889 * mptscsih_search_running_cmds - Delete any commands associated
890 * with the specified target and lun. Function called only
891 * when a lun is disable by mid-layer.
892 * Do NOT access the referenced scsi_cmnd structure or
893 * members. Will cause either a paging or NULL ptr error.
05e8ec17 894 * (BUT, BUT, BUT, the code does reference it! - mdr)
c7c82987
MED
895 * @hd: Pointer to a SCSI HOST structure
896 * @vdevice: per device private data
1da177e4
LT
897 *
898 * Returns: None.
899 *
900 * Called from slave_destroy.
901 */
902static void
c7c82987 903mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1da177e4
LT
904{
905 SCSIIORequest_t *mf = NULL;
906 int ii;
907 int max = hd->ioc->req_depth;
466544d8 908 struct scsi_cmnd *sc;
1da177e4
LT
909
910 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
c7c82987 911 vdevice->target_id, vdevice->lun, max));
1da177e4
LT
912
913 for (ii=0; ii < max; ii++) {
466544d8 914 if ((sc = hd->ScsiLookup[ii]) != NULL) {
1da177e4
LT
915
916 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
917
918 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
919 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
920
c7c82987 921 if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
1da177e4
LT
922 continue;
923
924 /* Cleanup
925 */
926 hd->ScsiLookup[ii] = NULL;
927 mptscsih_freeChainBuffers(hd->ioc, ii);
928 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
466544d8
MED
929 if (sc->use_sg) {
930 pci_unmap_sg(hd->ioc->pcidev,
931 (struct scatterlist *) sc->request_buffer,
932 sc->use_sg,
933 sc->sc_data_direction);
934 } else if (sc->request_bufflen) {
935 pci_unmap_single(hd->ioc->pcidev,
936 sc->SCp.dma_handle,
937 sc->request_bufflen,
938 sc->sc_data_direction);
939 }
940 sc->host_scribble = NULL;
941 sc->result = DID_NO_CONNECT << 16;
942 sc->scsi_done(sc);
1da177e4
LT
943 }
944 }
1da177e4
LT
945 return;
946}
947
948/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
949
950/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
951/*
952 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
953 * from a SCSI target device.
954 * @sc: Pointer to scsi_cmnd structure
955 * @pScsiReply: Pointer to SCSIIOReply_t
956 * @pScsiReq: Pointer to original SCSI request
957 *
958 * This routine periodically reports QUEUE_FULL status returned from a
959 * SCSI target device. It reports this to the console via kernel
960 * printk() API call, not more than once every 10 seconds.
961 */
962static void
963mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
964{
965 long time = jiffies;
1da177e4 966 MPT_SCSI_HOST *hd;
1da177e4 967
0d0c7974
MED
968 if (sc->device == NULL)
969 return;
970 if (sc->device->host == NULL)
971 return;
972 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
973 return;
1da177e4 974
0d0c7974
MED
975 if (time - hd->last_queue_full > 10 * HZ) {
976 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
977 hd->ioc->name, 0, sc->device->id, sc->device->lun));
978 hd->last_queue_full = time;
1da177e4 979 }
1da177e4
LT
980}
981
982/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
983/*
984 * mptscsih_remove - Removed scsi devices
985 * @pdev: Pointer to pci_dev structure
986 *
987 *
988 */
0d0c7974 989void
1da177e4
LT
990mptscsih_remove(struct pci_dev *pdev)
991{
992 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
993 struct Scsi_Host *host = ioc->sh;
994 MPT_SCSI_HOST *hd;
f2ea8671 995#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1da177e4
LT
996 int count;
997 unsigned long flags;
c7c82987 998#endif
0d0c7974 999 int sz1;
1da177e4 1000
466544d8
MED
1001 if(!host) {
1002 mpt_detach(pdev);
1da177e4 1003 return;
466544d8 1004 }
1da177e4
LT
1005
1006 scsi_remove_host(host);
1007
0d0c7974
MED
1008 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1009 return;
1010
1da177e4
LT
1011#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1012 /* Check DV thread active */
1013 count = 10 * HZ;
1014 spin_lock_irqsave(&dvtaskQ_lock, flags);
1015 if (dvtaskQ_active) {
1016 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
6521018d
NA
1017 while(dvtaskQ_active && --count)
1018 schedule_timeout_interruptible(1);
1da177e4
LT
1019 } else {
1020 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1021 }
1022 if (!count)
1023 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
1024#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
1025 else
1026 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
1027#endif
1028#endif
1029
d18c3db5 1030 mptscsih_shutdown(pdev);
1da177e4 1031
0d0c7974 1032 sz1=0;
1da177e4 1033
0d0c7974
MED
1034 if (hd->ScsiLookup != NULL) {
1035 sz1 = hd->ioc->req_depth * sizeof(void *);
1036 kfree(hd->ScsiLookup);
1037 hd->ScsiLookup = NULL;
1038 }
1da177e4 1039
d485eb83
MED
1040 /*
1041 * Free pointer array.
1042 */
1043 kfree(hd->Targets);
1044 hd->Targets = NULL;
1da177e4 1045
0d0c7974
MED
1046 dprintk((MYIOC_s_INFO_FMT
1047 "Free'd ScsiLookup (%d) memory\n",
1048 hd->ioc->name, sz1));
1da177e4 1049
d485eb83 1050 kfree(hd->info_kbuf);
1da177e4 1051
0d0c7974
MED
1052 /* NULL the Scsi_Host pointer
1053 */
1054 hd->ioc->sh = NULL;
1da177e4
LT
1055
1056 scsi_host_put(host);
1da177e4 1057
0d0c7974 1058 mpt_detach(pdev);
c6678e0c 1059
1da177e4
LT
1060}
1061
1062/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1063/*
1064 * mptscsih_shutdown - reboot notifier
1065 *
1066 */
0d0c7974 1067void
d18c3db5 1068mptscsih_shutdown(struct pci_dev *pdev)
1da177e4 1069{
d18c3db5 1070 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1da177e4
LT
1071 struct Scsi_Host *host = ioc->sh;
1072 MPT_SCSI_HOST *hd;
1073
1074 if(!host)
1075 return;
1076
1077 hd = (MPT_SCSI_HOST *)host->hostdata;
1078
1da177e4
LT
1079}
1080
1081#ifdef CONFIG_PM
1082/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1083/*
0d0c7974 1084 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1da177e4
LT
1085 *
1086 *
1087 */
0d0c7974 1088int
8d189f72 1089mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1da177e4 1090{
d18c3db5 1091 mptscsih_shutdown(pdev);
0d0c7974 1092 return mpt_suspend(pdev,state);
1da177e4
LT
1093}
1094
1095/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1096/*
1097 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1098 *
1099 *
1100 */
0d0c7974 1101int
1da177e4
LT
1102mptscsih_resume(struct pci_dev *pdev)
1103{
1104 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1105 struct Scsi_Host *host = ioc->sh;
1106 MPT_SCSI_HOST *hd;
1107
0d0c7974 1108 mpt_resume(pdev);
c6678e0c 1109
1da177e4
LT
1110 if(!host)
1111 return 0;
1112
1113 hd = (MPT_SCSI_HOST *)host->hostdata;
1114 if(!hd)
1115 return 0;
1116
1117#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1118 {
1119 unsigned long lflags;
1120 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1121 if (!dvtaskQ_active) {
1122 dvtaskQ_active = 1;
1123 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
0d0c7974 1124 INIT_WORK(&dvTaskQ_task,
1da177e4 1125 mptscsih_domainValidation, (void *) hd);
0d0c7974 1126 schedule_work(&dvTaskQ_task);
1da177e4
LT
1127 } else {
1128 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1129 }
1130 }
1131#endif
1132 return 0;
1133}
1134
1135#endif
1136
1da177e4
LT
1137/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1138/**
1139 * mptscsih_info - Return information about MPT adapter
1140 * @SChost: Pointer to Scsi_Host structure
1141 *
1142 * (linux scsi_host_template.info routine)
1143 *
1144 * Returns pointer to buffer where information was written.
1145 */
0d0c7974 1146const char *
1da177e4
LT
1147mptscsih_info(struct Scsi_Host *SChost)
1148{
1149 MPT_SCSI_HOST *h;
1150 int size = 0;
1151
1da177e4 1152 h = (MPT_SCSI_HOST *)SChost->hostdata;
0d0c7974 1153
1da177e4 1154 if (h) {
0d0c7974
MED
1155 if (h->info_kbuf == NULL)
1156 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1157 return h->info_kbuf;
1158 h->info_kbuf[0] = '\0';
1159
1160 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1161 h->info_kbuf[size-1] = '\0';
1da177e4
LT
1162 }
1163
0d0c7974 1164 return h->info_kbuf;
1da177e4
LT
1165}
1166
1167struct info_str {
1168 char *buffer;
1169 int length;
1170 int offset;
1171 int pos;
1172};
1173
0d0c7974
MED
1174static void
1175mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1da177e4
LT
1176{
1177 if (info->pos + len > info->length)
1178 len = info->length - info->pos;
1179
1180 if (info->pos + len < info->offset) {
1181 info->pos += len;
1182 return;
1183 }
1184
1185 if (info->pos < info->offset) {
1186 data += (info->offset - info->pos);
1187 len -= (info->offset - info->pos);
1188 }
1189
1190 if (len > 0) {
1191 memcpy(info->buffer + info->pos, data, len);
1192 info->pos += len;
1193 }
1194}
1195
0d0c7974
MED
1196static int
1197mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1da177e4
LT
1198{
1199 va_list args;
1200 char buf[81];
1201 int len;
1202
1203 va_start(args, fmt);
1204 len = vsprintf(buf, fmt, args);
1205 va_end(args);
1206
0d0c7974 1207 mptscsih_copy_mem_info(info, buf, len);
1da177e4
LT
1208 return len;
1209}
1210
0d0c7974
MED
1211static int
1212mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1da177e4
LT
1213{
1214 struct info_str info;
1215
1216 info.buffer = pbuf;
1217 info.length = len;
1218 info.offset = offset;
1219 info.pos = 0;
1220
0d0c7974
MED
1221 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1222 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1223 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1224 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1da177e4
LT
1225
1226 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1227}
1228
1229/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1230/**
1231 * mptscsih_proc_info - Return information about MPT adapter
1232 *
1233 * (linux scsi_host_template.info routine)
1234 *
1235 * buffer: if write, user data; if read, buffer for user
1236 * length: if write, return length;
1237 * offset: if write, 0; if read, the current offset into the buffer from
1238 * the previous read.
1239 * hostno: scsi host number
1240 * func: if write = 1; if read = 0
1241 */
0d0c7974 1242int
1da177e4
LT
1243mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1244 int length, int func)
1245{
1246 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1247 MPT_ADAPTER *ioc = hd->ioc;
1248 int size = 0;
1249
1250 if (func) {
c6678e0c
CH
1251 /*
1252 * write is not supported
1da177e4
LT
1253 */
1254 } else {
1255 if (start)
1256 *start = buffer;
1257
1258 size = mptscsih_host_info(ioc, buffer, offset, length);
1259 }
1260
1261 return size;
1262}
1263
1264/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1265#define ADD_INDEX_LOG(req_ent) do { } while(0)
1266
1267/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1268/**
1269 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1270 * @SCpnt: Pointer to scsi_cmnd structure
1271 * @done: Pointer SCSI mid-layer IO completion function
1272 *
1273 * (linux scsi_host_template.queuecommand routine)
1274 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1275 * from a linux scsi_cmnd request and send it to the IOC.
1276 *
1277 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1278 */
0d0c7974 1279int
1da177e4
LT
1280mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1281{
1282 MPT_SCSI_HOST *hd;
1283 MPT_FRAME_HDR *mf;
1284 SCSIIORequest_t *pScsiReq;
c7c82987 1285 VirtDevice *vdev = SCpnt->device->hostdata;
1da177e4
LT
1286 int lun;
1287 u32 datalen;
1288 u32 scsictl;
1289 u32 scsidir;
1290 u32 cmd_len;
1291 int my_idx;
1292 int ii;
1293
1294 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1da177e4
LT
1295 lun = SCpnt->device->lun;
1296 SCpnt->scsi_done = done;
1297
1da177e4
LT
1298 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1299 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1300
1301 if (hd->resetPending) {
1302 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1303 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1304 return SCSI_MLQUEUE_HOST_BUSY;
1305 }
1306
1307 /*
1308 * Put together a MPT SCSI request...
1309 */
0d0c7974 1310 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1da177e4
LT
1311 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1312 hd->ioc->name));
1313 return SCSI_MLQUEUE_HOST_BUSY;
1314 }
1315
1316 pScsiReq = (SCSIIORequest_t *) mf;
1317
1318 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1319
1320 ADD_INDEX_LOG(my_idx);
1321
0d0c7974 1322 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1da177e4
LT
1323 * Seems we may receive a buffer (datalen>0) even when there
1324 * will be no data transfer! GRRRRR...
1325 */
1326 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1327 datalen = SCpnt->request_bufflen;
1328 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1329 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1330 datalen = SCpnt->request_bufflen;
1331 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1332 } else {
1333 datalen = 0;
1334 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1335 }
1336
1337 /* Default to untagged. Once a target structure has been allocated,
1338 * use the Inquiry data to determine if device supports tagged.
1339 */
c7c82987
MED
1340 if (vdev
1341 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1da177e4
LT
1342 && (SCpnt->device->tagged_supported)) {
1343 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1344 } else {
1345 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1346 }
1347
1348 /* Use the above information to set up the message frame
1349 */
c7c82987
MED
1350 pScsiReq->TargetID = (u8) vdev->target_id;
1351 pScsiReq->Bus = vdev->bus_id;
1da177e4
LT
1352 pScsiReq->ChainOffset = 0;
1353 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1354 pScsiReq->CDBLength = SCpnt->cmd_len;
1355 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1356 pScsiReq->Reserved = 0;
1357 pScsiReq->MsgFlags = mpt_msg_flags();
1358 pScsiReq->LUN[0] = 0;
1359 pScsiReq->LUN[1] = lun;
1360 pScsiReq->LUN[2] = 0;
1361 pScsiReq->LUN[3] = 0;
1362 pScsiReq->LUN[4] = 0;
1363 pScsiReq->LUN[5] = 0;
1364 pScsiReq->LUN[6] = 0;
1365 pScsiReq->LUN[7] = 0;
1366 pScsiReq->Control = cpu_to_le32(scsictl);
1367
1368 /*
1369 * Write SCSI CDB into the message
1370 */
1371 cmd_len = SCpnt->cmd_len;
1372 for (ii=0; ii < cmd_len; ii++)
1373 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1374
1375 for (ii=cmd_len; ii < 16; ii++)
1376 pScsiReq->CDB[ii] = 0;
1377
1378 /* DataLength */
1379 pScsiReq->DataLength = cpu_to_le32(datalen);
1380
1381 /* SenseBuffer low address */
1382 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1383 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1384
1385 /* Now add the SG list
1386 * Always have a SGE even if null length.
1387 */
1388 if (datalen == 0) {
1389 /* Add a NULL SGE */
1390 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1391 (dma_addr_t) -1);
1392 } else {
1393 /* Add a 32 or 64 bit SGE */
1394 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1395 goto fail;
1396 }
1397
1398 hd->ScsiLookup[my_idx] = SCpnt;
1399 SCpnt->host_scribble = NULL;
1400
1401#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
a9b2937a 1402 if (hd->ioc->bus_type == SPI) {
c7c82987 1403 int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id];
1da177e4
LT
1404 int issueCmd = 1;
1405
1406 if (dvStatus || hd->ioc->spi_data.forceDv) {
1407
1408 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
1409 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
1410 unsigned long lflags;
1411 /* Schedule DV if necessary */
1412 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1413 if (!dvtaskQ_active) {
1414 dvtaskQ_active = 1;
1415 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
0d0c7974 1416 INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
1da177e4 1417
0d0c7974 1418 schedule_work(&dvTaskQ_task);
1da177e4
LT
1419 } else {
1420 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1421 }
1422 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
1423 }
1424
1425 /* Trying to do DV to this target, extend timeout.
1426 * Wait to issue until flag is clear
1427 */
1428 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
1429 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
1430 issueCmd = 0;
1431 }
1432
1433 /* Set the DV flags.
1434 */
1435 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
c7c82987 1436 mptscsih_set_dvflags(hd, SCpnt);
1da177e4
LT
1437
1438 if (!issueCmd)
1439 goto fail;
1440 }
1441 }
1442#endif
1443
0d0c7974 1444 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1da177e4
LT
1445 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1446 hd->ioc->name, SCpnt, mf, my_idx));
1447 DBG_DUMP_REQUEST_FRAME(mf)
1448 return 0;
1449
1450 fail:
466544d8 1451 hd->ScsiLookup[my_idx] = NULL;
1da177e4
LT
1452 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1453 mpt_free_msg_frame(hd->ioc, mf);
1454 return SCSI_MLQUEUE_HOST_BUSY;
1455}
1456
1457/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1458/*
1459 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1460 * with a SCSI IO request
1461 * @hd: Pointer to the MPT_SCSI_HOST instance
1462 * @req_idx: Index of the SCSI IO request frame.
1463 *
1464 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1465 * No return.
1466 */
1467static void
1468mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1469{
1470 MPT_FRAME_HDR *chain;
1471 unsigned long flags;
1472 int chain_idx;
1473 int next;
1474
1475 /* Get the first chain index and reset
1476 * tracker state.
1477 */
1478 chain_idx = ioc->ReqToChain[req_idx];
1479 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1480
1481 while (chain_idx != MPT_HOST_NO_CHAIN) {
1482
1483 /* Save the next chain buffer index */
1484 next = ioc->ChainToChain[chain_idx];
1485
1486 /* Free this chain buffer and reset
1487 * tracker
1488 */
1489 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1490
1491 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1492 + (chain_idx * ioc->req_sz));
1493
1494 spin_lock_irqsave(&ioc->FreeQlock, flags);
1495 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1496 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1497
1498 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1499 ioc->name, chain_idx));
1500
1501 /* handle next */
1502 chain_idx = next;
1503 }
1504 return;
1505}
1506
1507/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1508/*
1509 * Reset Handling
1510 */
1511
1512/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1513/*
1514 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1515 * Fall through to mpt_HardResetHandler if: not operational, too many
1516 * failed TM requests or handshake failure.
1517 *
1518 * @ioc: Pointer to MPT_ADAPTER structure
1519 * @type: Task Management type
1520 * @target: Logical Target ID for reset (if appropriate)
1521 * @lun: Logical Unit for reset (if appropriate)
1522 * @ctx2abort: Context for the task to be aborted (if appropriate)
1523 *
1524 * Remark: Currently invoked from a non-interrupt thread (_bh).
1525 *
1526 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1527 * will be active.
1528 *
1529 * Returns 0 for SUCCESS or -1 if FAILED.
1530 */
1531static int
1532mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1533{
1534 MPT_ADAPTER *ioc;
1535 int rc = -1;
1536 int doTask = 1;
1537 u32 ioc_raw_state;
1538 unsigned long flags;
1539
1540 /* If FW is being reloaded currently, return success to
1541 * the calling function.
1542 */
1543 if (hd == NULL)
1544 return 0;
1545
1546 ioc = hd->ioc;
1547 if (ioc == NULL) {
1548 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1549 return FAILED;
1550 }
1551 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1552
1553 // SJR - CHECKME - Can we avoid this here?
1554 // (mpt_HardResetHandler has this check...)
1555 spin_lock_irqsave(&ioc->diagLock, flags);
1556 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1557 spin_unlock_irqrestore(&ioc->diagLock, flags);
1558 return FAILED;
1559 }
1560 spin_unlock_irqrestore(&ioc->diagLock, flags);
1561
1562 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1563 * If we time out and not bus reset, then we return a FAILED status to the caller.
1564 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1565 * successful. Otherwise, reload the FW.
1566 */
1567 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1568 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
c6678e0c 1569 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1da177e4
LT
1570 "Timed out waiting for last TM (%d) to complete! \n",
1571 hd->ioc->name, hd->tmPending));
1572 return FAILED;
1573 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
c6678e0c 1574 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
1da177e4
LT
1575 "Timed out waiting for last TM (%d) to complete! \n",
1576 hd->ioc->name, hd->tmPending));
1577 return FAILED;
1578 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
c6678e0c 1579 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1da177e4
LT
1580 "Timed out waiting for last TM (%d) to complete! \n",
1581 hd->ioc->name, hd->tmPending));
1582 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1583 return FAILED;
1584
1585 doTask = 0;
1586 }
1587 } else {
1588 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1589 hd->tmPending |= (1 << type);
1590 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1591 }
1592
1593 /* Is operational?
1594 */
1595 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1596
1597#ifdef MPT_DEBUG_RESET
1598 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1599 printk(MYIOC_s_WARN_FMT
1600 "TM Handler: IOC Not operational(0x%x)!\n",
1601 hd->ioc->name, ioc_raw_state);
1602 }
1603#endif
1604
1605 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1606 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1607
1608 /* Isse the Task Mgmt request.
1609 */
1610 if (hd->hard_resets < -1)
1611 hd->hard_resets++;
1612 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1613 if (rc) {
1614 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1615 } else {
1616 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1617 }
1618 }
1619
1620 /* Only fall through to the HRH if this is a bus reset
1621 */
1622 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1623 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1624 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1625 hd->ioc->name));
1626 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1627 }
1628
1629 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1630
1631 return rc;
1632}
1633
1634
1635/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1636/*
1637 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1638 * @hd: Pointer to MPT_SCSI_HOST structure
1639 * @type: Task Management type
1640 * @target: Logical Target ID for reset (if appropriate)
1641 * @lun: Logical Unit for reset (if appropriate)
1642 * @ctx2abort: Context for the task to be aborted (if appropriate)
1643 *
1644 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1645 * or a non-interrupt thread. In the former, must not call schedule().
1646 *
1647 * Not all fields are meaningfull for all task types.
1648 *
1649 * Returns 0 for SUCCESS, -999 for "no msg frames",
1650 * else other non-zero value returned.
1651 */
1652static int
1653mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1654{
1655 MPT_FRAME_HDR *mf;
1656 SCSITaskMgmt_t *pScsiTm;
1657 int ii;
1658 int retval;
1659
1660 /* Return Fail to calling function if no message frames available.
1661 */
0d0c7974 1662 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1da177e4
LT
1663 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1664 hd->ioc->name));
c6678e0c 1665 return FAILED;
1da177e4
LT
1666 }
1667 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1668 hd->ioc->name, mf));
1669
1670 /* Format the Request
1671 */
1672 pScsiTm = (SCSITaskMgmt_t *) mf;
1673 pScsiTm->TargetID = target;
1674 pScsiTm->Bus = channel;
1675 pScsiTm->ChainOffset = 0;
1676 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1677
1678 pScsiTm->Reserved = 0;
1679 pScsiTm->TaskType = type;
1680 pScsiTm->Reserved1 = 0;
1681 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1682 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1683
1684 for (ii= 0; ii < 8; ii++) {
1685 pScsiTm->LUN[ii] = 0;
1686 }
1687 pScsiTm->LUN[1] = lun;
1688
1689 for (ii=0; ii < 7; ii++)
1690 pScsiTm->Reserved2[ii] = 0;
1691
1692 pScsiTm->TaskMsgContext = ctx2abort;
1693
c6678e0c
CH
1694 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1695 hd->ioc->name, ctx2abort, type));
1da177e4
LT
1696
1697 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1698
0d0c7974 1699 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1da177e4
LT
1700 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1701 CAN_SLEEP)) != 0) {
1702 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1703 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1704 hd->ioc, mf));
1705 mpt_free_msg_frame(hd->ioc, mf);
1706 return retval;
1707 }
1708
1709 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1710 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1711 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1712 hd->ioc, mf));
1713 mpt_free_msg_frame(hd->ioc, mf);
1714 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1715 hd->ioc->name));
1716 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1717 }
1718
1719 return retval;
1720}
1721
1722/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1723/**
1724 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1725 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1726 *
1727 * (linux scsi_host_template.eh_abort_handler routine)
1728 *
1729 * Returns SUCCESS or FAILED.
1730 */
0d0c7974 1731int
1da177e4
LT
1732mptscsih_abort(struct scsi_cmnd * SCpnt)
1733{
1734 MPT_SCSI_HOST *hd;
1735 MPT_ADAPTER *ioc;
1736 MPT_FRAME_HDR *mf;
1737 u32 ctx2abort;
1738 int scpnt_idx;
466544d8 1739 int retval;
c7c82987 1740 VirtDevice *vdev;
1da177e4
LT
1741
1742 /* If we can't locate our host adapter structure, return FAILED status.
1743 */
1744 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1745 SCpnt->result = DID_RESET << 16;
1746 SCpnt->scsi_done(SCpnt);
466544d8 1747 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1da177e4
LT
1748 "Can't locate host! (sc=%p)\n",
1749 SCpnt));
1750 return FAILED;
1751 }
1752
1753 ioc = hd->ioc;
466544d8 1754 if (hd->resetPending) {
1da177e4 1755 return FAILED;
466544d8 1756 }
1da177e4
LT
1757
1758 if (hd->timeouts < -1)
1759 hd->timeouts++;
1760
1761 /* Find this command
1762 */
1763 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
466544d8 1764 /* Cmd not found in ScsiLookup.
1da177e4
LT
1765 * Do OS callback.
1766 */
1767 SCpnt->result = DID_RESET << 16;
466544d8 1768 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1da177e4
LT
1769 "Command not in the active list! (sc=%p)\n",
1770 hd->ioc->name, SCpnt));
1771 return SUCCESS;
1772 }
1773
466544d8
MED
1774 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1775 hd->ioc->name, SCpnt);
1776 scsi_print_command(SCpnt);
1777
1da177e4
LT
1778 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1779 * (the IO to be ABORT'd)
1780 *
1781 * NOTE: Since we do not byteswap MsgContext, we do not
1782 * swap it here either. It is an opaque cookie to
1783 * the controller, so it does not matter. -DaveM
1784 */
1785 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1786 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1787
1788 hd->abortSCpnt = SCpnt;
1789
c7c82987 1790 vdev = SCpnt->device->hostdata;
466544d8 1791 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
c7c82987 1792 vdev->bus_id, vdev->target_id, vdev->lun,
466544d8 1793 ctx2abort, 2 /* 2 second timeout */);
1da177e4 1794
466544d8
MED
1795 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1796 hd->ioc->name,
1797 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1da177e4 1798
466544d8
MED
1799 if (retval == 0)
1800 return SUCCESS;
1801
1802 if(retval != FAILED ) {
1da177e4
LT
1803 hd->tmPending = 0;
1804 hd->tmState = TM_STATE_NONE;
1da177e4 1805 }
466544d8 1806 return FAILED;
1da177e4
LT
1807}
1808
1809/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1810/**
1811 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1812 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1813 *
1814 * (linux scsi_host_template.eh_dev_reset_handler routine)
1815 *
1816 * Returns SUCCESS or FAILED.
1817 */
0d0c7974 1818int
1da177e4
LT
1819mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1820{
1821 MPT_SCSI_HOST *hd;
466544d8 1822 int retval;
c7c82987 1823 VirtDevice *vdev;
1da177e4
LT
1824
1825 /* If we can't locate our host adapter structure, return FAILED status.
1826 */
1827 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
466544d8 1828 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1da177e4
LT
1829 "Can't locate host! (sc=%p)\n",
1830 SCpnt));
1831 return FAILED;
1832 }
1833
1834 if (hd->resetPending)
1835 return FAILED;
1836
466544d8 1837 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1da177e4 1838 hd->ioc->name, SCpnt);
466544d8 1839 scsi_print_command(SCpnt);
1da177e4 1840
c7c82987 1841 vdev = SCpnt->device->hostdata;
466544d8 1842 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
c7c82987 1843 vdev->bus_id, vdev->target_id,
466544d8
MED
1844 0, 0, 5 /* 5 second timeout */);
1845
1846 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1847 hd->ioc->name,
1848 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1849
1850 if (retval == 0)
1851 return SUCCESS;
1852
1853 if(retval != FAILED ) {
1da177e4
LT
1854 hd->tmPending = 0;
1855 hd->tmState = TM_STATE_NONE;
1da177e4 1856 }
466544d8 1857 return FAILED;
1da177e4
LT
1858}
1859
1860/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1861/**
1862 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1863 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1864 *
1865 * (linux scsi_host_template.eh_bus_reset_handler routine)
1866 *
1867 * Returns SUCCESS or FAILED.
1868 */
0d0c7974 1869int
1da177e4
LT
1870mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1871{
1872 MPT_SCSI_HOST *hd;
466544d8 1873 int retval;
c7c82987 1874 VirtDevice *vdev;
1da177e4
LT
1875
1876 /* If we can't locate our host adapter structure, return FAILED status.
1877 */
1878 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
466544d8 1879 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1da177e4
LT
1880 "Can't locate host! (sc=%p)\n",
1881 SCpnt ) );
1882 return FAILED;
1883 }
1884
466544d8 1885 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1da177e4 1886 hd->ioc->name, SCpnt);
466544d8 1887 scsi_print_command(SCpnt);
1da177e4
LT
1888
1889 if (hd->timeouts < -1)
1890 hd->timeouts++;
1891
c7c82987 1892 vdev = SCpnt->device->hostdata;
466544d8 1893 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
c7c82987 1894 vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */);
1da177e4 1895
466544d8
MED
1896 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1897 hd->ioc->name,
1898 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1899
1900 if (retval == 0)
1901 return SUCCESS;
1902
1903 if(retval != FAILED ) {
1da177e4
LT
1904 hd->tmPending = 0;
1905 hd->tmState = TM_STATE_NONE;
1da177e4 1906 }
466544d8 1907 return FAILED;
1da177e4
LT
1908}
1909
1910/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1911/**
1912 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1913 * new_eh variant
1914 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1915 *
1916 * (linux scsi_host_template.eh_host_reset_handler routine)
1917 *
1918 * Returns SUCCESS or FAILED.
1919 */
0d0c7974 1920int
1da177e4
LT
1921mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1922{
1923 MPT_SCSI_HOST * hd;
1924 int status = SUCCESS;
1da177e4
LT
1925
1926 /* If we can't locate the host to reset, then we failed. */
1927 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
c6678e0c 1928 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1da177e4
LT
1929 "Can't locate host! (sc=%p)\n",
1930 SCpnt ) );
1931 return FAILED;
1932 }
1933
c6678e0c 1934 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1da177e4
LT
1935 hd->ioc->name, SCpnt);
1936
1937 /* If our attempts to reset the host failed, then return a failed
1938 * status. The host will be taken off line by the SCSI mid-layer.
1939 */
1da177e4
LT
1940 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1941 status = FAILED;
1942 } else {
1943 /* Make sure TM pending is cleared and TM state is set to
1944 * NONE.
1945 */
1946 hd->tmPending = 0;
1947 hd->tmState = TM_STATE_NONE;
1948 }
1da177e4 1949
c6678e0c 1950 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1da177e4
LT
1951 "Status = %s\n",
1952 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1953
1954 return status;
1955}
1956
1957/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1958/**
1959 * mptscsih_tm_pending_wait - wait for pending task management request to
1960 * complete.
1961 * @hd: Pointer to MPT host structure.
1962 *
1963 * Returns {SUCCESS,FAILED}.
1964 */
1965static int
1966mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1967{
1968 unsigned long flags;
1969 int loop_count = 4 * 10; /* Wait 10 seconds */
1970 int status = FAILED;
1971
1972 do {
1973 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1974 if (hd->tmState == TM_STATE_NONE) {
1975 hd->tmState = TM_STATE_IN_PROGRESS;
1976 hd->tmPending = 1;
1da177e4 1977 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
c6678e0c 1978 status = SUCCESS;
1da177e4
LT
1979 break;
1980 }
1981 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1982 msleep(250);
1983 } while (--loop_count);
1984
1985 return status;
1986}
1987
1988/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1989/**
1990 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1991 * @hd: Pointer to MPT host structure.
1992 *
1993 * Returns {SUCCESS,FAILED}.
1994 */
1995static int
1996mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1997{
1998 unsigned long flags;
1999 int loop_count = 4 * timeout;
2000 int status = FAILED;
2001
2002 do {
2003 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2004 if(hd->tmPending == 0) {
2005 status = SUCCESS;
c6678e0c 2006 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1da177e4
LT
2007 break;
2008 }
2009 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2010 msleep_interruptible(250);
2011 } while (--loop_count);
2012
2013 return status;
2014}
2015
2016/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2017/**
2018 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2019 * @ioc: Pointer to MPT_ADAPTER structure
2020 * @mf: Pointer to SCSI task mgmt request frame
2021 * @mr: Pointer to SCSI task mgmt reply frame
2022 *
2023 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2024 * of any SCSI task management request.
2025 * This routine is registered with the MPT (base) driver at driver
2026 * load/init time via the mpt_register() API call.
2027 *
2028 * Returns 1 indicating alloc'd request frame ptr should be freed.
2029 */
0d0c7974 2030int
1da177e4
LT
2031mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2032{
2033 SCSITaskMgmtReply_t *pScsiTmReply;
2034 SCSITaskMgmt_t *pScsiTmReq;
2035 MPT_SCSI_HOST *hd;
2036 unsigned long flags;
2037 u16 iocstatus;
2038 u8 tmType;
2039
2040 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2041 ioc->name, mf, mr));
2042 if (ioc->sh) {
2043 /* Depending on the thread, a timer is activated for
2044 * the TM request. Delete this timer on completion of TM.
2045 * Decrement count of outstanding TM requests.
2046 */
2047 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2048 } else {
2049 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2050 ioc->name));
2051 return 1;
2052 }
2053
2054 if (mr == NULL) {
2055 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2056 ioc->name, mf));
2057 return 1;
2058 } else {
2059 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2060 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2061
2062 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2063 tmType = pScsiTmReq->TaskType;
2064
2065 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2066 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2067 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2068
2069 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2070 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2071 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2072 /* Error? (anything non-zero?) */
2073 if (iocstatus) {
2074
2075 /* clear flags and continue.
2076 */
2077 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2078 hd->abortSCpnt = NULL;
2079
2080 /* If an internal command is present
2081 * or the TM failed - reload the FW.
2082 * FC FW may respond FAILED to an ABORT
2083 */
2084 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2085 if ((hd->cmdPtr) ||
2086 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2087 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2088 printk((KERN_WARNING
2089 " Firmware Reload FAILED!!\n"));
2090 }
2091 }
2092 }
2093 } else {
2094 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2095
2096 hd->abortSCpnt = NULL;
2097
2098 }
2099 }
2100
2101 spin_lock_irqsave(&ioc->FreeQlock, flags);
2102 hd->tmPending = 0;
2103 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2104 hd->tmState = TM_STATE_NONE;
2105
2106 return 1;
2107}
2108
2109/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2110/*
2111 * This is anyones guess quite frankly.
2112 */
0d0c7974 2113int
1da177e4
LT
2114mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2115 sector_t capacity, int geom[])
2116{
2117 int heads;
2118 int sectors;
2119 sector_t cylinders;
2120 ulong dummy;
2121
2122 heads = 64;
2123 sectors = 32;
2124
2125 dummy = heads * sectors;
2126 cylinders = capacity;
2127 sector_div(cylinders,dummy);
2128
2129 /*
2130 * Handle extended translation size for logical drives
2131 * > 1Gb
2132 */
2133 if ((ulong)capacity >= 0x200000) {
2134 heads = 255;
2135 sectors = 63;
2136 dummy = heads * sectors;
2137 cylinders = capacity;
2138 sector_div(cylinders,dummy);
2139 }
2140
2141 /* return result */
2142 geom[0] = heads;
2143 geom[1] = sectors;
2144 geom[2] = cylinders;
2145
2146 dprintk((KERN_NOTICE
2147 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2148 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2149
2150 return 0;
2151}
2152
c7c82987
MED
2153/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2154/*
2155 * OS entry point to allow host driver to alloc memory
2156 * for each scsi target. Called once per device the bus scan.
2157 * Return non-zero if allocation fails.
2158 */
2159int
2160mptscsih_target_alloc(struct scsi_target *starget)
2161{
2162 VirtTarget *vtarget;
2163
1ca00bb7 2164 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
c7c82987
MED
2165 if (!vtarget)
2166 return -ENOMEM;
c7c82987
MED
2167 starget->hostdata = vtarget;
2168 return 0;
2169}
2170
1da177e4
LT
2171/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2172/*
2173 * OS entry point to allow host driver to alloc memory
2174 * for each scsi device. Called once per device the bus scan.
2175 * Return non-zero if allocation fails.
1da177e4 2176 */
0d0c7974 2177int
c7c82987 2178mptscsih_slave_alloc(struct scsi_device *sdev)
1da177e4 2179{
c7c82987 2180 struct Scsi_Host *host = sdev->host;
1da177e4 2181 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
c7c82987 2182 VirtTarget *vtarget;
1da177e4 2183 VirtDevice *vdev;
c7c82987 2184 struct scsi_target *starget;
1da177e4 2185
1ca00bb7 2186 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
1da177e4
LT
2187 if (!vdev) {
2188 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2189 hd->ioc->name, sizeof(VirtDevice));
2190 return -ENOMEM;
2191 }
2192
1da177e4 2193 vdev->ioc_id = hd->ioc->id;
c7c82987
MED
2194 vdev->target_id = sdev->id;
2195 vdev->bus_id = sdev->channel;
2196 vdev->lun = sdev->lun;
2197 sdev->hostdata = vdev;
2198
2199 starget = scsi_target(sdev);
2200 vtarget = starget->hostdata;
2201 vdev->vtarget = vtarget;
2202
2203 if (vtarget->num_luns == 0) {
2204 hd->Targets[sdev->id] = vtarget;
2205 vtarget->ioc_id = hd->ioc->id;
2206 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
2207 vtarget->target_id = sdev->id;
2208 vtarget->bus_id = sdev->channel;
2209 if (hd->ioc->bus_type == SPI) {
2210 if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
2211 vtarget->raidVolume = 1;
2212 ddvtprintk((KERN_INFO
2213 "RAID Volume @ id %d\n", sdev->id));
2214 }
2215 } else {
2216 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
1da177e4 2217 }
1da177e4 2218 }
c7c82987 2219 vtarget->num_luns++;
1da177e4
LT
2220 return 0;
2221}
2222
1da177e4
LT
2223/*
2224 * OS entry point to allow for host driver to free allocated memory
2225 * Called if no device present or device being unloaded
2226 */
0d0c7974 2227void
c7c82987 2228mptscsih_target_destroy(struct scsi_target *starget)
1da177e4 2229{
c7c82987
MED
2230 if (starget->hostdata)
2231 kfree(starget->hostdata);
2232 starget->hostdata = NULL;
2233}
1da177e4 2234
c7c82987
MED
2235/*
2236 * OS entry point to allow for host driver to free allocated memory
2237 * Called if no device present or device being unloaded
2238 */
2239void
2240mptscsih_slave_destroy(struct scsi_device *sdev)
2241{
2242 struct Scsi_Host *host = sdev->host;
2243 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2244 VirtTarget *vtarget;
2245 VirtDevice *vdevice;
2246 struct scsi_target *starget;
2247
2248 starget = scsi_target(sdev);
2249 vtarget = starget->hostdata;
2250 vdevice = sdev->hostdata;
2251
2252 mptscsih_search_running_cmds(hd, vdevice);
2253 vtarget->luns[0] &= ~(1 << vdevice->lun);
2254 vtarget->num_luns--;
2255 if (vtarget->num_luns == 0) {
2256 mptscsih_negotiate_to_asyn_narrow(hd, vtarget);
2257 if (hd->ioc->bus_type == SPI) {
2258 if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
2259 hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
2260 } else {
2261 hd->ioc->spi_data.dvStatus[vtarget->target_id] =
2262 MPT_SCSICFG_NEGOTIATE;
2263 if (!hd->negoNvram) {
2264 hd->ioc->spi_data.dvStatus[vtarget->target_id] |=
2265 MPT_SCSICFG_DV_NOT_DONE;
2266 }
1da177e4
LT
2267 }
2268 }
c7c82987 2269 hd->Targets[sdev->id] = NULL;
1da177e4 2270 }
c7c82987
MED
2271 mptscsih_synchronize_cache(hd, vdevice);
2272 kfree(vdevice);
2273 sdev->hostdata = NULL;
1da177e4
LT
2274}
2275
6e3815ba
MED
2276/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2277/*
2278 * mptscsih_change_queue_depth - This function will set a devices queue depth
2279 * @sdev: per scsi_device pointer
2280 * @qdepth: requested queue depth
2281 *
2282 * Adding support for new 'change_queue_depth' api.
2283*/
2284int
2285mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
1da177e4 2286{
c7c82987
MED
2287 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2288 VirtTarget *vtarget;
2289 struct scsi_target *starget;
2290 int max_depth;
2291 int tagged;
1da177e4 2292
c7c82987
MED
2293 starget = scsi_target(sdev);
2294 vtarget = starget->hostdata;
6e3815ba 2295
a9b2937a 2296 if (hd->ioc->bus_type == SPI) {
c7c82987
MED
2297 if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
2298 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
1da177e4 2299 max_depth = 1;
c7c82987
MED
2300 else if (((vtarget->inq_data[0] & 0x1f) == 0x00) &&
2301 (vtarget->minSyncFactor <= MPT_ULTRA160 ))
1da177e4
LT
2302 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2303 else
2304 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2305 } else {
2306 /* error case - No Inq. Data */
2307 max_depth = 1;
2308 }
2309 } else
2310 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2311
2312 if (qdepth > max_depth)
2313 qdepth = max_depth;
2314 if (qdepth == 1)
2315 tagged = 0;
2316 else
2317 tagged = MSG_SIMPLE_TAG;
2318
6e3815ba
MED
2319 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2320 return sdev->queue_depth;
1da177e4
LT
2321}
2322
1da177e4
LT
2323/*
2324 * OS entry point to adjust the queue_depths on a per-device basis.
2325 * Called once per device the bus scan. Use it to force the queue_depth
2326 * member to 1 if a device does not support Q tags.
2327 * Return non-zero if fails.
2328 */
0d0c7974 2329int
c7c82987 2330mptscsih_slave_configure(struct scsi_device *sdev)
1da177e4 2331{
c7c82987
MED
2332 struct Scsi_Host *sh = sdev->host;
2333 VirtTarget *vtarget;
2334 VirtDevice *vdevice;
2335 struct scsi_target *starget;
1da177e4 2336 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
c7c82987 2337 int indexed_lun, lun_index;
1da177e4 2338
c7c82987
MED
2339 starget = scsi_target(sdev);
2340 vtarget = starget->hostdata;
2341 vdevice = sdev->hostdata;
1da177e4
LT
2342
2343 dsprintk((MYIOC_s_INFO_FMT
2344 "device @ %p, id=%d, LUN=%d, channel=%d\n",
c7c82987
MED
2345 hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
2346 if (hd->ioc->bus_type == SPI)
2347 dsprintk((MYIOC_s_INFO_FMT
2348 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2349 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2350 sdev->ppr, sdev->inquiry_len));
2351
2352 if (sdev->id > sh->max_id) {
1da177e4 2353 /* error case, should never happen */
c7c82987 2354 scsi_adjust_queue_depth(sdev, 0, 1);
1da177e4
LT
2355 goto slave_configure_exit;
2356 }
2357
c7c82987
MED
2358 vdevice->configured_lun=1;
2359 lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */
2360 indexed_lun = (vdevice->lun % 32);
2361 vtarget->luns[lun_index] |= (1 << indexed_lun);
2362 mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry,
2363 sdev->inquiry_len );
2364 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
1da177e4
LT
2365
2366 dsprintk((MYIOC_s_INFO_FMT
2367 "Queue depth=%d, tflags=%x\n",
c7c82987 2368 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
1da177e4 2369
c7c82987
MED
2370 if (hd->ioc->bus_type == SPI)
2371 dsprintk((MYIOC_s_INFO_FMT
2372 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2373 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2374 vtarget->minSyncFactor));
1da177e4
LT
2375
2376slave_configure_exit:
2377
2378 dsprintk((MYIOC_s_INFO_FMT
2379 "tagged %d, simple %d, ordered %d\n",
c7c82987
MED
2380 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2381 sdev->ordered_tags));
1da177e4
LT
2382
2383 return 0;
2384}
2385
1da177e4
LT
2386/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2387/*
2388 * Private routines...
2389 */
2390
2391/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2392/* Utility function to copy sense data from the scsi_cmnd buffer
2393 * to the FC and SCSI target structures.
2394 *
2395 */
2396static void
0d0c7974 2397mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
1da177e4 2398{
c7c82987 2399 VirtDevice *vdev;
1da177e4
LT
2400 SCSIIORequest_t *pReq;
2401 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
1da177e4
LT
2402
2403 /* Get target structure
2404 */
2405 pReq = (SCSIIORequest_t *) mf;
c7c82987 2406 vdev = sc->device->hostdata;
1da177e4
LT
2407
2408 if (sense_count) {
2409 u8 *sense_data;
2410 int req_index;
2411
2412 /* Copy the sense received into the scsi command block. */
2413 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2414 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2415 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2416
2417 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2418 */
2419 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
c7c82987 2420 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
1da177e4
LT
2421 int idx;
2422 MPT_ADAPTER *ioc = hd->ioc;
2423
2424 idx = ioc->eventContext % ioc->eventLogSize;
2425 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2426 ioc->events[idx].eventContext = ioc->eventContext;
2427
2428 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2429 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
c7c82987 2430 (sc->device->channel << 8) || sc->device->id;
1da177e4
LT
2431
2432 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2433
2434 ioc->eventContext++;
2435 }
2436 }
2437 } else {
2438 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2439 hd->ioc->name));
2440 }
2441}
2442
2443static u32
2444SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2445{
2446 MPT_SCSI_HOST *hd;
2447 int i;
2448
2449 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2450
2451 for (i = 0; i < hd->ioc->req_depth; i++) {
2452 if (hd->ScsiLookup[i] == sc) {
2453 return i;
2454 }
2455 }
2456
2457 return -1;
2458}
2459
2460/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2461int
1da177e4
LT
2462mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2463{
2464 MPT_SCSI_HOST *hd;
2465 unsigned long flags;
466544d8 2466 int ii;
1da177e4
LT
2467
2468 dtmprintk((KERN_WARNING MYNAM
2469 ": IOC %s_reset routed to SCSI host driver!\n",
2470 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2471 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2472
2473 /* If a FW reload request arrives after base installed but
2474 * before all scsi hosts have been attached, then an alt_ioc
2475 * may have a NULL sh pointer.
2476 */
2477 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2478 return 0;
2479 else
2480 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2481
2482 if (reset_phase == MPT_IOC_SETUP_RESET) {
2483 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2484
2485 /* Clean Up:
2486 * 1. Set Hard Reset Pending Flag
2487 * All new commands go to doneQ
2488 */
2489 hd->resetPending = 1;
2490
2491 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2492 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2493
2494 /* 2. Flush running commands
2495 * Clean ScsiLookup (and associated memory)
2496 * AND clean mytaskQ
2497 */
2498
2499 /* 2b. Reply to OS all known outstanding I/O commands.
2500 */
2501 mptscsih_flush_running_cmds(hd);
2502
2503 /* 2c. If there was an internal command that
2504 * has not completed, configuration or io request,
2505 * free these resources.
2506 */
2507 if (hd->cmdPtr) {
2508 del_timer(&hd->timer);
2509 mpt_free_msg_frame(ioc, hd->cmdPtr);
2510 }
2511
2512 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2513
2514 } else {
2515 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2516
2517 /* Once a FW reload begins, all new OS commands are
2518 * redirected to the doneQ w/ a reset status.
2519 * Init all control structures.
2520 */
2521
2522 /* ScsiLookup initialization
2523 */
466544d8
MED
2524 for (ii=0; ii < hd->ioc->req_depth; ii++)
2525 hd->ScsiLookup[ii] = NULL;
1da177e4
LT
2526
2527 /* 2. Chain Buffer initialization
2528 */
2529
a9b2937a 2530 /* 4. Renegotiate to all devices, if SPI
1da177e4 2531 */
a9b2937a 2532 if (ioc->bus_type == SPI) {
1da177e4
LT
2533 dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2534 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
2535 }
2536
2537 /* 5. Enable new commands to be posted
2538 */
2539 spin_lock_irqsave(&ioc->FreeQlock, flags);
2540 hd->tmPending = 0;
2541 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2542 hd->resetPending = 0;
2543 hd->tmState = TM_STATE_NONE;
2544
2545 /* 6. If there was an internal command,
2546 * wake this process up.
2547 */
2548 if (hd->cmdPtr) {
2549 /*
2550 * Wake up the original calling thread
2551 */
2552 hd->pLocal = &hd->localReply;
2553 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
0d0c7974
MED
2554 hd->scandv_wait_done = 1;
2555 wake_up(&hd->scandv_waitq);
1da177e4
LT
2556 hd->cmdPtr = NULL;
2557 }
2558
05e8ec17 2559 /* 7. SPI: Set flag to force DV and re-read IOC Page 3
1da177e4 2560 */
a9b2937a 2561 if (ioc->bus_type == SPI) {
1da177e4
LT
2562 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2563 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2564 }
2565
05e8ec17
MR
2566 /* 7. FC: Rescan for blocked rports which might have returned.
2567 */
2568 else if (ioc->bus_type == FC) {
2569 int work_count;
2570 unsigned long flags;
2571
2572 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2573 work_count = ++ioc->fc_rescan_work_count;
2574 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2575 if (work_count == 1)
2576 schedule_work(&ioc->fc_rescan_work);
2577 }
1da177e4
LT
2578 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2579
2580 }
2581
2582 return 1; /* currently means nothing really */
2583}
2584
2585/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2586int
1da177e4
LT
2587mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2588{
2589 MPT_SCSI_HOST *hd;
2590 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
05e8ec17
MR
2591 int work_count;
2592 unsigned long flags;
1da177e4
LT
2593
2594 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2595 ioc->name, event));
2596
466544d8
MED
2597 if (ioc->sh == NULL ||
2598 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2599 return 1;
2600
1da177e4
LT
2601 switch (event) {
2602 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2603 /* FIXME! */
2604 break;
2605 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2606 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
a9b2937a 2607 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
466544d8 2608 hd->soft_resets++;
1da177e4
LT
2609 break;
2610 case MPI_EVENT_LOGOUT: /* 09 */
2611 /* FIXME! */
2612 break;
2613
05e8ec17
MR
2614 case MPI_EVENT_RESCAN: /* 06 */
2615 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2616 work_count = ++ioc->fc_rescan_work_count;
2617 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2618 if (work_count == 1)
2619 schedule_work(&ioc->fc_rescan_work);
2620 break;
2621
1da177e4
LT
2622 /*
2623 * CHECKME! Don't think we need to do
2624 * anything for these, but...
2625 */
1da177e4
LT
2626 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2627 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2628 /*
2629 * CHECKME! Falling thru...
2630 */
2631 break;
2632
2633 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
466544d8 2634 {
f2ea8671 2635#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
466544d8
MED
2636 pMpiEventDataRaid_t pRaidEventData =
2637 (pMpiEventDataRaid_t) pEvReply->Data;
466544d8 2638 /* Domain Validation Needed */
a9b2937a 2639 if (ioc->bus_type == SPI &&
466544d8
MED
2640 pRaidEventData->ReasonCode ==
2641 MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
2642 mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
1da177e4 2643#endif
466544d8
MED
2644 break;
2645 }
1da177e4 2646
1da177e4
LT
2647 case MPI_EVENT_NONE: /* 00 */
2648 case MPI_EVENT_LOG_DATA: /* 01 */
2649 case MPI_EVENT_STATE_CHANGE: /* 02 */
2650 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2651 default:
2652 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2653 break;
2654 }
2655
2656 return 1; /* currently means nothing really */
2657}
2658
1da177e4
LT
2659/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2660/*
2661 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2662 * @hd: Pointer to MPT_SCSI_HOST structure
c7c82987 2663 * @vtarget: per target private data
1da177e4
LT
2664 * @lun: SCSI LUN id
2665 * @data: Pointer to data
2666 * @dlen: Number of INQUIRY bytes
2667 *
2668 * NOTE: It's only SAFE to call this routine if data points to
2669 * sane & valid STANDARD INQUIRY data!
2670 *
2671 * Allocate and initialize memory for this target.
2672 * Save inquiry data.
2673 *
2674 */
2675static void
c7c82987 2676mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen)
1da177e4 2677{
466544d8 2678 SpiCfgData *pSpi;
1da177e4 2679 char data_56;
c7c82987 2680 int inq_len;
1da177e4
LT
2681
2682 dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
c7c82987 2683 hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
1da177e4
LT
2684
2685 /*
2686 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2687 * (i.e. The targer is capable of supporting the specified peripheral device type
2688 * on this logical unit; however, the physical device is not currently connected
c6678e0c 2689 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
1da177e4
LT
2690 * capable of supporting a physical device on this logical unit). This is to work
2691 * around a bug in th emid-layer in some distributions in which the mid-layer will
2692 * continue to try to communicate to the LUN and evntually create a dummy LUN.
2693 */
0d0c7974 2694 if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
1da177e4 2695 data[0] |= 0x40;
0d0c7974 2696
1da177e4
LT
2697 /* Is LUN supported? If so, upper 2 bits will be 0
2698 * in first byte of inquiry data.
2699 */
2700 if (data[0] & 0xe0)
2701 return;
2702
c7c82987 2703 if (vtarget == NULL)
1da177e4 2704 return;
1da177e4 2705
c7c82987
MED
2706 if (data)
2707 vtarget->type = data[0];
1da177e4 2708
c7c82987
MED
2709 if (hd->ioc->bus_type != SPI)
2710 return;
2711
2712 if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2713 /* Treat all Processors as SAF-TE if
2714 * command line option is set */
2715 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2716 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2717 }else if ((data[0] == TYPE_PROCESSOR) &&
2718 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2719 if ( dlen > 49 ) {
2720 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2721 if ( data[44] == 'S' &&
2722 data[45] == 'A' &&
2723 data[46] == 'F' &&
2724 data[47] == '-' &&
2725 data[48] == 'T' &&
2726 data[49] == 'E' ) {
2727 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2728 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
1da177e4
LT
2729 }
2730 }
c7c82987
MED
2731 }
2732 if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
2733 inq_len = dlen < 8 ? dlen : 8;
2734 memcpy (vtarget->inq_data, data, inq_len);
2735 /* If have not done DV, set the DV flag.
2736 */
2737 pSpi = &hd->ioc->spi_data;
2738 if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
2739 if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE)
2740 pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV;
2741 }
2742 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
1da177e4 2743
c7c82987
MED
2744 data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
2745 if (dlen > 56) {
2746 if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2747 /* Update the target capabilities
1da177e4 2748 */
c7c82987
MED
2749 data_56 = data[56];
2750 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
1da177e4 2751 }
c7c82987
MED
2752 }
2753 mptscsih_setTargetNegoParms(hd, vtarget, data_56);
2754 } else {
2755 /* Initial Inquiry may not request enough data bytes to
2756 * obtain byte 57. DV will; if target doesn't return
2757 * at least 57 bytes, data[56] will be zero. */
2758 if (dlen > 56) {
2759 if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2760 /* Update the target capabilities
2761 */
2762 data_56 = data[56];
2763 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
2764 mptscsih_setTargetNegoParms(hd, vtarget, data_56);
1da177e4
LT
2765 }
2766 }
2767 }
2768}
2769
2770/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2771/*
2772 * Update the target negotiation parameters based on the
2773 * the Inquiry data, adapter capabilities, and NVRAM settings.
2774 *
2775 */
2776static void
c7c82987 2777mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
1da177e4 2778{
466544d8 2779 SpiCfgData *pspi_data = &hd->ioc->spi_data;
1da177e4
LT
2780 int id = (int) target->target_id;
2781 int nvram;
c7c82987 2782 VirtTarget *vtarget;
1da177e4
LT
2783 int ii;
2784 u8 width = MPT_NARROW;
2785 u8 factor = MPT_ASYNC;
2786 u8 offset = 0;
2787 u8 version, nfactor;
2788 u8 noQas = 1;
2789
2790 target->negoFlags = pspi_data->noQas;
2791
2792 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2793 * support. If available, default QAS to off and allow enabling.
2794 * If not available, default QAS to on, turn off for non-disks.
2795 */
2796
2797 /* Set flags based on Inquiry data
2798 */
2799 version = target->inq_data[2] & 0x07;
2800 if (version < 2) {
2801 width = 0;
2802 factor = MPT_ULTRA2;
2803 offset = pspi_data->maxSyncOffset;
2804 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2805 } else {
2806 if (target->inq_data[7] & 0x20) {
2807 width = 1;
2808 }
2809
2810 if (target->inq_data[7] & 0x10) {
2811 factor = pspi_data->minSyncFactor;
2812 if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
2813 /* bits 2 & 3 show Clocking support */
2814 if ((byte56 & 0x0C) == 0)
2815 factor = MPT_ULTRA2;
2816 else {
2817 if ((byte56 & 0x03) == 0)
2818 factor = MPT_ULTRA160;
2819 else {
2820 factor = MPT_ULTRA320;
2821 if (byte56 & 0x02)
2822 {
2823 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2824 noQas = 0;
2825 }
2826 if (target->inq_data[0] == TYPE_TAPE) {
2827 if (byte56 & 0x01)
2828 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2829 }
2830 }
2831 }
2832 } else {
2833 ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
2834 noQas = 0;
2835 }
0d0c7974 2836
1da177e4
LT
2837 offset = pspi_data->maxSyncOffset;
2838
2839 /* If RAID, never disable QAS
2840 * else if non RAID, do not disable
2841 * QAS if bit 1 is set
2842 * bit 1 QAS support, non-raid only
2843 * bit 0 IU support
2844 */
2845 if (target->raidVolume == 1) {
2846 noQas = 0;
2847 }
2848 } else {
2849 factor = MPT_ASYNC;
2850 offset = 0;
2851 }
2852 }
2853
2854 if ( (target->inq_data[7] & 0x02) == 0) {
2855 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2856 }
2857
2858 /* Update tflags based on NVRAM settings. (SCSI only)
2859 */
2860 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2861 nvram = pspi_data->nvram[id];
2862 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2863
2864 if (width)
2865 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2866
2867 if (offset > 0) {
2868 /* Ensure factor is set to the
2869 * maximum of: adapter, nvram, inquiry
2870 */
2871 if (nfactor) {
2872 if (nfactor < pspi_data->minSyncFactor )
2873 nfactor = pspi_data->minSyncFactor;
2874
2875 factor = max(factor, nfactor);
2876 if (factor == MPT_ASYNC)
2877 offset = 0;
2878 } else {
2879 offset = 0;
2880 factor = MPT_ASYNC;
2881 }
2882 } else {
2883 factor = MPT_ASYNC;
2884 }
2885 }
2886
2887 /* Make sure data is consistent
2888 */
2889 if ((!width) && (factor < MPT_ULTRA2)) {
2890 factor = MPT_ULTRA2;
2891 }
2892
2893 /* Save the data to the target structure.
2894 */
2895 target->minSyncFactor = factor;
2896 target->maxOffset = offset;
2897 target->maxWidth = width;
2898
2899 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2900
2901 /* Disable unused features.
2902 */
2903 if (!width)
2904 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2905
2906 if (!offset)
2907 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2908
2909 if ( factor > MPT_ULTRA320 )
2910 noQas = 0;
2911
2912 /* GEM, processor WORKAROUND
2913 */
2914 if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
2915 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
2916 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
2917 } else {
2918 if (noQas && (pspi_data->noQas == 0)) {
2919 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2920 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2921
2922 /* Disable QAS in a mixed configuration case
2923 */
2924
2925 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2926 for (ii = 0; ii < id; ii++) {
c7c82987
MED
2927 if ( (vtarget = hd->Targets[ii]) ) {
2928 vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2929 mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags);
0d0c7974 2930 }
1da177e4
LT
2931 }
2932 }
2933 }
2934
2935 /* Write SDP1 on this I/O to this target */
2936 if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
2937 ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
2938 mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
2939 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
2940 } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
2941 ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
2942 mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
2943 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
2944 }
2945}
2946
1da177e4
LT
2947/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2948/*
2949 * If no Target, bus reset on 1st I/O. Set the flag to
2950 * prevent any future negotiations to this device.
2951 */
0d0c7974 2952static void
c7c82987 2953mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
1da177e4 2954{
c7c82987 2955 VirtDevice *vdev;
1da177e4 2956
c7c82987
MED
2957 if ((vdev = sc->device->hostdata) != NULL)
2958 hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO;
1da177e4
LT
2959 return;
2960}
2961
2962/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2963/*
2964 * SCSI Config Page functionality ...
2965 */
2966/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2967/* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
2968 * based on width, factor and offset parameters.
2969 * @width: bus width
2970 * @factor: sync factor
2971 * @offset: sync offset
2972 * @requestedPtr: pointer to requested values (updated)
2973 * @configurationPtr: pointer to configuration values (updated)
2974 * @flags: flags to block WDTR or SDTR negotiation
2975 *
2976 * Return: None.
2977 *
2978 * Remark: Called by writeSDP1 and _dv_params
2979 */
2980static void
2981mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
2982{
2983 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
2984 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
2985
2986 *configurationPtr = 0;
2987 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
2988 *requestedPtr |= (offset << 16) | (factor << 8);
2989
2990 if (width && offset && !nowide && !nosync) {
2991 if (factor < MPT_ULTRA160) {
2992 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
2993 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
2994 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
2995 if (flags & MPT_TAPE_NEGO_IDP)
2996 *requestedPtr |= 0x08000000;
2997 } else if (factor < MPT_ULTRA2) {
2998 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
2999 }
3000 }
3001
3002 if (nowide)
3003 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
3004
3005 if (nosync)
3006 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
3007
3008 return;
3009}
3010
3011/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3012/* mptscsih_writeSDP1 - write SCSI Device Page 1
3013 * @hd: Pointer to a SCSI Host Strucutre
3014 * @portnum: IOC port number
3015 * @target_id: writeSDP1 for single ID
3016 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3017 *
3018 * Return: -EFAULT if read of config page header fails
3019 * or 0 if success.
3020 *
3021 * Remark: If a target has been found, the settings from the
3022 * target structure are used, else the device is set
3023 * to async/narrow.
3024 *
3025 * Remark: Called during init and after a FW reload.
3026 * Remark: We do not wait for a return, write pages sequentially.
3027 */
3028static int
3029mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
3030{
3031 MPT_ADAPTER *ioc = hd->ioc;
3032 Config_t *pReq;
3033 SCSIDevicePage1_t *pData;
c7c82987 3034 VirtTarget *vtarget=NULL;
1da177e4
LT
3035 MPT_FRAME_HDR *mf;
3036 dma_addr_t dataDma;
3037 u16 req_idx;
3038 u32 frameOffset;
3039 u32 requested, configuration, flagsLength;
3040 int ii, nvram;
3041 int id = 0, maxid = 0;
3042 u8 width;
3043 u8 factor;
3044 u8 offset;
3045 u8 bus = 0;
3046 u8 negoFlags;
3047 u8 maxwidth, maxoffset, maxfactor;
3048
3049 if (ioc->spi_data.sdp1length == 0)
3050 return 0;
3051
3052 if (flags & MPT_SCSICFG_ALL_IDS) {
3053 id = 0;
3054 maxid = ioc->sh->max_id - 1;
3055 } else if (ioc->sh) {
3056 id = target_id;
3057 maxid = min_t(int, id, ioc->sh->max_id - 1);
3058 }
3059
3060 for (; id <= maxid; id++) {
3061
3062 if (id == ioc->pfacts[portnum].PortSCSIID)
3063 continue;
3064
3065 /* Use NVRAM to get adapter and target maximums
3066 * Data over-riden by target structure information, if present
3067 */
3068 maxwidth = ioc->spi_data.maxBusWidth;
3069 maxoffset = ioc->spi_data.maxSyncOffset;
3070 maxfactor = ioc->spi_data.minSyncFactor;
3071 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3072 nvram = ioc->spi_data.nvram[id];
3073
3074 if (maxwidth)
3075 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
3076
3077 if (maxoffset > 0) {
3078 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
3079 if (maxfactor == 0) {
3080 /* Key for async */
3081 maxfactor = MPT_ASYNC;
3082 maxoffset = 0;
3083 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
3084 maxfactor = ioc->spi_data.minSyncFactor;
3085 }
3086 } else
3087 maxfactor = MPT_ASYNC;
3088 }
3089
3090 /* Set the negotiation flags.
3091 */
3092 negoFlags = ioc->spi_data.noQas;
3093 if (!maxwidth)
3094 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
3095
3096 if (!maxoffset)
3097 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
3098
3099 if (flags & MPT_SCSICFG_USE_NVRAM) {
3100 width = maxwidth;
3101 factor = maxfactor;
3102 offset = maxoffset;
3103 } else {
3104 width = 0;
3105 factor = MPT_ASYNC;
3106 offset = 0;
3107 //negoFlags = 0;
3108 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3109 }
3110
3111 /* If id is not a raid volume, get the updated
3112 * transmission settings from the target structure.
3113 */
c7c82987
MED
3114 if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) {
3115 width = vtarget->maxWidth;
3116 factor = vtarget->minSyncFactor;
3117 offset = vtarget->maxOffset;
3118 negoFlags = vtarget->negoFlags;
1da177e4 3119 }
0d0c7974 3120
1da177e4
LT
3121#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3122 /* Force to async and narrow if DV has not been executed
3123 * for this ID
3124 */
3125 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
3126 width = 0;
3127 factor = MPT_ASYNC;
3128 offset = 0;
3129 }
3130#endif
3131
3132 if (flags & MPT_SCSICFG_BLK_NEGO)
466544d8 3133 negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
1da177e4
LT
3134
3135 mptscsih_setDevicePage1Flags(width, factor, offset,
3136 &requested, &configuration, negoFlags);
3137 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3138 target_id, width, factor, offset, negoFlags, requested, configuration));
3139
3140 /* Get a MF for this command.
3141 */
0d0c7974 3142 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
c6678e0c
CH
3143 dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
3144 ioc->name));
1da177e4
LT
3145 return -EAGAIN;
3146 }
3147
3148 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3149 hd->ioc->name, mf, id, requested, configuration));
3150
3151
3152 /* Set the request and the data pointers.
3153 * Request takes: 36 bytes (32 bit SGE)
3154 * SCSI Device Page 1 requires 16 bytes
3155 * 40 + 16 <= size of SCSI IO Request = 56 bytes
3156 * and MF size >= 64 bytes.
3157 * Place data at end of MF.
3158 */
3159 pReq = (Config_t *)mf;
3160
3161 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3162 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
3163
3164 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
3165 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
3166
3167 /* Complete the request frame (same for all requests).
3168 */
3169 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3170 pReq->Reserved = 0;
3171 pReq->ChainOffset = 0;
3172 pReq->Function = MPI_FUNCTION_CONFIG;
3173 pReq->ExtPageLength = 0;
3174 pReq->ExtPageType = 0;
3175 pReq->MsgFlags = 0;
3176 for (ii=0; ii < 8; ii++) {
3177 pReq->Reserved2[ii] = 0;
3178 }
3179 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
3180 pReq->Header.PageLength = ioc->spi_data.sdp1length;
3181 pReq->Header.PageNumber = 1;
3182 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3183 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
3184
3185 /* Add a SGE to the config request.
3186 */
3187 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
3188
3189 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3190
3191 /* Set up the common data portion
3192 */
3193 pData->Header.PageVersion = pReq->Header.PageVersion;
3194 pData->Header.PageLength = pReq->Header.PageLength;
3195 pData->Header.PageNumber = pReq->Header.PageNumber;
3196 pData->Header.PageType = pReq->Header.PageType;
3197 pData->RequestedParameters = cpu_to_le32(requested);
3198 pData->Reserved = 0;
3199 pData->Configuration = cpu_to_le32(configuration);
3200
3201 dprintk((MYIOC_s_INFO_FMT
3202 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3203 ioc->name, id, (id | (bus<<8)),
3204 requested, configuration));
3205
0d0c7974 3206 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
1da177e4
LT
3207 }
3208
3209 return 0;
3210}
3211
3212/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3213/* mptscsih_writeIOCPage4 - write IOC Page 4
3214 * @hd: Pointer to a SCSI Host Structure
3215 * @target_id: write IOC Page4 for this ID & Bus
3216 *
3217 * Return: -EAGAIN if unable to obtain a Message Frame
3218 * or 0 if success.
3219 *
3220 * Remark: We do not wait for a return, write pages sequentially.
3221 */
3222static int
3223mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
3224{
3225 MPT_ADAPTER *ioc = hd->ioc;
3226 Config_t *pReq;
3227 IOCPage4_t *IOCPage4Ptr;
3228 MPT_FRAME_HDR *mf;
3229 dma_addr_t dataDma;
3230 u16 req_idx;
3231 u32 frameOffset;
3232 u32 flagsLength;
3233 int ii;
3234
3235 /* Get a MF for this command.
3236 */
0d0c7974 3237 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
c6678e0c 3238 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
1da177e4
LT
3239 ioc->name));
3240 return -EAGAIN;
3241 }
3242
3243 /* Set the request and the data pointers.
3244 * Place data at end of MF.
3245 */
3246 pReq = (Config_t *)mf;
3247
3248 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3249 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
3250
3251 /* Complete the request frame (same for all requests).
3252 */
3253 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3254 pReq->Reserved = 0;
3255 pReq->ChainOffset = 0;
3256 pReq->Function = MPI_FUNCTION_CONFIG;
3257 pReq->ExtPageLength = 0;
3258 pReq->ExtPageType = 0;
3259 pReq->MsgFlags = 0;
3260 for (ii=0; ii < 8; ii++) {
3261 pReq->Reserved2[ii] = 0;
3262 }
3263
3264 IOCPage4Ptr = ioc->spi_data.pIocPg4;
3265 dataDma = ioc->spi_data.IocPg4_dma;
3266 ii = IOCPage4Ptr->ActiveSEP++;
3267 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
3268 IOCPage4Ptr->SEP[ii].SEPBus = bus;
3269 pReq->Header = IOCPage4Ptr->Header;
3270 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
3271
3272 /* Add a SGE to the config request.
3273 */
3274 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
3275 (IOCPage4Ptr->Header.PageLength + ii) * 4;
3276
3277 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3278
3279 dinitprintk((MYIOC_s_INFO_FMT
3280 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3281 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
3282
0d0c7974 3283 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
1da177e4
LT
3284
3285 return 0;
3286}
3287
3288/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3289/*
3290 * Bus Scan and Domain Validation functionality ...
3291 */
3292
3293/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3294/*
3295 * mptscsih_scandv_complete - Scan and DV callback routine registered
3296 * to Fustion MPT (base) driver.
3297 *
3298 * @ioc: Pointer to MPT_ADAPTER structure
3299 * @mf: Pointer to original MPT request frame
3300 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
3301 *
3302 * This routine is called from mpt.c::mpt_interrupt() at the completion
3303 * of any SCSI IO request.
3304 * This routine is registered with the Fusion MPT (base) driver at driver
3305 * load/init time via the mpt_register() API call.
3306 *
3307 * Returns 1 indicating alloc'd request frame ptr should be freed.
3308 *
3309 * Remark: Sets a completion code and (possibly) saves sense data
3310 * in the IOC member localReply structure.
3311 * Used ONLY for DV and other internal commands.
3312 */
0d0c7974 3313int
1da177e4
LT
3314mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3315{
3316 MPT_SCSI_HOST *hd;
3317 SCSIIORequest_t *pReq;
3318 int completionCode;
3319 u16 req_idx;
3320
0d0c7974
MED
3321 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3322
1da177e4
LT
3323 if ((mf == NULL) ||
3324 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3325 printk(MYIOC_s_ERR_FMT
3326 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3327 ioc->name, mf?"BAD":"NULL", (void *) mf);
3328 goto wakeup;
3329 }
3330
1da177e4
LT
3331 del_timer(&hd->timer);
3332 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3333 hd->ScsiLookup[req_idx] = NULL;
3334 pReq = (SCSIIORequest_t *) mf;
3335
3336 if (mf != hd->cmdPtr) {
3337 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3338 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3339 }
3340 hd->cmdPtr = NULL;
3341
3342 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3343 hd->ioc->name, mf, mr, req_idx));
3344
3345 hd->pLocal = &hd->localReply;
3346 hd->pLocal->scsiStatus = 0;
3347
3348 /* If target struct exists, clear sense valid flag.
3349 */
3350 if (mr == NULL) {
3351 completionCode = MPT_SCANDV_GOOD;
3352 } else {
3353 SCSIIOReply_t *pReply;
3354 u16 status;
3355 u8 scsi_status;
3356
3357 pReply = (SCSIIOReply_t *) mr;
3358
3359 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3360 scsi_status = pReply->SCSIStatus;
3361
3362 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3363 status, pReply->SCSIState, scsi_status,
3364 le32_to_cpu(pReply->IOCLogInfo)));
3365
3366 switch(status) {
3367
3368 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3369 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3370 break;
3371
3372 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
3373 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
3374 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
3375 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
3376 completionCode = MPT_SCANDV_DID_RESET;
3377 break;
3378
3379 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
3380 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
3381 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
3382 if (pReply->Function == MPI_FUNCTION_CONFIG) {
3383 ConfigReply_t *pr = (ConfigReply_t *)mr;
3384 completionCode = MPT_SCANDV_GOOD;
3385 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3386 hd->pLocal->header.PageLength = pr->Header.PageLength;
3387 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3388 hd->pLocal->header.PageType = pr->Header.PageType;
3389
3390 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3391 /* If the RAID Volume request is successful,
3392 * return GOOD, else indicate that
3393 * some type of error occurred.
3394 */
3395 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
637fa99b 3396 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
1da177e4
LT
3397 completionCode = MPT_SCANDV_GOOD;
3398 else
3399 completionCode = MPT_SCANDV_SOME_ERROR;
3400
3401 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3402 u8 *sense_data;
3403 int sz;
3404
3405 /* save sense data in global structure
3406 */
3407 completionCode = MPT_SCANDV_SENSE;
3408 hd->pLocal->scsiStatus = scsi_status;
3409 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3410 (req_idx * MPT_SENSE_BUFFER_ALLOC));
3411
3412 sz = min_t(int, pReq->SenseBufferLength,
3413 SCSI_STD_SENSE_BYTES);
3414 memcpy(hd->pLocal->sense, sense_data, sz);
3415
3416 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
3417 sense_data));
3418 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3419 if (pReq->CDB[0] == INQUIRY)
3420 completionCode = MPT_SCANDV_ISSUE_SENSE;
3421 else
3422 completionCode = MPT_SCANDV_DID_RESET;
3423 }
3424 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3425 completionCode = MPT_SCANDV_DID_RESET;
3426 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3427 completionCode = MPT_SCANDV_DID_RESET;
3428 else {
3429 completionCode = MPT_SCANDV_GOOD;
3430 hd->pLocal->scsiStatus = scsi_status;
3431 }
3432 break;
3433
3434 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
3435 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3436 completionCode = MPT_SCANDV_DID_RESET;
3437 else
3438 completionCode = MPT_SCANDV_SOME_ERROR;
3439 break;
3440
3441 default:
3442 completionCode = MPT_SCANDV_SOME_ERROR;
3443 break;
3444
3445 } /* switch(status) */
3446
3447 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3448 completionCode));
3449 } /* end of address reply case */
3450
3451 hd->pLocal->completion = completionCode;
3452
3453 /* MF and RF are freed in mpt_interrupt
3454 */
3455wakeup:
3456 /* Free Chain buffers (will never chain) in scan or dv */
3457 //mptscsih_freeChainBuffers(ioc, req_idx);
3458
3459 /*
3460 * Wake up the original calling thread
3461 */
0d0c7974
MED
3462 hd->scandv_wait_done = 1;
3463 wake_up(&hd->scandv_waitq);
1da177e4
LT
3464
3465 return 1;
3466}
3467
3468/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3469/* mptscsih_timer_expired - Call back for timer process.
3470 * Used only for dv functionality.
3471 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3472 *
3473 */
0d0c7974
MED
3474void
3475mptscsih_timer_expired(unsigned long data)
1da177e4
LT
3476{
3477 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3478
3479 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3480
3481 if (hd->cmdPtr) {
3482 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3483
3484 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3485 /* Desire to issue a task management request here.
3486 * TM requests MUST be single threaded.
3487 * If old eh code and no TM current, issue request.
3488 * If new eh code, do nothing. Wait for OS cmd timeout
3489 * for bus reset.
3490 */
3491 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3492 } else {
3493 /* Perform a FW reload */
3494 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3495 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3496 }
3497 }
3498 } else {
3499 /* This should NEVER happen */
3500 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3501 }
3502
3503 /* No more processing.
3504 * TM call will generate an interrupt for SCSI TM Management.
3505 * The FW will reply to all outstanding commands, callback will finish cleanup.
3506 * Hard reset clean-up will free all resources.
3507 */
3508 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3509
3510 return;
3511}
3512
3513#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3514/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3515/* mptscsih_do_raid - Format and Issue a RAID volume request message.
3516 * @hd: Pointer to scsi host structure
3517 * @action: What do be done.
3518 * @id: Logical target id.
3519 * @bus: Target locations bus.
3520 *
3521 * Returns: < 0 on a fatal error
3522 * 0 on success
3523 *
3524 * Remark: Wait to return until reply processed by the ISR.
3525 */
3526static int
3527mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
3528{
3529 MpiRaidActionRequest_t *pReq;
3530 MPT_FRAME_HDR *mf;
3531 int in_isr;
3532
3533 in_isr = in_interrupt();
3534 if (in_isr) {
3535 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
3536 hd->ioc->name));
3537 return -EPERM;
3538 }
3539
3540 /* Get and Populate a free Frame
3541 */
0d0c7974 3542 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
1da177e4
LT
3543 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
3544 hd->ioc->name));
3545 return -EAGAIN;
3546 }
3547 pReq = (MpiRaidActionRequest_t *)mf;
3548 pReq->Action = action;
3549 pReq->Reserved1 = 0;
3550 pReq->ChainOffset = 0;
3551 pReq->Function = MPI_FUNCTION_RAID_ACTION;
3552 pReq->VolumeID = io->id;
3553 pReq->VolumeBus = io->bus;
3554 pReq->PhysDiskNum = io->physDiskNum;
3555 pReq->MsgFlags = 0;
3556 pReq->Reserved2 = 0;
3557 pReq->ActionDataWord = 0; /* Reserved for this action */
3558 //pReq->ActionDataSGE = 0;
3559
3560 mpt_add_sge((char *)&pReq->ActionDataSGE,
3561 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3562
3563 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
3564 hd->ioc->name, action, io->id));
3565
3566 hd->pLocal = NULL;
3567 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
0d0c7974 3568 hd->scandv_wait_done = 0;
1da177e4
LT
3569
3570 /* Save cmd pointer, for resource free if timeout or
3571 * FW reload occurs
3572 */
3573 hd->cmdPtr = mf;
3574
3575 add_timer(&hd->timer);
0d0c7974
MED
3576 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3577 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
1da177e4
LT
3578
3579 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
3580 return -1;
3581
3582 return 0;
3583}
3584#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3585
3586/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3587/**
3588 * mptscsih_do_cmd - Do internal command.
3589 * @hd: MPT_SCSI_HOST pointer
3590 * @io: INTERNAL_CMD pointer.
3591 *
3592 * Issue the specified internally generated command and do command
3593 * specific cleanup. For bus scan / DV only.
3594 * NOTES: If command is Inquiry and status is good,
3595 * initialize a target structure, save the data
3596 *
3597 * Remark: Single threaded access only.
3598 *
3599 * Return:
3600 * < 0 if an illegal command or no resources
3601 *
3602 * 0 if good
3603 *
3604 * > 0 if command complete but some type of completion error.
3605 */
3606static int
3607mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3608{
3609 MPT_FRAME_HDR *mf;
3610 SCSIIORequest_t *pScsiReq;
3611 SCSIIORequest_t ReqCopy;
3612 int my_idx, ii, dir;
3613 int rc, cmdTimeout;
3614 int in_isr;
3615 char cmdLen;
3616 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3617 char cmd = io->cmd;
3618
3619 in_isr = in_interrupt();
3620 if (in_isr) {
3621 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3622 hd->ioc->name));
3623 return -EPERM;
3624 }
3625
3626
3627 /* Set command specific information
3628 */
3629 switch (cmd) {
3630 case INQUIRY:
3631 cmdLen = 6;
3632 dir = MPI_SCSIIO_CONTROL_READ;
3633 CDB[0] = cmd;
3634 CDB[4] = io->size;
3635 cmdTimeout = 10;
3636 break;
3637
3638 case TEST_UNIT_READY:
3639 cmdLen = 6;
3640 dir = MPI_SCSIIO_CONTROL_READ;
3641 cmdTimeout = 10;
3642 break;
3643
3644 case START_STOP:
3645 cmdLen = 6;
3646 dir = MPI_SCSIIO_CONTROL_READ;
3647 CDB[0] = cmd;
3648 CDB[4] = 1; /*Spin up the disk */
3649 cmdTimeout = 15;
3650 break;
3651
3652 case REQUEST_SENSE:
3653 cmdLen = 6;
3654 CDB[0] = cmd;
3655 CDB[4] = io->size;
3656 dir = MPI_SCSIIO_CONTROL_READ;
3657 cmdTimeout = 10;
3658 break;
3659
3660 case READ_BUFFER:
3661 cmdLen = 10;
3662 dir = MPI_SCSIIO_CONTROL_READ;
3663 CDB[0] = cmd;
3664 if (io->flags & MPT_ICFLAG_ECHO) {
3665 CDB[1] = 0x0A;
3666 } else {
3667 CDB[1] = 0x02;
3668 }
3669
3670 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3671 CDB[1] |= 0x01;
3672 }
3673 CDB[6] = (io->size >> 16) & 0xFF;
3674 CDB[7] = (io->size >> 8) & 0xFF;
3675 CDB[8] = io->size & 0xFF;
3676 cmdTimeout = 10;
3677 break;
3678
3679 case WRITE_BUFFER:
3680 cmdLen = 10;
3681 dir = MPI_SCSIIO_CONTROL_WRITE;
3682 CDB[0] = cmd;
3683 if (io->flags & MPT_ICFLAG_ECHO) {
3684 CDB[1] = 0x0A;
3685 } else {
3686 CDB[1] = 0x02;
3687 }
3688 CDB[6] = (io->size >> 16) & 0xFF;
3689 CDB[7] = (io->size >> 8) & 0xFF;
3690 CDB[8] = io->size & 0xFF;
3691 cmdTimeout = 10;
3692 break;
3693
3694 case RESERVE:
3695 cmdLen = 6;
3696 dir = MPI_SCSIIO_CONTROL_READ;
3697 CDB[0] = cmd;
3698 cmdTimeout = 10;
3699 break;
3700
3701 case RELEASE:
3702 cmdLen = 6;
3703 dir = MPI_SCSIIO_CONTROL_READ;
3704 CDB[0] = cmd;
3705 cmdTimeout = 10;
3706 break;
3707
3708 case SYNCHRONIZE_CACHE:
3709 cmdLen = 10;
3710 dir = MPI_SCSIIO_CONTROL_READ;
3711 CDB[0] = cmd;
3712// CDB[1] = 0x02; /* set immediate bit */
3713 cmdTimeout = 10;
3714 break;
3715
3716 default:
3717 /* Error Case */
3718 return -EFAULT;
3719 }
3720
3721 /* Get and Populate a free Frame
3722 */
0d0c7974 3723 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
1da177e4
LT
3724 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3725 hd->ioc->name));
3726 return -EBUSY;
3727 }
3728
3729 pScsiReq = (SCSIIORequest_t *) mf;
3730
3731 /* Get the request index */
3732 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3733 ADD_INDEX_LOG(my_idx); /* for debug */
3734
3735 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3736 pScsiReq->TargetID = io->physDiskNum;
3737 pScsiReq->Bus = 0;
3738 pScsiReq->ChainOffset = 0;
3739 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3740 } else {
3741 pScsiReq->TargetID = io->id;
3742 pScsiReq->Bus = io->bus;
3743 pScsiReq->ChainOffset = 0;
3744 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3745 }
3746
3747 pScsiReq->CDBLength = cmdLen;
3748 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3749
3750 pScsiReq->Reserved = 0;
3751
3752 pScsiReq->MsgFlags = mpt_msg_flags();
3753 /* MsgContext set in mpt_get_msg_fram call */
3754
3755 for (ii=0; ii < 8; ii++)
3756 pScsiReq->LUN[ii] = 0;
3757 pScsiReq->LUN[1] = io->lun;
3758
3759 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3760 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3761 else
3762 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3763
3764 if (cmd == REQUEST_SENSE) {
3765 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3766 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3767 hd->ioc->name, cmd));
3768 }
3769
3770 for (ii=0; ii < 16; ii++)
3771 pScsiReq->CDB[ii] = CDB[ii];
3772
3773 pScsiReq->DataLength = cpu_to_le32(io->size);
3774 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3775 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3776
3777 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3778 hd->ioc->name, cmd, io->bus, io->id, io->lun));
3779
3780 if (dir == MPI_SCSIIO_CONTROL_READ) {
3781 mpt_add_sge((char *) &pScsiReq->SGL,
3782 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3783 io->data_dma);
3784 } else {
3785 mpt_add_sge((char *) &pScsiReq->SGL,
3786 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3787 io->data_dma);
3788 }
3789
3790 /* The ISR will free the request frame, but we need
3791 * the information to initialize the target. Duplicate.
3792 */
3793 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3794
3795 /* Issue this command after:
3796 * finish init
3797 * add timer
3798 * Wait until the reply has been received
3799 * ScsiScanDvCtx callback function will
3800 * set hd->pLocal;
3801 * set scandv_wait_done and call wake_up
3802 */
3803 hd->pLocal = NULL;
3804 hd->timer.expires = jiffies + HZ*cmdTimeout;
0d0c7974 3805 hd->scandv_wait_done = 0;
1da177e4
LT
3806
3807 /* Save cmd pointer, for resource free if timeout or
3808 * FW reload occurs
3809 */
3810 hd->cmdPtr = mf;
3811
3812 add_timer(&hd->timer);
0d0c7974
MED
3813 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3814 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
1da177e4
LT
3815
3816 if (hd->pLocal) {
3817 rc = hd->pLocal->completion;
3818 hd->pLocal->skip = 0;
3819
3820 /* Always set fatal error codes in some cases.
3821 */
3822 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3823 rc = -ENXIO;
3824 else if (rc == MPT_SCANDV_SOME_ERROR)
3825 rc = -rc;
3826 } else {
3827 rc = -EFAULT;
3828 /* This should never happen. */
3829 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3830 hd->ioc->name));
3831 }
3832
3833 return rc;
3834}
3835
3836/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3837/**
c7c82987
MED
3838 * mptscsih_negotiate_to_asyn_narrow - Restore devices to default state
3839 * @hd: Pointer to a SCSI HOST structure
3840 * @vtarget: per device private data
1da177e4
LT
3841 *
3842 * Uses the ISR, but with special processing.
3843 * MUST be single-threaded.
3844 *
1da177e4 3845 */
c7c82987
MED
3846static void
3847mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
1da177e4
LT
3848{
3849 MPT_ADAPTER *ioc= hd->ioc;
c7c82987 3850 SCSIDevicePage1_t *pcfg1Data;
1da177e4 3851 CONFIGPARMS cfg;
c7c82987
MED
3852 dma_addr_t cfg1_dma_addr;
3853 ConfigPageHeader_t header;
3854 int id;
3855 int requested, configuration, data,i;
1da177e4
LT
3856 u8 flags, factor;
3857
c7c82987
MED
3858 if (ioc->bus_type != SPI)
3859 return;
1da177e4 3860
c7c82987
MED
3861 if (!ioc->spi_data.sdp1length)
3862 return;
1da177e4 3863
c7c82987
MED
3864 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
3865 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
1da177e4 3866
c7c82987
MED
3867 if (pcfg1Data == NULL)
3868 return;
1da177e4 3869
c7c82987
MED
3870 header.PageVersion = ioc->spi_data.sdp1version;
3871 header.PageLength = ioc->spi_data.sdp1length;
3872 header.PageNumber = 1;
3873 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3874 cfg.cfghdr.hdr = &header;
3875 cfg.physAddr = cfg1_dma_addr;
3876 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3877 cfg.dir = 1;
3878 cfg.timeout = 0;
1da177e4 3879
c7c82987
MED
3880 if (vtarget->raidVolume && ioc->raid_data.pIocPg3) {
3881 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
3882 id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID;
3883 flags = hd->ioc->spi_data.noQas;
3884 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3885 data = hd->ioc->spi_data.nvram[id];
3886 if (data & MPT_NVRAM_WIDE_DISABLE)
3887 flags |= MPT_TARGET_NO_NEGO_WIDE;
3888 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
3889 if ((factor == 0) || (factor == MPT_ASYNC))
3890 flags |= MPT_TARGET_NO_NEGO_SYNC;
1da177e4 3891 }
1da177e4 3892 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
c7c82987 3893 &configuration, flags);
1da177e4
LT
3894 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
3895 "offset=0 negoFlags=%x request=%x config=%x\n",
3896 id, flags, requested, configuration));
637fa99b 3897 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
1da177e4 3898 pcfg1Data->Reserved = 0;
637fa99b 3899 pcfg1Data->Configuration = cpu_to_le32(configuration);
c7c82987 3900 cfg.pageAddr = (vtarget->bus_id<<8) | id;
1da177e4
LT
3901 mpt_config(hd->ioc, &cfg);
3902 }
c7c82987
MED
3903 } else {
3904 flags = vtarget->negoFlags;
3905 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
3906 &configuration, flags);
3907 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
3908 "offset=0 negoFlags=%x request=%x config=%x\n",
3909 vtarget->target_id, flags, requested, configuration));
3910 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
3911 pcfg1Data->Reserved = 0;
3912 pcfg1Data->Configuration = cpu_to_le32(configuration);
3913 cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id;
3914 mpt_config(hd->ioc, &cfg);
3915 }
1da177e4 3916
c7c82987
MED
3917 if (pcfg1Data)
3918 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr);
3919}
1da177e4 3920
c7c82987
MED
3921/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3922/**
3923 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3924 * @hd: Pointer to a SCSI HOST structure
3925 * @vtarget: per device private data
3926 * @lun: lun
3927 *
3928 * Uses the ISR, but with special processing.
3929 * MUST be single-threaded.
3930 *
3931 */
3932static void
3933mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3934{
3935 INTERNAL_CMD iocmd;
1da177e4 3936
c7c82987
MED
3937 /* Following parameters will not change
3938 * in this routine.
3939 */
3940 iocmd.cmd = SYNCHRONIZE_CACHE;
3941 iocmd.flags = 0;
3942 iocmd.physDiskNum = -1;
3943 iocmd.data = NULL;
3944 iocmd.data_dma = -1;
3945 iocmd.size = 0;
3946 iocmd.rsvd = iocmd.rsvd2 = 0;
3947 iocmd.bus = vdevice->bus_id;
3948 iocmd.id = vdevice->target_id;
3949 iocmd.lun = (u8)vdevice->lun;
1da177e4 3950
c7c82987
MED
3951 if ((vdevice->vtarget->type & TYPE_DISK) &&
3952 (vdevice->configured_lun))
3953 mptscsih_do_cmd(hd, &iocmd);
1da177e4
LT
3954}
3955
f2ea8671
MED
3956/* Search IOC page 3 to determine if this is hidden physical disk
3957 */
3958static int
3959mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
3960{
3961 int i;
3962
3963 if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
3964 return 0;
3965
3966 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
3967 if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
3968 return 1;
3969 }
3970
3971 return 0;
3972}
3973
1da177e4
LT
3974#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3975/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3976/**
3977 * mptscsih_domainValidation - Top level handler for domain validation.
3978 * @hd: Pointer to MPT_SCSI_HOST structure.
3979 *
3980 * Uses the ISR, but with special processing.
3981 * Called from schedule, should not be in interrupt mode.
3982 * While thread alive, do dv for all devices needing dv
3983 *
3984 * Return: None.
3985 */
3986static void
3987mptscsih_domainValidation(void *arg)
3988{
3989 MPT_SCSI_HOST *hd;
3990 MPT_ADAPTER *ioc;
3991 unsigned long flags;
3992 int id, maxid, dvStatus, did;
3993 int ii, isPhysDisk;
3994
3995 spin_lock_irqsave(&dvtaskQ_lock, flags);
3996 dvtaskQ_active = 1;
3997 if (dvtaskQ_release) {
3998 dvtaskQ_active = 0;
3999 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4000 return;
4001 }
4002 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4003
4004 /* For this ioc, loop through all devices and do dv to each device.
4005 * When complete with this ioc, search through the ioc list, and
4006 * for each scsi ioc found, do dv for all devices. Exit when no
4007 * device needs dv.
4008 */
4009 did = 1;
4010 while (did) {
4011 did = 0;
4012 list_for_each_entry(ioc, &ioc_list, list) {
4013 spin_lock_irqsave(&dvtaskQ_lock, flags);
4014 if (dvtaskQ_release) {
4015 dvtaskQ_active = 0;
4016 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4017 return;
4018 }
4019 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4020
4021 msleep(250);
4022
a9b2937a
MED
4023 /* DV only to SPI adapters */
4024 if (ioc->bus_type != SPI)
1da177e4
LT
4025 continue;
4026
4027 /* Make sure everything looks ok */
4028 if (ioc->sh == NULL)
4029 continue;
4030
4031 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4032 if (hd == NULL)
4033 continue;
4034
4035 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
4036 mpt_read_ioc_pg_3(ioc);
466544d8
MED
4037 if (ioc->raid_data.pIocPg3) {
4038 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
4039 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
1da177e4
LT
4040
4041 while (numPDisk) {
4042 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
4043 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4044
4045 pPDisk++;
4046 numPDisk--;
4047 }
4048 }
4049 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
4050 }
4051
4052 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
4053
4054 for (id = 0; id < maxid; id++) {
4055 spin_lock_irqsave(&dvtaskQ_lock, flags);
4056 if (dvtaskQ_release) {
4057 dvtaskQ_active = 0;
4058 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4059 return;
4060 }
4061 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4062 dvStatus = hd->ioc->spi_data.dvStatus[id];
4063
4064 if (dvStatus & MPT_SCSICFG_NEED_DV) {
4065 did++;
4066 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
4067 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
4068
4069 msleep(250);
4070
4071 /* If hidden phys disk, block IO's to all
4072 * raid volumes
4073 * else, process normally
4074 */
4075 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
4076 if (isPhysDisk) {
4077 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
466544d8 4078 if (hd->ioc->raid_data.isRaid & (1 << ii)) {
1da177e4
LT
4079 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
4080 }
4081 }
4082 }
4083
2a238ea5
MED
4084 if(mpt_alt_ioc_wait(hd->ioc)!=0) {
4085 ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
4086 hd->ioc->name));
4087 continue;
4088 }
4089
1da177e4
LT
4090 if (mptscsih_doDv(hd, 0, id) == 1) {
4091 /* Untagged device was busy, try again
4092 */
4093 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
4094 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
4095 } else {
4096 /* DV is complete. Clear flags.
4097 */
4098 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
4099 }
4100
2a238ea5
MED
4101 spin_lock(&hd->ioc->initializing_hba_lock);
4102 hd->ioc->initializing_hba_lock_flag=0;
4103 spin_unlock(&hd->ioc->initializing_hba_lock);
4104
1da177e4
LT
4105 if (isPhysDisk) {
4106 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
466544d8 4107 if (hd->ioc->raid_data.isRaid & (1 << ii)) {
1da177e4
LT
4108 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
4109 }
4110 }
4111 }
4112
4113 if (hd->ioc->spi_data.noQas)
4114 mptscsih_qas_check(hd, id);
4115 }
4116 }
4117 }
4118 }
4119
4120 spin_lock_irqsave(&dvtaskQ_lock, flags);
4121 dvtaskQ_active = 0;
4122 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4123
4124 return;
4125}
4126
1da177e4
LT
4127/* Write SDP1 if no QAS has been enabled
4128 */
0d0c7974
MED
4129static void
4130mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
1da177e4 4131{
c7c82987 4132 VirtTarget *vtarget;
1da177e4
LT
4133 int ii;
4134
4135 if (hd->Targets == NULL)
4136 return;
4137
4138 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4139 if (ii == id)
4140 continue;
4141
4142 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
4143 continue;
4144
c7c82987 4145 vtarget = hd->Targets[ii];
1da177e4 4146
c7c82987
MED
4147 if ((vtarget != NULL) && (!vtarget->raidVolume)) {
4148 if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
4149 vtarget->negoFlags |= hd->ioc->spi_data.noQas;
1da177e4
LT
4150 dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
4151 mptscsih_writeSDP1(hd, 0, ii, 0);
4152 }
4153 } else {
4154 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
4155 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
4156 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
4157 }
4158 }
4159 }
4160 return;
4161}
4162
4163
4164
4165#define MPT_GET_NVRAM_VALS 0x01
4166#define MPT_UPDATE_MAX 0x02
4167#define MPT_SET_MAX 0x04
4168#define MPT_SET_MIN 0x08
4169#define MPT_FALLBACK 0x10
4170#define MPT_SAVE 0x20
4171
4172/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4173/**
4174 * mptscsih_doDv - Perform domain validation to a target.
4175 * @hd: Pointer to MPT_SCSI_HOST structure.
4176 * @portnum: IOC port number.
4177 * @target: Physical ID of this target
4178 *
4179 * Uses the ISR, but with special processing.
4180 * MUST be single-threaded.
4181 * Test will exit if target is at async & narrow.
4182 *
4183 * Return: None.
4184 */
4185static int
4186mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
4187{
4188 MPT_ADAPTER *ioc = hd->ioc;
c7c82987 4189 VirtTarget *vtarget;
1da177e4
LT
4190 SCSIDevicePage1_t *pcfg1Data;
4191 SCSIDevicePage0_t *pcfg0Data;
4192 u8 *pbuf1;
4193 u8 *pbuf2;
4194 u8 *pDvBuf;
4195 dma_addr_t dvbuf_dma = -1;
4196 dma_addr_t buf1_dma = -1;
4197 dma_addr_t buf2_dma = -1;
4198 dma_addr_t cfg1_dma_addr = -1;
4199 dma_addr_t cfg0_dma_addr = -1;
4200 ConfigPageHeader_t header1;
4201 ConfigPageHeader_t header0;
4202 DVPARAMETERS dv;
4203 INTERNAL_CMD iocmd;
4204 CONFIGPARMS cfg;
4205 int dv_alloc = 0;
4206 int rc, sz = 0;
4207 int bufsize = 0;
4208 int dataBufSize = 0;
4209 int echoBufSize = 0;
4210 int notDone;
4211 int patt;
4212 int repeat;
4213 int retcode = 0;
4214 int nfactor = MPT_ULTRA320;
4215 char firstPass = 1;
4216 char doFallback = 0;
4217 char readPage0;
4218 char bus, lun;
4219 char inq0 = 0;
4220
4221 if (ioc->spi_data.sdp1length == 0)
4222 return 0;
4223
4224 if (ioc->spi_data.sdp0length == 0)
4225 return 0;
4226
4227 /* If multiple buses are used, require that the initiator
4228 * id be the same on all buses.
4229 */
4230 if (id == ioc->pfacts[0].PortSCSIID)
4231 return 0;
4232
4233 lun = 0;
4234 bus = (u8) bus_number;
4235 ddvtprintk((MYIOC_s_NOTE_FMT
4236 "DV started: bus=%d, id=%d dv @ %p\n",
4237 ioc->name, bus, id, &dv));
4238
4239 /* Prep DV structure
4240 */
4241 memset (&dv, 0, sizeof(DVPARAMETERS));
4242 dv.id = id;
4243
4244 /* Populate tmax with the current maximum
4245 * transfer parameters for this target.
4246 * Exit if narrow and async.
4247 */
4248 dv.cmd = MPT_GET_NVRAM_VALS;
4249 mptscsih_dv_parms(hd, &dv, NULL);
4250
4251 /* Prep SCSI IO structure
4252 */
4253 iocmd.id = id;
4254 iocmd.bus = bus;
4255 iocmd.lun = lun;
4256 iocmd.flags = 0;
4257 iocmd.physDiskNum = -1;
4258 iocmd.rsvd = iocmd.rsvd2 = 0;
4259
c7c82987 4260 vtarget = hd->Targets[id];
1da177e4
LT
4261
4262 /* Use tagged commands if possible.
4263 */
c7c82987
MED
4264 if (vtarget) {
4265 if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1da177e4
LT
4266 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
4267 else {
4268 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
4269 return 0;
4270
4271 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4272 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
4273 return 0;
4274 }
4275 }
4276
4277 /* Prep cfg structure
4278 */
4279 cfg.pageAddr = (bus<<8) | id;
69218ee5 4280 cfg.cfghdr.hdr = NULL;
1da177e4
LT
4281
4282 /* Prep SDP0 header
4283 */
4284 header0.PageVersion = ioc->spi_data.sdp0version;
4285 header0.PageLength = ioc->spi_data.sdp0length;
4286 header0.PageNumber = 0;
4287 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4288
4289 /* Prep SDP1 header
4290 */
4291 header1.PageVersion = ioc->spi_data.sdp1version;
4292 header1.PageLength = ioc->spi_data.sdp1length;
4293 header1.PageNumber = 1;
4294 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4295
4296 if (header0.PageLength & 1)
4297 dv_alloc = (header0.PageLength * 4) + 4;
4298
4299 dv_alloc += (2048 + (header1.PageLength * 4));
4300
4301 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
4302 if (pDvBuf == NULL)
4303 return 0;
4304
4305 sz = 0;
4306 pbuf1 = (u8 *)pDvBuf;
4307 buf1_dma = dvbuf_dma;
4308 sz +=1024;
4309
4310 pbuf2 = (u8 *) (pDvBuf + sz);
4311 buf2_dma = dvbuf_dma + sz;
4312 sz +=1024;
4313
4314 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
4315 cfg0_dma_addr = dvbuf_dma + sz;
4316 sz += header0.PageLength * 4;
4317
4318 /* 8-byte alignment
4319 */
4320 if (header0.PageLength & 1)
4321 sz += 4;
4322
4323 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
4324 cfg1_dma_addr = dvbuf_dma + sz;
4325
69218ee5 4326 /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
1da177e4
LT
4327 */
4328 {
466544d8 4329 SpiCfgData *pspi_data = &hd->ioc->spi_data;
1da177e4
LT
4330 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4331 /* Set the factor from nvram */
4332 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
4333 if (nfactor < pspi_data->minSyncFactor )
4334 nfactor = pspi_data->minSyncFactor;
4335
4336 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
4337 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
4338
4339 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
4340 ioc->name, bus, id, lun));
4341
4342 dv.cmd = MPT_SET_MAX;
4343 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
69218ee5 4344 cfg.cfghdr.hdr = &header1;
1da177e4
LT
4345
4346 /* Save the final negotiated settings to
4347 * SCSI device page 1.
4348 */
4349 cfg.physAddr = cfg1_dma_addr;
4350 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4351 cfg.dir = 1;
4352 mpt_config(hd->ioc, &cfg);
4353 goto target_done;
4354 }
4355 }
4356 }
4357
4358 /* Finish iocmd inititialization - hidden or visible disk? */
466544d8 4359 if (ioc->raid_data.pIocPg3) {
1da177e4
LT
4360 /* Search IOC page 3 for matching id
4361 */
466544d8
MED
4362 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
4363 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
1da177e4
LT
4364
4365 while (numPDisk) {
4366 if (pPDisk->PhysDiskID == id) {
4367 /* match */
4368 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
4369 iocmd.physDiskNum = pPDisk->PhysDiskNum;
4370
4371 /* Quiesce the IM
4372 */
4373 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
4374 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
4375 goto target_done;
4376 }
4377 break;
4378 }
4379 pPDisk++;
4380 numPDisk--;
4381 }
4382 }
4383
4384 /* RAID Volume ID's may double for a physical device. If RAID but
4385 * not a physical ID as well, skip DV.
4386 */
466544d8 4387 if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
1da177e4
LT
4388 goto target_done;
4389
4390
4391 /* Basic Test.
4392 * Async & Narrow - Inquiry
4393 * Async & Narrow - Inquiry
4394 * Maximum transfer rate - Inquiry
4395 * Compare buffers:
4396 * If compare, test complete.
4397 * If miscompare and first pass, repeat
4398 * If miscompare and not first pass, fall back and repeat
4399 */
4400 hd->pLocal = NULL;
4401 readPage0 = 0;
4402 sz = SCSI_MAX_INQUIRY_BYTES;
4403 rc = MPT_SCANDV_GOOD;
4404 while (1) {
4405 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
4406 retcode = 0;
4407 dv.cmd = MPT_SET_MIN;
4408 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4409
69218ee5 4410 cfg.cfghdr.hdr = &header1;
1da177e4
LT
4411 cfg.physAddr = cfg1_dma_addr;
4412 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4413 cfg.dir = 1;
4414 if (mpt_config(hd->ioc, &cfg) != 0)
4415 goto target_done;
4416
4417 /* Wide - narrow - wide workaround case
4418 */
4419 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
4420 /* Send an untagged command to reset disk Qs corrupted
4421 * when a parity error occurs on a Request Sense.
4422 */
4423 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
4424 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4425 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
4426
4427 iocmd.cmd = REQUEST_SENSE;
4428 iocmd.data_dma = buf1_dma;
4429 iocmd.data = pbuf1;
4430 iocmd.size = 0x12;
4431 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4432 goto target_done;
4433 else {
4434 if (hd->pLocal == NULL)
4435 goto target_done;
4436 rc = hd->pLocal->completion;
4437 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
4438 dv.max.width = 0;
4439 doFallback = 0;
4440 } else
4441 goto target_done;
4442 }
4443 } else
4444 goto target_done;
4445 }
4446
4447 iocmd.cmd = INQUIRY;
4448 iocmd.data_dma = buf1_dma;
4449 iocmd.data = pbuf1;
4450 iocmd.size = sz;
4451 memset(pbuf1, 0x00, sz);
4452 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4453 goto target_done;
4454 else {
4455 if (hd->pLocal == NULL)
4456 goto target_done;
4457 rc = hd->pLocal->completion;
4458 if (rc == MPT_SCANDV_GOOD) {
4459 if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
4460 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
4461 retcode = 1;
4462 else
4463 retcode = 0;
4464
4465 goto target_done;
4466 }
4467 } else if (rc == MPT_SCANDV_SENSE) {
4468 ;
4469 } else {
4470 /* If first command doesn't complete
4471 * with a good status or with a check condition,
4472 * exit.
4473 */
4474 goto target_done;
4475 }
4476 }
4477
4478 /* Reset the size for disks
4479 */
4480 inq0 = (*pbuf1) & 0x1F;
c7c82987 4481 if ((inq0 == 0) && vtarget && !vtarget->raidVolume) {
1da177e4
LT
4482 sz = 0x40;
4483 iocmd.size = sz;
4484 }
4485
4486 /* Another GEM workaround. Check peripheral device type,
4487 * if PROCESSOR, quit DV.
4488 */
4489 if (inq0 == TYPE_PROCESSOR) {
4490 mptscsih_initTarget(hd,
c7c82987 4491 vtarget,
1da177e4
LT
4492 lun,
4493 pbuf1,
4494 sz);
4495 goto target_done;
4496 }
4497
4498 if (inq0 > 0x08)
4499 goto target_done;
4500
4501 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4502 goto target_done;
4503
4504 if (sz == 0x40) {
c7c82987
MED
4505 if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A)
4506 && (vtarget->minSyncFactor > 0x09)) {
1da177e4
LT
4507 if ((pbuf1[56] & 0x04) == 0)
4508 ;
4509 else if ((pbuf1[56] & 0x01) == 1) {
c7c82987 4510 vtarget->minSyncFactor =
1da177e4
LT
4511 nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
4512 } else {
c7c82987 4513 vtarget->minSyncFactor =
1da177e4
LT
4514 nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
4515 }
4516
c7c82987 4517 dv.max.factor = vtarget->minSyncFactor;
1da177e4
LT
4518
4519 if ((pbuf1[56] & 0x02) == 0) {
c7c82987 4520 vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
1da177e4 4521 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
c6678e0c
CH
4522 ddvprintk((MYIOC_s_NOTE_FMT
4523 "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
1da177e4
LT
4524 ioc->name, id, pbuf1[56]));
4525 }
4526 }
4527 }
4528
4529 if (doFallback)
4530 dv.cmd = MPT_FALLBACK;
4531 else
4532 dv.cmd = MPT_SET_MAX;
4533
4534 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4535 if (mpt_config(hd->ioc, &cfg) != 0)
4536 goto target_done;
4537
4538 if ((!dv.now.width) && (!dv.now.offset))
4539 goto target_done;
4540
4541 iocmd.cmd = INQUIRY;
4542 iocmd.data_dma = buf2_dma;
4543 iocmd.data = pbuf2;
4544 iocmd.size = sz;
4545 memset(pbuf2, 0x00, sz);
4546 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4547 goto target_done;
4548 else if (hd->pLocal == NULL)
4549 goto target_done;
4550 else {
4551 /* Save the return code.
4552 * If this is the first pass,
4553 * read SCSI Device Page 0
4554 * and update the target max parameters.
4555 */
4556 rc = hd->pLocal->completion;
4557 doFallback = 0;
4558 if (rc == MPT_SCANDV_GOOD) {
4559 if (!readPage0) {
4560 u32 sdp0_info;
4561 u32 sdp0_nego;
4562
69218ee5 4563 cfg.cfghdr.hdr = &header0;
1da177e4
LT
4564 cfg.physAddr = cfg0_dma_addr;
4565 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4566 cfg.dir = 0;
4567
4568 if (mpt_config(hd->ioc, &cfg) != 0)
4569 goto target_done;
4570
4571 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
4572 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
4573
4574 /* Quantum and Fujitsu workarounds.
4575 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4576 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4577 * Resetart with a request for U160.
4578 */
4579 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
4580 doFallback = 1;
4581 } else {
4582 dv.cmd = MPT_UPDATE_MAX;
4583 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
4584 /* Update the SCSI device page 1 area
4585 */
4586 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
4587 readPage0 = 1;
4588 }
4589 }
4590
4591 /* Quantum workaround. Restart this test will the fallback
4592 * flag set.
4593 */
4594 if (doFallback == 0) {
4595 if (memcmp(pbuf1, pbuf2, sz) != 0) {
4596 if (!firstPass)
4597 doFallback = 1;
4598 } else {
c6678e0c 4599 ddvprintk((MYIOC_s_NOTE_FMT
1da177e4
LT
4600 "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
4601 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
4602 mptscsih_initTarget(hd,
c7c82987 4603 vtarget,
1da177e4
LT
4604 lun,
4605 pbuf1,
4606 sz);
4607 break; /* test complete */
4608 }
4609 }
4610
4611
4612 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
4613 doFallback = 1; /* set fallback flag */
c6678e0c
CH
4614 else if ((rc == MPT_SCANDV_DID_RESET) ||
4615 (rc == MPT_SCANDV_SENSE) ||
1da177e4
LT
4616 (rc == MPT_SCANDV_FALLBACK))
4617 doFallback = 1; /* set fallback flag */
4618 else
4619 goto target_done;
4620
4621 firstPass = 0;
4622 }
4623 }
4624 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
4625
0d0c7974 4626 if (ioc->spi_data.mpt_dv == 0)
1da177e4
LT
4627 goto target_done;
4628
4629 inq0 = (*pbuf1) & 0x1F;
4630
4631 /* Continue only for disks
4632 */
4633 if (inq0 != 0)
4634 goto target_done;
4635
4636 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
4637 goto target_done;
4638
4639 /* Start the Enhanced Test.
4640 * 0) issue TUR to clear out check conditions
4641 * 1) read capacity of echo (regular) buffer
4642 * 2) reserve device
4643 * 3) do write-read-compare data pattern test
4644 * 4) release
4645 * 5) update nego parms to target struct
4646 */
69218ee5 4647 cfg.cfghdr.hdr = &header1;
1da177e4
LT
4648 cfg.physAddr = cfg1_dma_addr;
4649 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4650 cfg.dir = 1;
4651
4652 iocmd.cmd = TEST_UNIT_READY;
4653 iocmd.data_dma = -1;
4654 iocmd.data = NULL;
4655 iocmd.size = 0;
4656 notDone = 1;
4657 while (notDone) {
4658 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4659 goto target_done;
4660
4661 if (hd->pLocal == NULL)
4662 goto target_done;
4663
4664 rc = hd->pLocal->completion;
4665 if (rc == MPT_SCANDV_GOOD)
4666 notDone = 0;
4667 else if (rc == MPT_SCANDV_SENSE) {
4668 u8 skey = hd->pLocal->sense[2] & 0x0F;
4669 u8 asc = hd->pLocal->sense[12];
4670 u8 ascq = hd->pLocal->sense[13];
4671 ddvprintk((MYIOC_s_INFO_FMT
4672 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4673 ioc->name, skey, asc, ascq));
4674
4675 if (skey == UNIT_ATTENTION)
4676 notDone++; /* repeat */
4677 else if ((skey == NOT_READY) &&
4678 (asc == 0x04)&&(ascq == 0x01)) {
4679 /* wait then repeat */
4680 mdelay (2000);
4681 notDone++;
4682 } else if ((skey == NOT_READY) && (asc == 0x3A)) {
4683 /* no medium, try read test anyway */
4684 notDone = 0;
4685 } else {
4686 /* All other errors are fatal.
4687 */
4688 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4689 ioc->name));
4690 goto target_done;
4691 }
4692 } else
4693 goto target_done;
4694 }
4695
4696 iocmd.cmd = READ_BUFFER;
4697 iocmd.data_dma = buf1_dma;
4698 iocmd.data = pbuf1;
4699 iocmd.size = 4;
4700 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
4701
4702 dataBufSize = 0;
4703 echoBufSize = 0;
4704 for (patt = 0; patt < 2; patt++) {
4705 if (patt == 0)
4706 iocmd.flags |= MPT_ICFLAG_ECHO;
4707 else
4708 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4709
4710 notDone = 1;
4711 while (notDone) {
4712 bufsize = 0;
4713
4714 /* If not ready after 8 trials,
4715 * give up on this device.
4716 */
4717 if (notDone > 8)
4718 goto target_done;
4719
4720 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4721 goto target_done;
4722 else if (hd->pLocal == NULL)
4723 goto target_done;
4724 else {
4725 rc = hd->pLocal->completion;
4726 ddvprintk(("ReadBuffer Comp Code %d", rc));
4727 ddvprintk((" buff: %0x %0x %0x %0x\n",
4728 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
4729
4730 if (rc == MPT_SCANDV_GOOD) {
4731 notDone = 0;
4732 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4733 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
466544d8
MED
4734 if (pbuf1[0] & 0x01)
4735 iocmd.flags |= MPT_ICFLAG_EBOS;
1da177e4
LT
4736 } else {
4737 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
4738 }
4739 } else if (rc == MPT_SCANDV_SENSE) {
4740 u8 skey = hd->pLocal->sense[2] & 0x0F;
4741 u8 asc = hd->pLocal->sense[12];
4742 u8 ascq = hd->pLocal->sense[13];
4743 ddvprintk((MYIOC_s_INFO_FMT
4744 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4745 ioc->name, skey, asc, ascq));
4746 if (skey == ILLEGAL_REQUEST) {
4747 notDone = 0;
4748 } else if (skey == UNIT_ATTENTION) {
4749 notDone++; /* repeat */
4750 } else if ((skey == NOT_READY) &&
4751 (asc == 0x04)&&(ascq == 0x01)) {
4752 /* wait then repeat */
4753 mdelay (2000);
4754 notDone++;
4755 } else {
4756 /* All other errors are fatal.
4757 */
4758 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4759 ioc->name));
4760 goto target_done;
4761 }
4762 } else {
4763 /* All other errors are fatal
4764 */
4765 goto target_done;
4766 }
4767 }
4768 }
4769
4770 if (iocmd.flags & MPT_ICFLAG_ECHO)
4771 echoBufSize = bufsize;
4772 else
4773 dataBufSize = bufsize;
4774 }
4775 sz = 0;
4776 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
4777
4778 /* Use echo buffers if possible,
4779 * Exit if both buffers are 0.
4780 */
4781 if (echoBufSize > 0) {
4782 iocmd.flags |= MPT_ICFLAG_ECHO;
4783 if (dataBufSize > 0)
4784 bufsize = min(echoBufSize, dataBufSize);
4785 else
4786 bufsize = echoBufSize;
4787 } else if (dataBufSize == 0)
4788 goto target_done;
4789
4790 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
4791 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
4792
4793 /* Data buffers for write-read-compare test max 1K.
4794 */
4795 sz = min(bufsize, 1024);
4796
4797 /* --- loop ----
4798 * On first pass, always issue a reserve.
4799 * On additional loops, only if a reset has occurred.
4800 * iocmd.flags indicates if echo or regular buffer
4801 */
4802 for (patt = 0; patt < 4; patt++) {
4803 ddvprintk(("Pattern %d\n", patt));
4804 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
4805 iocmd.cmd = TEST_UNIT_READY;
4806 iocmd.data_dma = -1;
4807 iocmd.data = NULL;
4808 iocmd.size = 0;
4809 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4810 goto target_done;
4811
4812 iocmd.cmd = RELEASE;
4813 iocmd.data_dma = -1;
4814 iocmd.data = NULL;
4815 iocmd.size = 0;
4816 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4817 goto target_done;
4818 else if (hd->pLocal == NULL)
4819 goto target_done;
4820 else {
4821 rc = hd->pLocal->completion;
4822 ddvprintk(("Release rc %d\n", rc));
4823 if (rc == MPT_SCANDV_GOOD)
4824 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4825 else
4826 goto target_done;
4827 }
4828 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4829 }
4830 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
4831
466544d8
MED
4832 if (iocmd.flags & MPT_ICFLAG_EBOS)
4833 goto skip_Reserve;
4834
1da177e4
LT
4835 repeat = 5;
4836 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
4837 iocmd.cmd = RESERVE;
4838 iocmd.data_dma = -1;
4839 iocmd.data = NULL;
4840 iocmd.size = 0;
4841 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4842 goto target_done;
4843 else if (hd->pLocal == NULL)
4844 goto target_done;
4845 else {
4846 rc = hd->pLocal->completion;
4847 if (rc == MPT_SCANDV_GOOD) {
4848 iocmd.flags |= MPT_ICFLAG_RESERVED;
4849 } else if (rc == MPT_SCANDV_SENSE) {
4850 /* Wait if coming ready
4851 */
4852 u8 skey = hd->pLocal->sense[2] & 0x0F;
4853 u8 asc = hd->pLocal->sense[12];
4854 u8 ascq = hd->pLocal->sense[13];
4855 ddvprintk((MYIOC_s_INFO_FMT
4856 "DV: Reserve Failed: ", ioc->name));
4857 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4858 skey, asc, ascq));
4859
4860 if ((skey == NOT_READY) && (asc == 0x04)&&
4861 (ascq == 0x01)) {
4862 /* wait then repeat */
4863 mdelay (2000);
4864 notDone++;
4865 } else {
4866 ddvprintk((MYIOC_s_INFO_FMT
4867 "DV: Reserved Failed.", ioc->name));
4868 goto target_done;
4869 }
4870 } else {
4871 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
4872 ioc->name));
4873 goto target_done;
4874 }
4875 }
4876 }
4877
466544d8 4878skip_Reserve:
1da177e4
LT
4879 mptscsih_fillbuf(pbuf1, sz, patt, 1);
4880 iocmd.cmd = WRITE_BUFFER;
4881 iocmd.data_dma = buf1_dma;
4882 iocmd.data = pbuf1;
4883 iocmd.size = sz;
4884 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4885 goto target_done;
4886 else if (hd->pLocal == NULL)
4887 goto target_done;
4888 else {
4889 rc = hd->pLocal->completion;
4890 if (rc == MPT_SCANDV_GOOD)
4891 ; /* Issue read buffer */
4892 else if (rc == MPT_SCANDV_DID_RESET) {
4893 /* If using echo buffers, reset to data buffers.
4894 * Else do Fallback and restart
4895 * this test (re-issue reserve
4896 * because of bus reset).
4897 */
4898 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
4899 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4900 } else {
4901 dv.cmd = MPT_FALLBACK;
4902 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4903
4904 if (mpt_config(hd->ioc, &cfg) != 0)
4905 goto target_done;
4906
4907 if ((!dv.now.width) && (!dv.now.offset))
4908 goto target_done;
4909 }
4910
4911 iocmd.flags |= MPT_ICFLAG_DID_RESET;
4912 patt = -1;
4913 continue;
4914 } else if (rc == MPT_SCANDV_SENSE) {
4915 /* Restart data test if UA, else quit.
4916 */
4917 u8 skey = hd->pLocal->sense[2] & 0x0F;
4918 ddvprintk((MYIOC_s_INFO_FMT
4919 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
4920 hd->pLocal->sense[12], hd->pLocal->sense[13]));
4921 if (skey == UNIT_ATTENTION) {
4922 patt = -1;
4923 continue;
4924 } else if (skey == ILLEGAL_REQUEST) {
4925 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4926 if (dataBufSize >= bufsize) {
4927 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4928 patt = -1;
4929 continue;
4930 }
4931 }
4932 goto target_done;
4933 }
4934 else
4935 goto target_done;
4936 } else {
4937 /* fatal error */
4938 goto target_done;
4939 }
4940 }
4941
4942 iocmd.cmd = READ_BUFFER;
4943 iocmd.data_dma = buf2_dma;
4944 iocmd.data = pbuf2;
4945 iocmd.size = sz;
4946 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4947 goto target_done;
4948 else if (hd->pLocal == NULL)
4949 goto target_done;
4950 else {
4951 rc = hd->pLocal->completion;
4952 if (rc == MPT_SCANDV_GOOD) {
4953 /* If buffers compare,
4954 * go to next pattern,
4955 * else, do a fallback and restart
4956 * data transfer test.
4957 */
4958 if (memcmp (pbuf1, pbuf2, sz) == 0) {
4959 ; /* goto next pattern */
4960 } else {
4961 /* Miscompare with Echo buffer, go to data buffer,
4962 * if that buffer exists.
4963 * Miscompare with Data buffer, check first 4 bytes,
4964 * some devices return capacity. Exit in this case.
4965 */
4966 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4967 if (dataBufSize >= bufsize)
4968 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4969 else
4970 goto target_done;
4971 } else {
4972 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
4973 /* Argh. Device returning wrong data.
4974 * Quit DV for this device.
4975 */
4976 goto target_done;
4977 }
4978
4979 /* Had an actual miscompare. Slow down.*/
4980 dv.cmd = MPT_FALLBACK;
4981 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4982
4983 if (mpt_config(hd->ioc, &cfg) != 0)
4984 goto target_done;
4985
4986 if ((!dv.now.width) && (!dv.now.offset))
4987 goto target_done;
4988 }
4989
4990 patt = -1;
4991 continue;
4992 }
4993 } else if (rc == MPT_SCANDV_DID_RESET) {
4994 /* Do Fallback and restart
4995 * this test (re-issue reserve
4996 * because of bus reset).
4997 */
4998 dv.cmd = MPT_FALLBACK;
4999 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5000
5001 if (mpt_config(hd->ioc, &cfg) != 0)
5002 goto target_done;
5003
5004 if ((!dv.now.width) && (!dv.now.offset))
5005 goto target_done;
5006
5007 iocmd.flags |= MPT_ICFLAG_DID_RESET;
5008 patt = -1;
5009 continue;
5010 } else if (rc == MPT_SCANDV_SENSE) {
5011 /* Restart data test if UA, else quit.
5012 */
5013 u8 skey = hd->pLocal->sense[2] & 0x0F;
5014 ddvprintk((MYIOC_s_INFO_FMT
5015 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
5016 hd->pLocal->sense[12], hd->pLocal->sense[13]));
5017 if (skey == UNIT_ATTENTION) {
5018 patt = -1;
5019 continue;
5020 }
5021 else
5022 goto target_done;
5023 } else {
5024 /* fatal error */
5025 goto target_done;
5026 }
5027 }
5028
5029 } /* --- end of patt loop ---- */
5030
5031target_done:
5032 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
5033 iocmd.cmd = RELEASE;
5034 iocmd.data_dma = -1;
5035 iocmd.data = NULL;
5036 iocmd.size = 0;
5037 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5038 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5039 ioc->name, id);
5040 else if (hd->pLocal) {
5041 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
5042 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
5043 } else {
5044 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5045 ioc->name, id);
5046 }
5047 }
5048
5049
5050 /* Set if cfg1_dma_addr contents is valid
5051 */
69218ee5 5052 if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
1da177e4
LT
5053 /* If disk, not U320, disable QAS
5054 */
5055 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
5056 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
c6678e0c 5057 ddvprintk((MYIOC_s_NOTE_FMT
1da177e4
LT
5058 "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
5059 }
5060
5061 dv.cmd = MPT_SAVE;
5062 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5063
5064 /* Double writes to SDP1 can cause problems,
5065 * skip save of the final negotiated settings to
5066 * SCSI device page 1.
5067 *
69218ee5 5068 cfg.cfghdr.hdr = &header1;
1da177e4
LT
5069 cfg.physAddr = cfg1_dma_addr;
5070 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5071 cfg.dir = 1;
5072 mpt_config(hd->ioc, &cfg);
5073 */
5074 }
5075
5076 /* If this is a RAID Passthrough, enable internal IOs
5077 */
5078 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
5079 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
5080 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
5081 }
5082
5083 /* Done with the DV scan of the current target
5084 */
5085 if (pDvBuf)
5086 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
5087
5088 ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
5089 ioc->name, id));
5090
5091 return retcode;
5092}
5093
5094/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5095/* mptscsih_dv_parms - perform a variety of operations on the
5096 * parameters used for negotiation.
5097 * @hd: Pointer to a SCSI host.
5098 * @dv: Pointer to a structure that contains the maximum and current
5099 * negotiated parameters.
5100 */
5101static void
5102mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
5103{
c7c82987 5104 VirtTarget *vtarget;
1da177e4
LT
5105 SCSIDevicePage0_t *pPage0;
5106 SCSIDevicePage1_t *pPage1;
5107 int val = 0, data, configuration;
5108 u8 width = 0;
5109 u8 offset = 0;
5110 u8 factor = 0;
5111 u8 negoFlags = 0;
5112 u8 cmd = dv->cmd;
5113 u8 id = dv->id;
5114
5115 switch (cmd) {
5116 case MPT_GET_NVRAM_VALS:
5117 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
5118 hd->ioc->name));
5119 /* Get the NVRAM values and save in tmax
5120 * If not an LVD bus, the adapter minSyncFactor has been
5121 * already throttled back.
5122 */
466544d8 5123 negoFlags = hd->ioc->spi_data.noQas;
c7c82987
MED
5124 if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) {
5125 width = vtarget->maxWidth;
5126 offset = vtarget->maxOffset;
5127 factor = vtarget->minSyncFactor;
5128 negoFlags |= vtarget->negoFlags;
1da177e4
LT
5129 } else {
5130 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5131 data = hd->ioc->spi_data.nvram[id];
5132 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5133 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
5134 factor = MPT_ASYNC;
5135 else {
5136 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5137 if ((factor == 0) || (factor == MPT_ASYNC)){
5138 factor = MPT_ASYNC;
5139 offset = 0;
5140 }
5141 }
5142 } else {
5143 width = MPT_NARROW;
5144 offset = 0;
5145 factor = MPT_ASYNC;
5146 }
5147
5148 /* Set the negotiation flags */
1da177e4
LT
5149 if (!width)
5150 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5151
5152 if (!offset)
5153 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5154 }
5155
5156 /* limit by adapter capabilities */
5157 width = min(width, hd->ioc->spi_data.maxBusWidth);
5158 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
5159 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
5160
5161 /* Check Consistency */
5162 if (offset && (factor < MPT_ULTRA2) && !width)
5163 factor = MPT_ULTRA2;
5164
5165 dv->max.width = width;
5166 dv->max.offset = offset;
5167 dv->max.factor = factor;
5168 dv->max.flags = negoFlags;
5169 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5170 id, width, factor, offset, negoFlags));
5171 break;
5172
5173 case MPT_UPDATE_MAX:
5174 ddvprintk((MYIOC_s_NOTE_FMT
5175 "Updating with SDP0 Data: ", hd->ioc->name));
5176 /* Update tmax values with those from Device Page 0.*/
5177 pPage0 = (SCSIDevicePage0_t *) pPage;
5178 if (pPage0) {
637fa99b 5179 val = le32_to_cpu(pPage0->NegotiatedParameters);
1da177e4
LT
5180 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
5181 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
5182 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
5183 }
5184
5185 dv->now.width = dv->max.width;
5186 dv->now.offset = dv->max.offset;
5187 dv->now.factor = dv->max.factor;
5188 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5189 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5190 break;
5191
5192 case MPT_SET_MAX:
5193 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
5194 hd->ioc->name));
5195 /* Set current to the max values. Update the config page.*/
5196 dv->now.width = dv->max.width;
5197 dv->now.offset = dv->max.offset;
5198 dv->now.factor = dv->max.factor;
5199 dv->now.flags = dv->max.flags;
5200
5201 pPage1 = (SCSIDevicePage1_t *)pPage;
5202 if (pPage1) {
5203 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
5204 dv->now.offset, &val, &configuration, dv->now.flags);
5205 dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5206 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
637fa99b 5207 pPage1->RequestedParameters = cpu_to_le32(val);
1da177e4 5208 pPage1->Reserved = 0;
637fa99b 5209 pPage1->Configuration = cpu_to_le32(configuration);
1da177e4
LT
5210 }
5211
637fa99b 5212 ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
1da177e4
LT
5213 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5214 break;
5215
5216 case MPT_SET_MIN:
5217 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
5218 hd->ioc->name));
5219 /* Set page to asynchronous and narrow
5220 * Do not update now, breaks fallback routine. */
5221 width = MPT_NARROW;
5222 offset = 0;
5223 factor = MPT_ASYNC;
5224 negoFlags = dv->max.flags;
5225
5226 pPage1 = (SCSIDevicePage1_t *)pPage;
5227 if (pPage1) {
5228 mptscsih_setDevicePage1Flags (width, factor,
5229 offset, &val, &configuration, negoFlags);
5230 dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5231 id, width, factor, offset, negoFlags, val, configuration));
637fa99b 5232 pPage1->RequestedParameters = cpu_to_le32(val);
1da177e4 5233 pPage1->Reserved = 0;
637fa99b 5234 pPage1->Configuration = cpu_to_le32(configuration);
1da177e4
LT
5235 }
5236 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5237 id, width, factor, offset, val, configuration, negoFlags));
5238 break;
5239
5240 case MPT_FALLBACK:
5241 ddvprintk((MYIOC_s_NOTE_FMT
5242 "Fallback: Start: offset %d, factor %x, width %d \n",
5243 hd->ioc->name, dv->now.offset,
5244 dv->now.factor, dv->now.width));
5245 width = dv->now.width;
5246 offset = dv->now.offset;
5247 factor = dv->now.factor;
5248 if ((offset) && (dv->max.width)) {
5249 if (factor < MPT_ULTRA160)
5250 factor = MPT_ULTRA160;
5251 else if (factor < MPT_ULTRA2) {
5252 factor = MPT_ULTRA2;
5253 width = MPT_WIDE;
5254 } else if ((factor == MPT_ULTRA2) && width) {
5255 factor = MPT_ULTRA2;
5256 width = MPT_NARROW;
5257 } else if (factor < MPT_ULTRA) {
5258 factor = MPT_ULTRA;
5259 width = MPT_WIDE;
5260 } else if ((factor == MPT_ULTRA) && width) {
5261 width = MPT_NARROW;
5262 } else if (factor < MPT_FAST) {
5263 factor = MPT_FAST;
5264 width = MPT_WIDE;
5265 } else if ((factor == MPT_FAST) && width) {
5266 factor = MPT_FAST;
5267 width = MPT_NARROW;
5268 } else if (factor < MPT_SCSI) {
5269 factor = MPT_SCSI;
5270 width = MPT_WIDE;
5271 } else if ((factor == MPT_SCSI) && width) {
5272 factor = MPT_SCSI;
5273 width = MPT_NARROW;
5274 } else {
5275 factor = MPT_ASYNC;
5276 offset = 0;
5277 }
5278
5279 } else if (offset) {
5280 width = MPT_NARROW;
5281 if (factor < MPT_ULTRA)
5282 factor = MPT_ULTRA;
5283 else if (factor < MPT_FAST)
5284 factor = MPT_FAST;
5285 else if (factor < MPT_SCSI)
5286 factor = MPT_SCSI;
5287 else {
5288 factor = MPT_ASYNC;
5289 offset = 0;
5290 }
5291
5292 } else {
5293 width = MPT_NARROW;
5294 factor = MPT_ASYNC;
5295 }
5296 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
5297 dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
5298
5299 dv->now.width = width;
5300 dv->now.offset = offset;
5301 dv->now.factor = factor;
5302 dv->now.flags = dv->max.flags;
5303
5304 pPage1 = (SCSIDevicePage1_t *)pPage;
5305 if (pPage1) {
5306 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
5307 &configuration, dv->now.flags);
637fa99b 5308 dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
1da177e4
LT
5309 id, width, offset, factor, dv->now.flags, val, configuration));
5310
637fa99b 5311 pPage1->RequestedParameters = cpu_to_le32(val);
1da177e4 5312 pPage1->Reserved = 0;
637fa99b 5313 pPage1->Configuration = cpu_to_le32(configuration);
1da177e4
LT
5314 }
5315
5316 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5317 id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
5318 break;
5319
5320 case MPT_SAVE:
5321 ddvprintk((MYIOC_s_NOTE_FMT
5322 "Saving to Target structure: ", hd->ioc->name));
5323 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5324 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5325
5326 /* Save these values to target structures
5327 * or overwrite nvram (phys disks only).
5328 */
5329
c7c82987
MED
5330 if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) {
5331 vtarget->maxWidth = dv->now.width;
5332 vtarget->maxOffset = dv->now.offset;
5333 vtarget->minSyncFactor = dv->now.factor;
5334 vtarget->negoFlags = dv->now.flags;
1da177e4
LT
5335 } else {
5336 /* Preserv all flags, use
5337 * read-modify-write algorithm
5338 */
5339 if (hd->ioc->spi_data.nvram) {
5340 data = hd->ioc->spi_data.nvram[id];
5341
5342 if (dv->now.width)
5343 data &= ~MPT_NVRAM_WIDE_DISABLE;
5344 else
5345 data |= MPT_NVRAM_WIDE_DISABLE;
5346
5347 if (!dv->now.offset)
5348 factor = MPT_ASYNC;
5349
5350 data &= ~MPT_NVRAM_SYNC_MASK;
5351 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
5352
5353 hd->ioc->spi_data.nvram[id] = data;
5354 }
5355 }
5356 break;
5357 }
5358}
5359
5360/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5361/* mptscsih_fillbuf - fill a buffer with a special data pattern
5362 * cleanup. For bus scan only.
5363 *
5364 * @buffer: Pointer to data buffer to be filled.
5365 * @size: Number of bytes to fill
5366 * @index: Pattern index
5367 * @width: bus width, 0 (8 bits) or 1 (16 bits)
5368 */
5369static void
5370mptscsih_fillbuf(char *buffer, int size, int index, int width)
5371{
5372 char *ptr = buffer;
5373 int ii;
5374 char byte;
5375 short val;
5376
5377 switch (index) {
5378 case 0:
5379
5380 if (width) {
5381 /* Pattern: 0000 FFFF 0000 FFFF
5382 */
5383 for (ii=0; ii < size; ii++, ptr++) {
5384 if (ii & 0x02)
5385 *ptr = 0xFF;
5386 else
5387 *ptr = 0x00;
5388 }
5389 } else {
5390 /* Pattern: 00 FF 00 FF
5391 */
5392 for (ii=0; ii < size; ii++, ptr++) {
5393 if (ii & 0x01)
5394 *ptr = 0xFF;
5395 else
5396 *ptr = 0x00;
5397 }
5398 }
5399 break;
5400
5401 case 1:
5402 if (width) {
5403 /* Pattern: 5555 AAAA 5555 AAAA 5555
5404 */
5405 for (ii=0; ii < size; ii++, ptr++) {
5406 if (ii & 0x02)
5407 *ptr = 0xAA;
5408 else
5409 *ptr = 0x55;
5410 }
5411 } else {
5412 /* Pattern: 55 AA 55 AA 55
5413 */
5414 for (ii=0; ii < size; ii++, ptr++) {
5415 if (ii & 0x01)
5416 *ptr = 0xAA;
5417 else
5418 *ptr = 0x55;
5419 }
5420 }
5421 break;
5422
5423 case 2:
5424 /* Pattern: 00 01 02 03 04 05
5425 * ... FE FF 00 01..
5426 */
5427 for (ii=0; ii < size; ii++, ptr++)
5428 *ptr = (char) ii;
5429 break;
5430
5431 case 3:
5432 if (width) {
5433 /* Wide Pattern: FFFE 0001 FFFD 0002
5434 * ... 4000 DFFF 8000 EFFF
5435 */
5436 byte = 0;
5437 for (ii=0; ii < size/2; ii++) {
5438 /* Create the base pattern
5439 */
5440 val = (1 << byte);
5441 /* every 64 (0x40) bytes flip the pattern
5442 * since we fill 2 bytes / iteration,
5443 * test for ii = 0x20
5444 */
5445 if (ii & 0x20)
5446 val = ~(val);
5447
5448 if (ii & 0x01) {
5449 *ptr = (char)( (val & 0xFF00) >> 8);
5450 ptr++;
5451 *ptr = (char)(val & 0xFF);
5452 byte++;
5453 byte &= 0x0F;
5454 } else {
5455 val = ~val;
5456 *ptr = (char)( (val & 0xFF00) >> 8);
5457 ptr++;
5458 *ptr = (char)(val & 0xFF);
5459 }
5460
5461 ptr++;
5462 }
5463 } else {
5464 /* Narrow Pattern: FE 01 FD 02 FB 04
5465 * .. 7F 80 01 FE 02 FD ... 80 7F
5466 */
5467 byte = 0;
5468 for (ii=0; ii < size; ii++, ptr++) {
5469 /* Base pattern - first 32 bytes
5470 */
5471 if (ii & 0x01) {
5472 *ptr = (1 << byte);
5473 byte++;
5474 byte &= 0x07;
5475 } else {
5476 *ptr = (char) (~(1 << byte));
5477 }
5478
5479 /* Flip the pattern every 32 bytes
5480 */
5481 if (ii & 0x20)
5482 *ptr = ~(*ptr);
5483 }
5484 }
5485 break;
5486 }
5487}
f2ea8671
MED
5488
5489/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5490/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
5491 * Else set the NEED_DV flag after Read Capacity Issued (disks)
5492 * or Mode Sense (cdroms).
5493 *
5494 * Tapes, initTarget will set this flag on completion of Inquiry command.
5495 * Called only if DV_NOT_DONE flag is set
5496 */
5497static void
c7c82987 5498mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
f2ea8671
MED
5499{
5500 MPT_ADAPTER *ioc = hd->ioc;
5501 u8 cmd;
5502 SpiCfgData *pSpi;
5503
5504 ddvtprintk((MYIOC_s_NOTE_FMT
5505 " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
c7c82987 5506 hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0]));
f2ea8671 5507
c7c82987 5508 if ((sc->device->lun != 0) || (hd->negoNvram != 0))
f2ea8671
MED
5509 return;
5510
c7c82987 5511 cmd = sc->cmnd[0];
f2ea8671
MED
5512
5513 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
5514 pSpi = &ioc->spi_data;
c7c82987 5515 if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) {
f2ea8671
MED
5516 /* Set NEED_DV for all hidden disks
5517 */
5518 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
5519 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
5520
5521 while (numPDisk) {
5522 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
5523 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
5524 pPDisk++;
5525 numPDisk--;
5526 }
5527 }
c7c82987
MED
5528 pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV;
5529 ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id));
f2ea8671
MED
5530 }
5531}
5532
5533/* mptscsih_raid_set_dv_flags()
5534 *
5535 * New or replaced disk. Set DV flag and schedule DV.
5536 */
5537static void
5538mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
5539{
5540 MPT_ADAPTER *ioc = hd->ioc;
5541 SpiCfgData *pSpi = &ioc->spi_data;
5542 Ioc3PhysDisk_t *pPDisk;
5543 int numPDisk;
5544
5545 if (hd->negoNvram != 0)
5546 return;
5547
5548 ddvtprintk(("DV requested for phys disk id %d\n", id));
5549 if (ioc->raid_data.pIocPg3) {
5550 pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
5551 numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
5552 while (numPDisk) {
5553 if (id == pPDisk->PhysDiskNum) {
5554 pSpi->dvStatus[pPDisk->PhysDiskID] =
5555 (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
5556 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
5557 ddvtprintk(("NEED_DV set for phys disk id %d\n",
5558 pPDisk->PhysDiskID));
5559 break;
5560 }
5561 pPDisk++;
5562 numPDisk--;
5563 }
5564
5565 if (numPDisk == 0) {
5566 /* The physical disk that needs DV was not found
5567 * in the stored IOC Page 3. The driver must reload
5568 * this page. DV routine will set the NEED_DV flag for
5569 * all phys disks that have DV_NOT_DONE set.
5570 */
5571 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
5572 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
5573 }
5574 }
5575}
1da177e4
LT
5576#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5577
0d0c7974
MED
5578EXPORT_SYMBOL(mptscsih_remove);
5579EXPORT_SYMBOL(mptscsih_shutdown);
5580#ifdef CONFIG_PM
5581EXPORT_SYMBOL(mptscsih_suspend);
5582EXPORT_SYMBOL(mptscsih_resume);
5583#endif
5584EXPORT_SYMBOL(mptscsih_proc_info);
5585EXPORT_SYMBOL(mptscsih_info);
5586EXPORT_SYMBOL(mptscsih_qcmd);
c7c82987 5587EXPORT_SYMBOL(mptscsih_target_alloc);
0d0c7974 5588EXPORT_SYMBOL(mptscsih_slave_alloc);
c7c82987 5589EXPORT_SYMBOL(mptscsih_target_destroy);
0d0c7974
MED
5590EXPORT_SYMBOL(mptscsih_slave_destroy);
5591EXPORT_SYMBOL(mptscsih_slave_configure);
5592EXPORT_SYMBOL(mptscsih_abort);
5593EXPORT_SYMBOL(mptscsih_dev_reset);
5594EXPORT_SYMBOL(mptscsih_bus_reset);
5595EXPORT_SYMBOL(mptscsih_host_reset);
5596EXPORT_SYMBOL(mptscsih_bios_param);
5597EXPORT_SYMBOL(mptscsih_io_done);
5598EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
5599EXPORT_SYMBOL(mptscsih_scandv_complete);
5600EXPORT_SYMBOL(mptscsih_event_process);
5601EXPORT_SYMBOL(mptscsih_ioc_reset);
6e3815ba 5602EXPORT_SYMBOL(mptscsih_change_queue_depth);
0d0c7974 5603EXPORT_SYMBOL(mptscsih_timer_expired);
1da177e4 5604
0d0c7974 5605/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/