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