OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [message/] [fusion/] [mptscsih.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.