]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/message/fusion/mptscsih.c
SCSI: convert struct class_device to struct device
[mirror_ubuntu-eoan-kernel.git] / drivers / message / fusion / mptscsih.c
CommitLineData
1da177e4
LT
1/*
2 * linux/drivers/message/fusion/mptscsih.c
f36789e2
PS
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
1da177e4 5 *
f36789e2 6 * Copyright (c) 1999-2007 LSI Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
1da177e4 8 *
1da177e4
LT
9 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
1da177e4
LT
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/kdev_t.h>
52#include <linux/blkdev.h>
53#include <linux/delay.h> /* for mdelay */
54#include <linux/interrupt.h> /* needed for in_interrupt() proto */
55#include <linux/reboot.h> /* notifier code */
1da177e4
LT
56#include <linux/workqueue.h>
57
58#include <scsi/scsi.h>
59#include <scsi/scsi_cmnd.h>
60#include <scsi/scsi_device.h>
61#include <scsi/scsi_host.h>
62#include <scsi/scsi_tcq.h>
e0fc15be 63#include <scsi/scsi_dbg.h>
1da177e4
LT
64
65#include "mptbase.h"
66#include "mptscsih.h"
bf451522 67#include "lsi/mpi_log_sas.h"
1da177e4
LT
68
69/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70#define my_NAME "Fusion MPT SCSI Host driver"
71#define my_VERSION MPT_LINUX_VERSION_COMMON
72#define MYNAM "mptscsih"
73
74MODULE_AUTHOR(MODULEAUTHOR);
75MODULE_DESCRIPTION(my_NAME);
76MODULE_LICENSE("GPL");
9f4203b3 77MODULE_VERSION(my_VERSION);
1da177e4 78
1da177e4 79/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
80/*
81 * Other private/forward protos...
82 */
e8206381
EM
83static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
84static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
85static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
86static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
0d0c7974 87int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 88static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
0d0c7974 89int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4
LT
90
91static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
92 SCSIIORequest_t *pReq, int req_idx);
93static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
0d0c7974 94static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
1da177e4
LT
95static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
96static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
1da177e4 97
793955f5 98static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
1da177e4 99
0d0c7974
MED
100int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
101int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
1da177e4 102
0d0c7974 103int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 104static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
c7c82987 105static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
1da177e4 106
0d0c7974 107void mptscsih_remove(struct pci_dev *);
d18c3db5 108void mptscsih_shutdown(struct pci_dev *);
1da177e4 109#ifdef CONFIG_PM
0d0c7974
MED
110int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
111int mptscsih_resume(struct pci_dev *pdev);
1da177e4
LT
112#endif
113
b80ca4f7 114#define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE
1da177e4 115
1da177e4
LT
116/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
117/**
118 * mptscsih_add_sge - Place a simple SGE at address pAddr.
119 * @pAddr: virtual address for SGE
120 * @flagslength: SGE flags and data transfer length
121 * @dma_addr: Physical address
122 *
123 * This routine places a MPT request frame back on the MPT adapter's
124 * FreeQ.
125 */
126static inline void
127mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
128{
129 if (sizeof(dma_addr_t) == sizeof(u64)) {
130 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
131 u32 tmp = dma_addr & 0xFFFFFFFF;
132
133 pSge->FlagsLength = cpu_to_le32(flagslength);
134 pSge->Address.Low = cpu_to_le32(tmp);
135 tmp = (u32) ((u64)dma_addr >> 32);
136 pSge->Address.High = cpu_to_le32(tmp);
137
138 } else {
139 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
140 pSge->FlagsLength = cpu_to_le32(flagslength);
141 pSge->Address = cpu_to_le32(dma_addr);
142 }
143} /* mptscsih_add_sge() */
144
145/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
146/**
147 * mptscsih_add_chain - Place a chain SGE at address pAddr.
148 * @pAddr: virtual address for SGE
149 * @next: nextChainOffset value (u32's)
150 * @length: length of next SGL segment
151 * @dma_addr: Physical address
152 *
153 * This routine places a MPT request frame back on the MPT adapter's
154 * FreeQ.
155 */
156static inline void
157mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
158{
159 if (sizeof(dma_addr_t) == sizeof(u64)) {
160 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
161 u32 tmp = dma_addr & 0xFFFFFFFF;
162
163 pChain->Length = cpu_to_le16(length);
164 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
165
166 pChain->NextChainOffset = next;
167
168 pChain->Address.Low = cpu_to_le32(tmp);
169 tmp = (u32) ((u64)dma_addr >> 32);
170 pChain->Address.High = cpu_to_le32(tmp);
171 } else {
172 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
173 pChain->Length = cpu_to_le16(length);
174 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
175 pChain->NextChainOffset = next;
176 pChain->Address = cpu_to_le32(dma_addr);
177 }
178} /* mptscsih_add_chain() */
179
180/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
181/*
182 * mptscsih_getFreeChainBuffer - Function to get a free chain
183 * from the MPT_SCSI_HOST FreeChainQ.
184 * @ioc: Pointer to MPT_ADAPTER structure
185 * @req_idx: Index of the SCSI IO request frame. (output)
186 *
187 * return SUCCESS or FAILED
188 */
189static inline int
190mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
191{
192 MPT_FRAME_HDR *chainBuf;
193 unsigned long flags;
194 int rc;
195 int chain_idx;
196
6757d6b4 197 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
29dd3609 198 ioc->name));
1da177e4
LT
199 spin_lock_irqsave(&ioc->FreeQlock, flags);
200 if (!list_empty(&ioc->FreeChainQ)) {
201 int offset;
202
203 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
204 u.frame.linkage.list);
205 list_del(&chainBuf->u.frame.linkage.list);
206 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
207 chain_idx = offset / ioc->req_sz;
208 rc = SUCCESS;
29dd3609
EM
209 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
210 "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
211 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
1da177e4
LT
212 } else {
213 rc = FAILED;
214 chain_idx = MPT_HOST_NO_CHAIN;
29dd3609
EM
215 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
216 ioc->name));
1da177e4
LT
217 }
218 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
219
220 *retIndex = chain_idx;
221 return rc;
222} /* mptscsih_getFreeChainBuffer() */
223
224/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
225/*
226 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
227 * SCSIIORequest_t Message Frame.
228 * @ioc: Pointer to MPT_ADAPTER structure
229 * @SCpnt: Pointer to scsi_cmnd structure
230 * @pReq: Pointer to SCSIIORequest_t structure
231 *
232 * Returns ...
233 */
234static int
235mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
236 SCSIIORequest_t *pReq, int req_idx)
237{
238 char *psge;
239 char *chainSge;
240 struct scatterlist *sg;
241 int frm_sz;
242 int sges_left, sg_done;
243 int chain_idx = MPT_HOST_NO_CHAIN;
244 int sgeOffset;
245 int numSgeSlots, numSgeThisFrame;
246 u32 sgflags, sgdir, thisxfer = 0;
247 int chain_dma_off = 0;
248 int newIndex;
249 int ii;
250 dma_addr_t v2;
251 u32 RequestNB;
252
253 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
254 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
255 sgdir = MPT_TRANSFER_HOST_TO_IOC;
256 } else {
257 sgdir = MPT_TRANSFER_IOC_TO_HOST;
258 }
259
260 psge = (char *) &pReq->SGL;
261 frm_sz = ioc->req_sz;
262
263 /* Map the data portion, if any.
264 * sges_left = 0 if no data transfer.
265 */
1928d73f
FT
266 sges_left = scsi_dma_map(SCpnt);
267 if (sges_left < 0)
268 return FAILED;
1da177e4
LT
269
270 /* Handle the SG case.
271 */
1928d73f 272 sg = scsi_sglist(SCpnt);
1da177e4
LT
273 sg_done = 0;
274 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
275 chainSge = NULL;
276
277 /* Prior to entering this loop - the following must be set
278 * current MF: sgeOffset (bytes)
279 * chainSge (Null if original MF is not a chain buffer)
280 * sg_done (num SGE done for this MF)
281 */
282
283nextSGEset:
284 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
285 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
286
287 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
288
289 /* Get first (num - 1) SG elements
290 * Skip any SG entries with a length of 0
291 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
292 */
293 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
294 thisxfer = sg_dma_len(sg);
295 if (thisxfer == 0) {
ed17b031 296 sg = sg_next(sg); /* Get next SG element from the OS */
1da177e4
LT
297 sg_done++;
298 continue;
299 }
300
301 v2 = sg_dma_address(sg);
302 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
303
ed17b031 304 sg = sg_next(sg); /* Get next SG element from the OS */
1da177e4
LT
305 psge += (sizeof(u32) + sizeof(dma_addr_t));
306 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
307 sg_done++;
308 }
309
310 if (numSgeThisFrame == sges_left) {
311 /* Add last element, end of buffer and end of list flags.
312 */
313 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
314 MPT_SGE_FLAGS_END_OF_BUFFER |
315 MPT_SGE_FLAGS_END_OF_LIST;
316
317 /* Add last SGE and set termination flags.
318 * Note: Last SGE may have a length of 0 - which should be ok.
319 */
320 thisxfer = sg_dma_len(sg);
321
322 v2 = sg_dma_address(sg);
323 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
324 /*
ed17b031 325 sg = sg_next(sg);
1da177e4
LT
326 psge += (sizeof(u32) + sizeof(dma_addr_t));
327 */
328 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
329 sg_done++;
330
331 if (chainSge) {
332 /* The current buffer is a chain buffer,
333 * but there is not another one.
334 * Update the chain element
335 * Offset and Length fields.
336 */
337 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
338 } else {
339 /* The current buffer is the original MF
340 * and there is no Chain buffer.
341 */
342 pReq->ChainOffset = 0;
343 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
6757d6b4 344 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1da177e4
LT
345 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
346 ioc->RequestNB[req_idx] = RequestNB;
347 }
348 } else {
349 /* At least one chain buffer is needed.
350 * Complete the first MF
351 * - last SGE element, set the LastElement bit
352 * - set ChainOffset (words) for orig MF
353 * (OR finish previous MF chain buffer)
354 * - update MFStructPtr ChainIndex
355 * - Populate chain element
356 * Also
357 * Loop until done.
358 */
359
6757d6b4 360 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SG: Chain Required! sg done %d\n",
1da177e4
LT
361 ioc->name, sg_done));
362
363 /* Set LAST_ELEMENT flag for last non-chain element
364 * in the buffer. Since psge points at the NEXT
365 * SGE element, go back one SGE element, update the flags
366 * and reset the pointer. (Note: sgflags & thisxfer are already
367 * set properly).
368 */
369 if (sg_done) {
370 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
371 sgflags = le32_to_cpu(*ptmp);
372 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
373 *ptmp = cpu_to_le32(sgflags);
374 }
375
376 if (chainSge) {
377 /* The current buffer is a chain buffer.
378 * chainSge points to the previous Chain Element.
379 * Update its chain element Offset and Length (must
380 * include chain element size) fields.
381 * Old chain element is now complete.
382 */
383 u8 nextChain = (u8) (sgeOffset >> 2);
384 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
385 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
386 } else {
387 /* The original MF buffer requires a chain buffer -
388 * set the offset.
389 * Last element in this MF is a chain element.
390 */
391 pReq->ChainOffset = (u8) (sgeOffset >> 2);
392 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
6757d6b4 393 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
1da177e4
LT
394 ioc->RequestNB[req_idx] = RequestNB;
395 }
396
397 sges_left -= sg_done;
398
399
400 /* NOTE: psge points to the beginning of the chain element
401 * in current buffer. Get a chain buffer.
402 */
c6678e0c 403 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
6757d6b4 404 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6678e0c
CH
405 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
406 ioc->name, pReq->CDB[0], SCpnt));
1da177e4 407 return FAILED;
c6678e0c 408 }
1da177e4
LT
409
410 /* Update the tracking arrays.
411 * If chainSge == NULL, update ReqToChain, else ChainToChain
412 */
413 if (chainSge) {
414 ioc->ChainToChain[chain_idx] = newIndex;
415 } else {
416 ioc->ReqToChain[req_idx] = newIndex;
417 }
418 chain_idx = newIndex;
419 chain_dma_off = ioc->req_sz * chain_idx;
420
421 /* Populate the chainSGE for the current buffer.
422 * - Set chain buffer pointer to psge and fill
423 * out the Address and Flags fields.
424 */
425 chainSge = (char *) psge;
29dd3609
EM
426 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Current buff @ %p (index 0x%x)",
427 ioc->name, psge, req_idx));
1da177e4
LT
428
429 /* Start the SGE for the next buffer
430 */
431 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
432 sgeOffset = 0;
433 sg_done = 0;
434
29dd3609
EM
435 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Chain buff @ %p (index 0x%x)\n",
436 ioc->name, psge, chain_idx));
1da177e4
LT
437
438 /* Start the SGE for the next buffer
439 */
440
441 goto nextSGEset;
442 }
443
444 return SUCCESS;
445} /* mptscsih_AddSGE() */
446
786899b0
EM
447static void
448mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
449 U32 SlotStatus)
450{
451 MPT_FRAME_HDR *mf;
452 SEPRequest_t *SEPMsg;
453
cc78d30a
EM
454 if (ioc->bus_type != SAS)
455 return;
456
457 /* Not supported for hidden raid components
458 */
459 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
786899b0
EM
460 return;
461
462 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
6757d6b4 463 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
786899b0
EM
464 ioc->name,__FUNCTION__));
465 return;
466 }
467
468 SEPMsg = (SEPRequest_t *)mf;
469 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
793955f5
EM
470 SEPMsg->Bus = vtarget->channel;
471 SEPMsg->TargetID = vtarget->id;
786899b0
EM
472 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
473 SEPMsg->SlotStatus = SlotStatus;
6757d6b4 474 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
793955f5
EM
475 "Sending SEP cmd=%x channel=%d id=%d\n",
476 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
786899b0
EM
477 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
478}
479
6757d6b4 480#ifdef CONFIG_FUSION_LOGGING
c6c727a1 481/**
6757d6b4 482 * mptscsih_info_scsiio - debug print info on reply frame
c6c727a1 483 * @ioc: Pointer to MPT_ADAPTER structure
c6c727a1 484 * @sc: original scsi cmnd pointer
6757d6b4
PS
485 * @pScsiReply: Pointer to MPT reply frame
486 *
487 * MPT_DEBUG_REPLY needs to be enabled to obtain this info
c6c727a1
EM
488 *
489 * Refer to lsi/mpi.h.
490 **/
491static void
6757d6b4 492mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply)
c6c727a1 493{
6757d6b4
PS
494 char *desc = NULL;
495 char *desc1 = NULL;
496 u16 ioc_status;
497 u8 skey, asc, ascq;
498
499 ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
c6c727a1
EM
500
501 switch (ioc_status) {
502
6757d6b4
PS
503 case MPI_IOCSTATUS_SUCCESS:
504 desc = "success";
c6c727a1 505 break;
6757d6b4
PS
506 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
507 desc = "invalid bus";
c6c727a1 508 break;
6757d6b4
PS
509 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
510 desc = "invalid target_id";
c6c727a1 511 break;
6757d6b4
PS
512 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
513 desc = "device not there";
c6c727a1 514 break;
6757d6b4
PS
515 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
516 desc = "data overrun";
c6c727a1 517 break;
6757d6b4
PS
518 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
519 desc = "data underrun";
c6c727a1 520 break;
6757d6b4
PS
521 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
522 desc = "I/O data error";
c6c727a1 523 break;
6757d6b4
PS
524 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
525 desc = "protocol error";
c6c727a1 526 break;
6757d6b4
PS
527 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
528 desc = "task terminated";
c6c727a1 529 break;
6757d6b4
PS
530 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
531 desc = "residual mismatch";
532 break;
533 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
534 desc = "task management failed";
535 break;
536 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
537 desc = "IOC terminated";
538 break;
539 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
540 desc = "ext terminated";
c6c727a1 541 break;
6757d6b4
PS
542 default:
543 desc = "";
544 break;
545 }
546
547 switch (pScsiReply->SCSIStatus)
548 {
c6c727a1 549
6757d6b4
PS
550 case MPI_SCSI_STATUS_SUCCESS:
551 desc1 = "success";
552 break;
553 case MPI_SCSI_STATUS_CHECK_CONDITION:
554 desc1 = "check condition";
555 break;
556 case MPI_SCSI_STATUS_CONDITION_MET:
557 desc1 = "condition met";
558 break;
559 case MPI_SCSI_STATUS_BUSY:
560 desc1 = "busy";
561 break;
562 case MPI_SCSI_STATUS_INTERMEDIATE:
563 desc1 = "intermediate";
564 break;
565 case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET:
566 desc1 = "intermediate condmet";
567 break;
568 case MPI_SCSI_STATUS_RESERVATION_CONFLICT:
569 desc1 = "reservation conflict";
570 break;
571 case MPI_SCSI_STATUS_COMMAND_TERMINATED:
572 desc1 = "command terminated";
573 break;
574 case MPI_SCSI_STATUS_TASK_SET_FULL:
575 desc1 = "task set full";
576 break;
577 case MPI_SCSI_STATUS_ACA_ACTIVE:
578 desc1 = "aca active";
579 break;
580 case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT:
581 desc1 = "fcpext device logged out";
582 break;
583 case MPI_SCSI_STATUS_FCPEXT_NO_LINK:
584 desc1 = "fcpext no link";
585 break;
586 case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED:
587 desc1 = "fcpext unassigned";
588 break;
589 default:
590 desc1 = "";
c6c727a1
EM
591 break;
592 }
593
6757d6b4 594 scsi_print_command(sc);
29dd3609
EM
595 printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n",
596 ioc->name, pScsiReply->Bus, pScsiReply->TargetID);
597 printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
598 "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
599 scsi_get_resid(sc));
600 printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, "
601 "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag),
6757d6b4 602 le32_to_cpu(pScsiReply->TransferCount), sc->result);
29dd3609 603 printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), "
6757d6b4 604 "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",
29dd3609 605 ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus,
6757d6b4 606 pScsiReply->SCSIState);
c6c727a1 607
6757d6b4
PS
608 if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
609 skey = sc->sense_buffer[2] & 0x0F;
610 asc = sc->sense_buffer[12];
611 ascq = sc->sense_buffer[13];
612
29dd3609
EM
613 printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: "
614 "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq);
6757d6b4
PS
615 }
616
617 /*
618 * Look for + dump FCP ResponseInfo[]!
619 */
620 if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
621 pScsiReply->ResponseInfo)
29dd3609
EM
622 printk(MYIOC_s_DEBUG_FMT "response_info = %08xh\n",
623 ioc->name, le32_to_cpu(pScsiReply->ResponseInfo));
c6c727a1
EM
624}
625#endif
626
1da177e4
LT
627/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
628/*
629 * mptscsih_io_done - Main SCSI IO callback routine registered to
630 * Fusion MPT (base) driver
631 * @ioc: Pointer to MPT_ADAPTER structure
632 * @mf: Pointer to original MPT request frame
633 * @r: Pointer to MPT reply frame (NULL if TurboReply)
634 *
635 * This routine is called from mpt.c::mpt_interrupt() at the completion
636 * of any SCSI IO request.
637 * This routine is registered with the Fusion MPT (base) driver at driver
638 * load/init time via the mpt_register() API call.
639 *
640 * Returns 1 indicating alloc'd request frame ptr should be freed.
641 */
0d0c7974 642int
1da177e4
LT
643mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
644{
645 struct scsi_cmnd *sc;
646 MPT_SCSI_HOST *hd;
647 SCSIIORequest_t *pScsiReq;
648 SCSIIOReply_t *pScsiReply;
2254c86d 649 u16 req_idx, req_idx_MR;
a69de507 650 VirtDevice *vdevice;
786899b0 651 VirtTarget *vtarget;
1da177e4 652
e7eae9f6 653 hd = shost_priv(ioc->sh);
1da177e4 654 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2254c86d
ME
655 req_idx_MR = (mr != NULL) ?
656 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
657 if ((req_idx != req_idx_MR) ||
658 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
659 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
660 ioc->name);
661 printk (MYIOC_s_ERR_FMT
662 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
663 ioc->name, req_idx, req_idx_MR, mf, mr,
e8206381 664 mptscsih_get_scsi_lookup(ioc, req_idx_MR));
2254c86d
ME
665 return 0;
666 }
667
e8206381 668 sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
1da177e4
LT
669 if (sc == NULL) {
670 MPIHeader_t *hdr = (MPIHeader_t *)mf;
671
672 /* Remark: writeSDP1 will use the ScsiDoneCtx
673 * If a SCSI I/O cmd, device disabled by OS and
674 * completion done. Cannot touch sc struct. Just free mem.
675 */
676 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
677 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
678 ioc->name);
679
680 mptscsih_freeChainBuffers(ioc, req_idx);
681 return 1;
682 }
683
3dc0b03f
EM
684 if ((unsigned char *)mf != sc->host_scribble) {
685 mptscsih_freeChainBuffers(ioc, req_idx);
686 return 1;
687 }
688
689 sc->host_scribble = NULL;
1da177e4
LT
690 sc->result = DID_OK << 16; /* Set default reply as OK */
691 pScsiReq = (SCSIIORequest_t *) mf;
692 pScsiReply = (SCSIIOReply_t *) mr;
693
c6678e0c 694 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
6757d6b4 695 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6678e0c
CH
696 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
697 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
698 }else{
6757d6b4 699 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6678e0c
CH
700 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
701 ioc->name, mf, mr, sc, req_idx));
702 }
703
1da177e4
LT
704 if (pScsiReply == NULL) {
705 /* special context reply handling */
706 ;
707 } else {
708 u32 xfer_cnt;
709 u16 status;
710 u8 scsi_state, scsi_status;
c6c727a1 711 u32 log_info;
1da177e4
LT
712
713 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
714 scsi_state = pScsiReply->SCSIState;
715 scsi_status = pScsiReply->SCSIStatus;
716 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
1928d73f 717 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
c6c727a1 718 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
1da177e4 719
466544d8
MED
720 /*
721 * if we get a data underrun indication, yet no data was
722 * transferred and the SCSI status indicates that the
723 * command was never started, change the data underrun
724 * to success
725 */
726 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
727 (scsi_status == MPI_SCSI_STATUS_BUSY ||
728 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
729 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
730 status = MPI_IOCSTATUS_SUCCESS;
731 }
732
1da177e4 733 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
0d0c7974
MED
734 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
735
1da177e4
LT
736 /*
737 * Look for + dump FCP ResponseInfo[]!
738 */
466544d8
MED
739 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
740 pScsiReply->ResponseInfo) {
29dd3609
EM
741 printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
742 "FCP_ResponseInfo=%08xh\n", ioc->name,
c6c727a1
EM
743 sc->device->host->host_no, sc->device->channel,
744 sc->device->id, sc->device->lun,
1da177e4
LT
745 le32_to_cpu(pScsiReply->ResponseInfo));
746 }
747
748 switch(status) {
749 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
750 /* CHECKME!
751 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
752 * But not: DID_BUS_BUSY lest one risk
753 * killing interrupt handler:-(
754 */
755 sc->result = SAM_STAT_BUSY;
756 break;
757
758 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
759 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
760 sc->result = DID_BAD_TARGET << 16;
761 break;
762
763 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
764 /* Spoof to SCSI Selection Timeout! */
65207fed
ME
765 if (ioc->bus_type != FC)
766 sc->result = DID_NO_CONNECT << 16;
767 /* else fibre, just stall until rescan event */
768 else
769 sc->result = DID_REQUEUE << 16;
1da177e4
LT
770
771 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
772 hd->sel_timeout[pScsiReq->TargetID]++;
786899b0 773
a69de507
EM
774 vdevice = sc->device->hostdata;
775 if (!vdevice)
786899b0 776 break;
a69de507 777 vtarget = vdevice->vtarget;
786899b0
EM
778 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
779 mptscsih_issue_sep_command(ioc, vtarget,
780 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
781 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
782 }
1da177e4
LT
783 break;
784
1da177e4 785 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
bf451522
EM
786 if ( ioc->bus_type == SAS ) {
787 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
788 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
c6c727a1
EM
789 if ((log_info & SAS_LOGINFO_MASK)
790 == SAS_LOGINFO_NEXUS_LOSS) {
bf451522
EM
791 sc->result = (DID_BUS_BUSY << 16);
792 break;
793 }
794 }
86dd4242
EM
795 } else if (ioc->bus_type == FC) {
796 /*
797 * The FC IOC may kill a request for variety of
798 * reasons, some of which may be recovered by a
799 * retry, some which are unlikely to be
800 * recovered. Return DID_ERROR instead of
801 * DID_RESET to permit retry of the command,
802 * just not an infinite number of them
803 */
804 sc->result = DID_ERROR << 16;
805 break;
bf451522
EM
806 }
807
808 /*
809 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
810 */
811
812 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
1da177e4
LT
813 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
814 /* Linux handles an unsolicited DID_RESET better
815 * than an unsolicited DID_ABORT.
816 */
817 sc->result = DID_RESET << 16;
818
1da177e4
LT
819 break;
820
821 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
1928d73f 822 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
466544d8
MED
823 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
824 sc->result=DID_SOFT_ERROR << 16;
825 else /* Sufficient data transfer occurred */
1da177e4 826 sc->result = (DID_OK << 16) | scsi_status;
29dd3609 827 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6c727a1 828 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
29dd3609 829 ioc->name, sc->result, sc->device->channel, sc->device->id));
1da177e4 830 break;
0d0c7974 831
1da177e4
LT
832 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
833 /*
834 * Do upfront check for valid SenseData and give it
835 * precedence!
836 */
837 sc->result = (DID_OK << 16) | scsi_status;
838 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
839 /* Have already saved the status and sense data
840 */
841 ;
842 } else {
843 if (xfer_cnt < sc->underflow) {
466544d8
MED
844 if (scsi_status == SAM_STAT_BUSY)
845 sc->result = SAM_STAT_BUSY;
846 else
847 sc->result = DID_SOFT_ERROR << 16;
1da177e4
LT
848 }
849 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
850 /* What to do?
851 */
852 sc->result = DID_SOFT_ERROR << 16;
853 }
854 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
855 /* Not real sure here either... */
856 sc->result = DID_RESET << 16;
857 }
858 }
859
6757d6b4 860
29dd3609
EM
861 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
862 " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
863 ioc->name, sc->underflow));
864 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
865 " ActBytesXferd=%02xh\n", ioc->name, xfer_cnt));
6757d6b4 866
1da177e4
LT
867 /* Report Queue Full
868 */
869 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
870 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
0d0c7974 871
1da177e4
LT
872 break;
873
7e55147f 874 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
1928d73f 875 scsi_set_resid(sc, 0);
1da177e4
LT
876 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
877 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
ad8c31bb 878 sc->result = (DID_OK << 16) | scsi_status;
1da177e4
LT
879 if (scsi_state == 0) {
880 ;
881 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
882 /*
883 * If running against circa 200003dd 909 MPT f/w,
884 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
885 * (QUEUE_FULL) returned from device! --> get 0x0000?128
886 * and with SenseBytes set to 0.
887 */
888 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
889 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
890
891 }
892 else if (scsi_state &
893 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
894 ) {
895 /*
896 * What to do?
897 */
898 sc->result = DID_SOFT_ERROR << 16;
899 }
900 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
901 /* Not real sure here either... */
902 sc->result = DID_RESET << 16;
903 }
904 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
905 /* Device Inq. data indicates that it supports
906 * QTags, but rejects QTag messages.
907 * This command completed OK.
908 *
909 * Not real sure here either so do nothing... */
910 }
911
912 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
913 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
914
915 /* Add handling of:
916 * Reservation Conflict, Busy,
917 * Command Terminated, CHECK
918 */
919 break;
920
921 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
922 sc->result = DID_SOFT_ERROR << 16;
923 break;
924
925 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
926 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
927 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
928 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
929 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
930 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
931 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
1da177e4
LT
932 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
933 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
934 default:
935 /*
936 * What to do?
937 */
938 sc->result = DID_SOFT_ERROR << 16;
939 break;
940
941 } /* switch(status) */
942
6757d6b4
PS
943#ifdef CONFIG_FUSION_LOGGING
944 if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY))
945 mptscsih_info_scsiio(ioc, sc, pScsiReply);
c6c727a1
EM
946#endif
947
1da177e4
LT
948 } /* end of address reply case */
949
950 /* Unmap the DMA buffers, if any. */
1928d73f 951 scsi_dma_unmap(sc);
1da177e4 952
1da177e4
LT
953 sc->scsi_done(sc); /* Issue the command callback */
954
955 /* Free Chain buffers */
956 mptscsih_freeChainBuffers(ioc, req_idx);
957 return 1;
958}
959
1da177e4
LT
960/*
961 * mptscsih_flush_running_cmds - For each command found, search
962 * Scsi_Host instance taskQ and reply to OS.
963 * Called only if recovering from a FW reload.
964 * @hd: Pointer to a SCSI HOST structure
965 *
966 * Returns: None.
967 *
968 * Must be called while new I/Os are being queued.
969 */
970static void
971mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
972{
973 MPT_ADAPTER *ioc = hd->ioc;
e8206381
EM
974 struct scsi_cmnd *sc;
975 SCSIIORequest_t *mf = NULL;
1da177e4 976 int ii;
e8206381 977 int channel, id;
1da177e4 978
e8206381
EM
979 for (ii= 0; ii < ioc->req_depth; ii++) {
980 sc = mptscsih_getclear_scsi_lookup(ioc, ii);
981 if (!sc)
982 continue;
983 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
984 if (!mf)
985 continue;
986 channel = mf->Bus;
987 id = mf->TargetID;
988 mptscsih_freeChainBuffers(ioc, ii);
989 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
990 if ((unsigned char *)mf != sc->host_scribble)
991 continue;
992 scsi_dma_unmap(sc);
993 sc->result = DID_RESET << 16;
994 sc->host_scribble = NULL;
c51d0bea 995 sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
e8206381
EM
996 "completing cmds: fw_channel %d, fw_id %d, sc=%p,"
997 " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii);
998 sc->scsi_done(sc);
1da177e4 999 }
1da177e4
LT
1000}
1001
1002/*
1003 * mptscsih_search_running_cmds - Delete any commands associated
1004 * with the specified target and lun. Function called only
1005 * when a lun is disable by mid-layer.
1006 * Do NOT access the referenced scsi_cmnd structure or
1007 * members. Will cause either a paging or NULL ptr error.
05e8ec17 1008 * (BUT, BUT, BUT, the code does reference it! - mdr)
c7c82987
MED
1009 * @hd: Pointer to a SCSI HOST structure
1010 * @vdevice: per device private data
1da177e4
LT
1011 *
1012 * Returns: None.
1013 *
1014 * Called from slave_destroy.
1015 */
1016static void
c7c82987 1017mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1da177e4
LT
1018{
1019 SCSIIORequest_t *mf = NULL;
1020 int ii;
466544d8 1021 struct scsi_cmnd *sc;
793955f5 1022 struct scsi_lun lun;
e80b002b 1023 MPT_ADAPTER *ioc = hd->ioc;
e8206381 1024 unsigned long flags;
1da177e4 1025
e8206381
EM
1026 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1027 for (ii = 0; ii < ioc->req_depth; ii++) {
1028 if ((sc = ioc->ScsiLookup[ii]) != NULL) {
1da177e4 1029
e80b002b 1030 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
3dc0b03f
EM
1031 if (mf == NULL)
1032 continue;
cc78d30a
EM
1033 /* If the device is a hidden raid component, then its
1034 * expected that the mf->function will be RAID_SCSI_IO
1035 */
1036 if (vdevice->vtarget->tflags &
1037 MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
1038 MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
1039 continue;
1040
793955f5
EM
1041 int_to_scsilun(vdevice->lun, &lun);
1042 if ((mf->Bus != vdevice->vtarget->channel) ||
1043 (mf->TargetID != vdevice->vtarget->id) ||
1044 memcmp(lun.scsi_lun, mf->LUN, 8))
1da177e4
LT
1045 continue;
1046
3dc0b03f
EM
1047 if ((unsigned char *)mf != sc->host_scribble)
1048 continue;
e8206381
EM
1049 ioc->ScsiLookup[ii] = NULL;
1050 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1051 mptscsih_freeChainBuffers(ioc, ii);
1052 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
1928d73f 1053 scsi_dma_unmap(sc);
466544d8
MED
1054 sc->host_scribble = NULL;
1055 sc->result = DID_NO_CONNECT << 16;
c51d0bea 1056 sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d,"
e80b002b 1057 "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel,
6757d6b4 1058 vdevice->vtarget->id, sc, mf, ii);
466544d8 1059 sc->scsi_done(sc);
e8206381 1060 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1da177e4
LT
1061 }
1062 }
e8206381 1063 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1da177e4
LT
1064 return;
1065}
1066
1067/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
1068
1069/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1070/*
1071 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1072 * from a SCSI target device.
1073 * @sc: Pointer to scsi_cmnd structure
1074 * @pScsiReply: Pointer to SCSIIOReply_t
1075 * @pScsiReq: Pointer to original SCSI request
1076 *
1077 * This routine periodically reports QUEUE_FULL status returned from a
1078 * SCSI target device. It reports this to the console via kernel
1079 * printk() API call, not more than once every 10 seconds.
1080 */
1081static void
1082mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1083{
1084 long time = jiffies;
1da177e4 1085 MPT_SCSI_HOST *hd;
e80b002b 1086 MPT_ADAPTER *ioc;
1da177e4 1087
0d0c7974
MED
1088 if (sc->device == NULL)
1089 return;
1090 if (sc->device->host == NULL)
1091 return;
e7eae9f6 1092 if ((hd = shost_priv(sc->device->host)) == NULL)
0d0c7974 1093 return;
e80b002b 1094 ioc = hd->ioc;
0d0c7974 1095 if (time - hd->last_queue_full > 10 * HZ) {
e80b002b
EM
1096 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1097 ioc->name, 0, sc->device->id, sc->device->lun));
0d0c7974 1098 hd->last_queue_full = time;
1da177e4 1099 }
1da177e4
LT
1100}
1101
1102/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1103/*
1104 * mptscsih_remove - Removed scsi devices
1105 * @pdev: Pointer to pci_dev structure
1106 *
1107 *
1108 */
0d0c7974 1109void
1da177e4
LT
1110mptscsih_remove(struct pci_dev *pdev)
1111{
1112 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1113 struct Scsi_Host *host = ioc->sh;
1114 MPT_SCSI_HOST *hd;
0d0c7974 1115 int sz1;
1da177e4 1116
466544d8
MED
1117 if(!host) {
1118 mpt_detach(pdev);
1da177e4 1119 return;
466544d8 1120 }
1da177e4
LT
1121
1122 scsi_remove_host(host);
1123
e7eae9f6 1124 if((hd = shost_priv(host)) == NULL)
0d0c7974
MED
1125 return;
1126
d18c3db5 1127 mptscsih_shutdown(pdev);
1da177e4 1128
0d0c7974 1129 sz1=0;
1da177e4 1130
e8206381 1131 if (ioc->ScsiLookup != NULL) {
e80b002b 1132 sz1 = ioc->req_depth * sizeof(void *);
e8206381
EM
1133 kfree(ioc->ScsiLookup);
1134 ioc->ScsiLookup = NULL;
0d0c7974 1135 }
1da177e4 1136
e80b002b 1137 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0d0c7974 1138 "Free'd ScsiLookup (%d) memory\n",
e80b002b 1139 ioc->name, sz1));
1da177e4 1140
d485eb83 1141 kfree(hd->info_kbuf);
1da177e4 1142
0d0c7974
MED
1143 /* NULL the Scsi_Host pointer
1144 */
e80b002b 1145 ioc->sh = NULL;
1da177e4
LT
1146
1147 scsi_host_put(host);
1da177e4 1148
0d0c7974 1149 mpt_detach(pdev);
c6678e0c 1150
1da177e4
LT
1151}
1152
1153/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1154/*
1155 * mptscsih_shutdown - reboot notifier
1156 *
1157 */
0d0c7974 1158void
d18c3db5 1159mptscsih_shutdown(struct pci_dev *pdev)
1da177e4 1160{
1da177e4
LT
1161}
1162
1163#ifdef CONFIG_PM
1164/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1165/*
0d0c7974 1166 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1da177e4
LT
1167 *
1168 *
1169 */
0d0c7974 1170int
8d189f72 1171mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1da177e4 1172{
4d4109d0
PS
1173 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1174
1175 scsi_block_requests(ioc->sh);
1176 flush_scheduled_work();
d18c3db5 1177 mptscsih_shutdown(pdev);
0d0c7974 1178 return mpt_suspend(pdev,state);
1da177e4
LT
1179}
1180
1181/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1182/*
1183 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1184 *
1185 *
1186 */
0d0c7974 1187int
1da177e4
LT
1188mptscsih_resume(struct pci_dev *pdev)
1189{
4d4109d0
PS
1190 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1191 int rc;
1192
1193 rc = mpt_resume(pdev);
1194 scsi_unblock_requests(ioc->sh);
1195 return rc;
1da177e4
LT
1196}
1197
1198#endif
1199
1da177e4
LT
1200/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1201/**
1202 * mptscsih_info - Return information about MPT adapter
1203 * @SChost: Pointer to Scsi_Host structure
1204 *
1205 * (linux scsi_host_template.info routine)
1206 *
1207 * Returns pointer to buffer where information was written.
1208 */
0d0c7974 1209const char *
1da177e4
LT
1210mptscsih_info(struct Scsi_Host *SChost)
1211{
1212 MPT_SCSI_HOST *h;
1213 int size = 0;
1214
e7eae9f6 1215 h = shost_priv(SChost);
0d0c7974 1216
1da177e4 1217 if (h) {
0d0c7974
MED
1218 if (h->info_kbuf == NULL)
1219 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1220 return h->info_kbuf;
1221 h->info_kbuf[0] = '\0';
1222
1223 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1224 h->info_kbuf[size-1] = '\0';
1da177e4
LT
1225 }
1226
0d0c7974 1227 return h->info_kbuf;
1da177e4
LT
1228}
1229
1230struct info_str {
1231 char *buffer;
1232 int length;
1233 int offset;
1234 int pos;
1235};
1236
0d0c7974
MED
1237static void
1238mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1da177e4
LT
1239{
1240 if (info->pos + len > info->length)
1241 len = info->length - info->pos;
1242
1243 if (info->pos + len < info->offset) {
1244 info->pos += len;
1245 return;
1246 }
1247
1248 if (info->pos < info->offset) {
1249 data += (info->offset - info->pos);
1250 len -= (info->offset - info->pos);
1251 }
1252
1253 if (len > 0) {
1254 memcpy(info->buffer + info->pos, data, len);
1255 info->pos += len;
1256 }
1257}
1258
0d0c7974
MED
1259static int
1260mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1da177e4
LT
1261{
1262 va_list args;
1263 char buf[81];
1264 int len;
1265
1266 va_start(args, fmt);
1267 len = vsprintf(buf, fmt, args);
1268 va_end(args);
1269
0d0c7974 1270 mptscsih_copy_mem_info(info, buf, len);
1da177e4
LT
1271 return len;
1272}
1273
0d0c7974
MED
1274static int
1275mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1da177e4
LT
1276{
1277 struct info_str info;
1278
1279 info.buffer = pbuf;
1280 info.length = len;
1281 info.offset = offset;
1282 info.pos = 0;
1283
0d0c7974
MED
1284 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1285 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1286 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1287 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1da177e4
LT
1288
1289 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1290}
1291
1292/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1293/**
1294 * mptscsih_proc_info - Return information about MPT adapter
d9489fb6
RD
1295 * @host: scsi host struct
1296 * @buffer: if write, user data; if read, buffer for user
1297 * @start: returns the buffer address
1298 * @offset: if write, 0; if read, the current offset into the buffer from
1299 * the previous read.
1300 * @length: if write, return length;
1301 * @func: write = 1; read = 0
1da177e4
LT
1302 *
1303 * (linux scsi_host_template.info routine)
1da177e4 1304 */
0d0c7974 1305int
1da177e4
LT
1306mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1307 int length, int func)
1308{
e7eae9f6 1309 MPT_SCSI_HOST *hd = shost_priv(host);
1da177e4
LT
1310 MPT_ADAPTER *ioc = hd->ioc;
1311 int size = 0;
1312
1313 if (func) {
c6678e0c
CH
1314 /*
1315 * write is not supported
1da177e4
LT
1316 */
1317 } else {
1318 if (start)
1319 *start = buffer;
1320
1321 size = mptscsih_host_info(ioc, buffer, offset, length);
1322 }
1323
1324 return size;
1325}
1326
1327/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1328#define ADD_INDEX_LOG(req_ent) do { } while(0)
1329
1330/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1331/**
1332 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1333 * @SCpnt: Pointer to scsi_cmnd structure
1334 * @done: Pointer SCSI mid-layer IO completion function
1335 *
1336 * (linux scsi_host_template.queuecommand routine)
1337 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1338 * from a linux scsi_cmnd request and send it to the IOC.
1339 *
1340 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1341 */
0d0c7974 1342int
1da177e4
LT
1343mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1344{
1345 MPT_SCSI_HOST *hd;
1346 MPT_FRAME_HDR *mf;
1347 SCSIIORequest_t *pScsiReq;
a69de507 1348 VirtDevice *vdevice = SCpnt->device->hostdata;
1da177e4
LT
1349 int lun;
1350 u32 datalen;
1351 u32 scsictl;
1352 u32 scsidir;
1353 u32 cmd_len;
1354 int my_idx;
1355 int ii;
6757d6b4 1356 MPT_ADAPTER *ioc;
1da177e4 1357
e7eae9f6 1358 hd = shost_priv(SCpnt->device->host);
6757d6b4 1359 ioc = hd->ioc;
1da177e4
LT
1360 lun = SCpnt->device->lun;
1361 SCpnt->scsi_done = done;
1362
6757d6b4
PS
1363 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
1364 ioc->name, SCpnt, done));
1da177e4
LT
1365
1366 if (hd->resetPending) {
6757d6b4
PS
1367 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1368 ioc->name, SCpnt));
1da177e4
LT
1369 return SCSI_MLQUEUE_HOST_BUSY;
1370 }
1371
1372 /*
1373 * Put together a MPT SCSI request...
1374 */
e80b002b 1375 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
6757d6b4
PS
1376 dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1377 ioc->name));
1da177e4
LT
1378 return SCSI_MLQUEUE_HOST_BUSY;
1379 }
1380
1381 pScsiReq = (SCSIIORequest_t *) mf;
1382
1383 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1384
1385 ADD_INDEX_LOG(my_idx);
1386
0d0c7974 1387 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1da177e4
LT
1388 * Seems we may receive a buffer (datalen>0) even when there
1389 * will be no data transfer! GRRRRR...
1390 */
1391 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1928d73f 1392 datalen = scsi_bufflen(SCpnt);
1da177e4
LT
1393 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1394 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1928d73f 1395 datalen = scsi_bufflen(SCpnt);
1da177e4
LT
1396 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1397 } else {
1398 datalen = 0;
1399 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1400 }
1401
1402 /* Default to untagged. Once a target structure has been allocated,
1403 * use the Inquiry data to determine if device supports tagged.
1404 */
a69de507
EM
1405 if (vdevice
1406 && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1da177e4
LT
1407 && (SCpnt->device->tagged_supported)) {
1408 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1409 } else {
1410 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1411 }
1412
1413 /* Use the above information to set up the message frame
1414 */
a69de507
EM
1415 pScsiReq->TargetID = (u8) vdevice->vtarget->id;
1416 pScsiReq->Bus = vdevice->vtarget->channel;
1da177e4 1417 pScsiReq->ChainOffset = 0;
a69de507 1418 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
c92f222e
JB
1419 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1420 else
1421 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1da177e4
LT
1422 pScsiReq->CDBLength = SCpnt->cmd_len;
1423 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1424 pScsiReq->Reserved = 0;
1425 pScsiReq->MsgFlags = mpt_msg_flags();
793955f5 1426 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1da177e4
LT
1427 pScsiReq->Control = cpu_to_le32(scsictl);
1428
1429 /*
1430 * Write SCSI CDB into the message
1431 */
1432 cmd_len = SCpnt->cmd_len;
1433 for (ii=0; ii < cmd_len; ii++)
1434 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1435
1436 for (ii=cmd_len; ii < 16; ii++)
1437 pScsiReq->CDB[ii] = 0;
1438
1439 /* DataLength */
1440 pScsiReq->DataLength = cpu_to_le32(datalen);
1441
1442 /* SenseBuffer low address */
e80b002b 1443 pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
1da177e4
LT
1444 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1445
1446 /* Now add the SG list
1447 * Always have a SGE even if null length.
1448 */
1449 if (datalen == 0) {
1450 /* Add a NULL SGE */
1451 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1452 (dma_addr_t) -1);
1453 } else {
1454 /* Add a 32 or 64 bit SGE */
e80b002b 1455 if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1da177e4
LT
1456 goto fail;
1457 }
1458
3dc0b03f 1459 SCpnt->host_scribble = (unsigned char *)mf;
e8206381 1460 mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
1da177e4 1461
e80b002b 1462 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
6757d6b4
PS
1463 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1464 ioc->name, SCpnt, mf, my_idx));
29dd3609 1465 DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);
1da177e4
LT
1466 return 0;
1467
1468 fail:
e80b002b
EM
1469 mptscsih_freeChainBuffers(ioc, my_idx);
1470 mpt_free_msg_frame(ioc, mf);
1da177e4
LT
1471 return SCSI_MLQUEUE_HOST_BUSY;
1472}
1473
1474/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1475/*
1476 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1477 * with a SCSI IO request
1478 * @hd: Pointer to the MPT_SCSI_HOST instance
1479 * @req_idx: Index of the SCSI IO request frame.
1480 *
1481 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1482 * No return.
1483 */
1484static void
1485mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1486{
1487 MPT_FRAME_HDR *chain;
1488 unsigned long flags;
1489 int chain_idx;
1490 int next;
1491
1492 /* Get the first chain index and reset
1493 * tracker state.
1494 */
1495 chain_idx = ioc->ReqToChain[req_idx];
1496 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1497
1498 while (chain_idx != MPT_HOST_NO_CHAIN) {
1499
1500 /* Save the next chain buffer index */
1501 next = ioc->ChainToChain[chain_idx];
1502
1503 /* Free this chain buffer and reset
1504 * tracker
1505 */
1506 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1507
1508 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1509 + (chain_idx * ioc->req_sz));
1510
1511 spin_lock_irqsave(&ioc->FreeQlock, flags);
1512 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1513 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1514
6757d6b4 1515 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n",
1da177e4
LT
1516 ioc->name, chain_idx));
1517
1518 /* handle next */
1519 chain_idx = next;
1520 }
1521 return;
1522}
1523
1524/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1525/*
1526 * Reset Handling
1527 */
1528
1529/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
cd2c6191 1530/**
1da177e4 1531 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1544d677 1532 * @hd: Pointer to MPT SCSI HOST structure
1da177e4 1533 * @type: Task Management type
1544d677 1534 * @channel: channel number for task management
793955f5 1535 * @id: Logical Target ID for reset (if appropriate)
1da177e4
LT
1536 * @lun: Logical Unit for reset (if appropriate)
1537 * @ctx2abort: Context for the task to be aborted (if appropriate)
1544d677
RD
1538 * @timeout: timeout for task management control
1539 *
1540 * Fall through to mpt_HardResetHandler if: not operational, too many
1541 * failed TM requests or handshake failure.
1da177e4
LT
1542 *
1543 * Remark: Currently invoked from a non-interrupt thread (_bh).
1544 *
7105a387 1545 * Note: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1da177e4
LT
1546 * will be active.
1547 *
1544d677 1548 * Returns 0 for SUCCESS, or %FAILED.
cd2c6191 1549 **/
663e1aa1 1550int
793955f5 1551mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1da177e4
LT
1552{
1553 MPT_ADAPTER *ioc;
1554 int rc = -1;
1da177e4
LT
1555 u32 ioc_raw_state;
1556 unsigned long flags;
1557
1da177e4 1558 ioc = hd->ioc;
6757d6b4 1559 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name));
1da177e4
LT
1560
1561 // SJR - CHECKME - Can we avoid this here?
1562 // (mpt_HardResetHandler has this check...)
1563 spin_lock_irqsave(&ioc->diagLock, flags);
1564 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1565 spin_unlock_irqrestore(&ioc->diagLock, flags);
1566 return FAILED;
1567 }
1568 spin_unlock_irqrestore(&ioc->diagLock, flags);
1569
1570 /* Wait a fixed amount of time for the TM pending flag to be cleared.
cd2c6191
EM
1571 * If we time out and not bus reset, then we return a FAILED status
1572 * to the caller.
1573 * The call to mptscsih_tm_pending_wait() will set the pending flag
1574 * if we are
1da177e4
LT
1575 * successful. Otherwise, reload the FW.
1576 */
1577 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1578 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
29dd3609 1579 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: "
1da177e4 1580 "Timed out waiting for last TM (%d) to complete! \n",
6757d6b4 1581 ioc->name, hd->tmPending));
1da177e4
LT
1582 return FAILED;
1583 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
29dd3609 1584 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target "
cd2c6191 1585 "reset: Timed out waiting for last TM (%d) "
6757d6b4 1586 "to complete! \n", ioc->name,
cd2c6191 1587 hd->tmPending));
1da177e4
LT
1588 return FAILED;
1589 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
29dd3609 1590 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: "
1da177e4 1591 "Timed out waiting for last TM (%d) to complete! \n",
6757d6b4 1592 ioc->name, hd->tmPending));
cd2c6191 1593 return FAILED;
1da177e4
LT
1594 }
1595 } else {
e80b002b 1596 spin_lock_irqsave(&ioc->FreeQlock, flags);
1da177e4 1597 hd->tmPending |= (1 << type);
e80b002b 1598 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1da177e4
LT
1599 }
1600
e80b002b 1601 ioc_raw_state = mpt_GetIocState(ioc, 0);
1da177e4 1602
1da177e4
LT
1603 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1604 printk(MYIOC_s_WARN_FMT
cd2c6191
EM
1605 "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
1606 ioc->name, type, ioc_raw_state);
29dd3609 1607 printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name);
cd2c6191 1608 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
29dd3609
EM
1609 printk(MYIOC_s_WARN_FMT "TMHandler: HardReset "
1610 "FAILED!!\n", ioc->name);
cd2c6191 1611 return FAILED;
1da177e4
LT
1612 }
1613
cd2c6191
EM
1614 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1615 printk(MYIOC_s_WARN_FMT
1616 "TM Handler for type=%x: ioc_state: "
1617 "DOORBELL_ACTIVE (0x%x)!\n",
1618 ioc->name, type, ioc_raw_state);
1619 return FAILED;
1da177e4
LT
1620 }
1621
cd2c6191 1622 /* Isse the Task Mgmt request.
3dc0b03f 1623 */
cd2c6191
EM
1624 if (hd->hard_resets < -1)
1625 hd->hard_resets++;
1626
1627 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1628 ctx2abort, timeout);
1629 if (rc)
1630 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
6757d6b4 1631 ioc->name);
cd2c6191 1632 else
6757d6b4
PS
1633 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n",
1634 ioc->name));
3dc0b03f 1635
6757d6b4
PS
1636 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1637 "TMHandler rc = %d!\n", ioc->name, rc));
1da177e4
LT
1638
1639 return rc;
1640}
1641
1642
1643/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
cd2c6191 1644/**
1da177e4
LT
1645 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1646 * @hd: Pointer to MPT_SCSI_HOST structure
1647 * @type: Task Management type
1544d677 1648 * @channel: channel number for task management
793955f5 1649 * @id: Logical Target ID for reset (if appropriate)
1da177e4
LT
1650 * @lun: Logical Unit for reset (if appropriate)
1651 * @ctx2abort: Context for the task to be aborted (if appropriate)
1544d677 1652 * @timeout: timeout for task management control
1da177e4
LT
1653 *
1654 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1655 * or a non-interrupt thread. In the former, must not call schedule().
1656 *
1657 * Not all fields are meaningfull for all task types.
1658 *
cd2c6191
EM
1659 * Returns 0 for SUCCESS, or FAILED.
1660 *
1661 **/
1da177e4 1662static int
793955f5 1663mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1da177e4
LT
1664{
1665 MPT_FRAME_HDR *mf;
1666 SCSITaskMgmt_t *pScsiTm;
1667 int ii;
1668 int retval;
e80b002b 1669 MPT_ADAPTER *ioc = hd->ioc;
1da177e4
LT
1670
1671 /* Return Fail to calling function if no message frames available.
1672 */
e80b002b
EM
1673 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
1674 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1675 ioc->name));
c6678e0c 1676 return FAILED;
1da177e4 1677 }
e80b002b
EM
1678 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
1679 ioc->name, mf));
1da177e4
LT
1680
1681 /* Format the Request
1682 */
1683 pScsiTm = (SCSITaskMgmt_t *) mf;
793955f5 1684 pScsiTm->TargetID = id;
1da177e4
LT
1685 pScsiTm->Bus = channel;
1686 pScsiTm->ChainOffset = 0;
1687 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1688
1689 pScsiTm->Reserved = 0;
1690 pScsiTm->TaskType = type;
1691 pScsiTm->Reserved1 = 0;
1692 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1693 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1694
793955f5 1695 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1da177e4
LT
1696
1697 for (ii=0; ii < 7; ii++)
1698 pScsiTm->Reserved2[ii] = 0;
1699
1700 pScsiTm->TaskMsgContext = ctx2abort;
1701
e80b002b
EM
1702 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
1703 "type=%d\n", ioc->name, ctx2abort, type));
1da177e4 1704
6757d6b4 1705 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
1da177e4 1706
e80b002b
EM
1707 if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
1708 (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
1709 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
7a195f46 1710 else {
e80b002b 1711 retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
7a195f46
PS
1712 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
1713 if (retval) {
e80b002b
EM
1714 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
1715 " (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd,
1716 ioc, mf, retval));
7a195f46
PS
1717 goto fail_out;
1718 }
1da177e4
LT
1719 }
1720
1721 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
e80b002b
EM
1722 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1723 " (hd %p, ioc %p, mf %p) \n", ioc->name, hd,
1724 ioc, mf));
1725 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
1726 ioc->name));
1727 retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
1728 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
1729 ioc->name, retval));
cd2c6191 1730 goto fail_out;
1da177e4
LT
1731 }
1732
cd2c6191
EM
1733 /*
1734 * Handle success case, see if theres a non-zero ioc_status.
1735 */
1736 if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1737 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1738 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1739 retval = 0;
1740 else
1741 retval = FAILED;
1742
1da177e4 1743 return retval;
cd2c6191
EM
1744
1745 fail_out:
1746
1747 /*
fc1323bb 1748 * Free task management mf, and corresponding tm flags
cd2c6191 1749 */
e80b002b 1750 mpt_free_msg_frame(ioc, mf);
cd2c6191
EM
1751 hd->tmPending = 0;
1752 hd->tmState = TM_STATE_NONE;
1753 return FAILED;
1da177e4
LT
1754}
1755
d66c7a0f
CH
1756static int
1757mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1758{
1759 switch (ioc->bus_type) {
1760 case FC:
1761 return 40;
1762 case SAS:
1763 return 10;
1764 case SPI:
1765 default:
1766 return 2;
1767 }
1768}
1769
1da177e4
LT
1770/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1771/**
1772 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1773 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1774 *
1775 * (linux scsi_host_template.eh_abort_handler routine)
1776 *
1777 * Returns SUCCESS or FAILED.
cd2c6191 1778 **/
0d0c7974 1779int
1da177e4
LT
1780mptscsih_abort(struct scsi_cmnd * SCpnt)
1781{
1782 MPT_SCSI_HOST *hd;
1da177e4
LT
1783 MPT_FRAME_HDR *mf;
1784 u32 ctx2abort;
1785 int scpnt_idx;
466544d8 1786 int retval;
958d4a32 1787 VirtDevice *vdevice;
3dc0b03f 1788 ulong sn = SCpnt->serial_number;
958d4a32 1789 MPT_ADAPTER *ioc;
1da177e4
LT
1790
1791 /* If we can't locate our host adapter structure, return FAILED status.
1792 */
e7eae9f6 1793 if ((hd = shost_priv(SCpnt->device->host)) == NULL) {
1da177e4
LT
1794 SCpnt->result = DID_RESET << 16;
1795 SCpnt->scsi_done(SCpnt);
29dd3609
EM
1796 printk(KERN_ERR MYNAM ": task abort: "
1797 "can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1798 return FAILED;
1799 }
1800
958d4a32
EM
1801 ioc = hd->ioc;
1802 printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
1803 ioc->name, SCpnt);
1804 scsi_print_command(SCpnt);
1805
1806 vdevice = SCpnt->device->hostdata;
1807 if (!vdevice || !vdevice->vtarget) {
29dd3609
EM
1808 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1809 "task abort: device has been deleted (sc=%p)\n",
1810 ioc->name, SCpnt));
958d4a32
EM
1811 SCpnt->result = DID_NO_CONNECT << 16;
1812 SCpnt->scsi_done(SCpnt);
1813 retval = 0;
1814 goto out;
1815 }
1816
cc78d30a
EM
1817 /* Task aborts are not supported for hidden raid components.
1818 */
1819 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
29dd3609
EM
1820 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1821 "task abort: hidden raid component (sc=%p)\n",
1822 ioc->name, SCpnt));
cc78d30a
EM
1823 SCpnt->result = DID_RESET << 16;
1824 retval = FAILED;
1825 goto out;
1826 }
1827
1da177e4
LT
1828 /* Find this command
1829 */
e8206381 1830 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
466544d8 1831 /* Cmd not found in ScsiLookup.
1da177e4
LT
1832 * Do OS callback.
1833 */
1834 SCpnt->result = DID_RESET << 16;
29dd3609 1835 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
958d4a32
EM
1836 "Command not in the active list! (sc=%p)\n", ioc->name,
1837 SCpnt));
1838 retval = 0;
1839 goto out;
1da177e4
LT
1840 }
1841
958d4a32
EM
1842 if (hd->resetPending) {
1843 retval = FAILED;
1844 goto out;
1845 }
65207fed
ME
1846
1847 if (hd->timeouts < -1)
1848 hd->timeouts++;
1849
1da177e4
LT
1850 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1851 * (the IO to be ABORT'd)
1852 *
1853 * NOTE: Since we do not byteswap MsgContext, we do not
1854 * swap it here either. It is an opaque cookie to
1855 * the controller, so it does not matter. -DaveM
1856 */
e80b002b 1857 mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
1da177e4
LT
1858 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1859
1860 hd->abortSCpnt = SCpnt;
1861
466544d8 1862 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
958d4a32
EM
1863 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
1864 ctx2abort, mptscsih_get_tm_timeout(ioc));
1da177e4 1865
e8206381 1866 if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
cd2c6191 1867 SCpnt->serial_number == sn)
3dc0b03f 1868 retval = FAILED;
3dc0b03f 1869
958d4a32
EM
1870 out:
1871 printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
1872 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1da177e4 1873
466544d8
MED
1874 if (retval == 0)
1875 return SUCCESS;
cd2c6191
EM
1876 else
1877 return FAILED;
1da177e4
LT
1878}
1879
1880/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1881/**
1882 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1883 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1884 *
1885 * (linux scsi_host_template.eh_dev_reset_handler routine)
1886 *
1887 * Returns SUCCESS or FAILED.
cd2c6191 1888 **/
0d0c7974 1889int
1da177e4
LT
1890mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1891{
1892 MPT_SCSI_HOST *hd;
466544d8 1893 int retval;
958d4a32
EM
1894 VirtDevice *vdevice;
1895 MPT_ADAPTER *ioc;
1da177e4
LT
1896
1897 /* If we can't locate our host adapter structure, return FAILED status.
1898 */
e7eae9f6 1899 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
1900 printk(KERN_ERR MYNAM ": target reset: "
1901 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1902 return FAILED;
1903 }
1904
958d4a32
EM
1905 ioc = hd->ioc;
1906 printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
1907 ioc->name, SCpnt);
466544d8 1908 scsi_print_command(SCpnt);
1da177e4 1909
958d4a32
EM
1910 if (hd->resetPending) {
1911 retval = FAILED;
1912 goto out;
1913 }
1914
1915 vdevice = SCpnt->device->hostdata;
1916 if (!vdevice || !vdevice->vtarget) {
1917 retval = 0;
1918 goto out;
1919 }
1920
cc78d30a
EM
1921 /* Target reset to hidden raid component is not supported
1922 */
1923 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1924 retval = FAILED;
1925 goto out;
1926 }
1927
466544d8 1928 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
958d4a32
EM
1929 vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
1930 mptscsih_get_tm_timeout(ioc));
466544d8 1931
958d4a32
EM
1932 out:
1933 printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
1934 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
466544d8
MED
1935
1936 if (retval == 0)
1937 return SUCCESS;
cd2c6191
EM
1938 else
1939 return FAILED;
1da177e4
LT
1940}
1941
cd2c6191 1942
1da177e4
LT
1943/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1944/**
1945 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1946 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1947 *
1948 * (linux scsi_host_template.eh_bus_reset_handler routine)
1949 *
1950 * Returns SUCCESS or FAILED.
cd2c6191 1951 **/
0d0c7974 1952int
1da177e4
LT
1953mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1954{
1955 MPT_SCSI_HOST *hd;
466544d8 1956 int retval;
a69de507 1957 VirtDevice *vdevice;
958d4a32 1958 MPT_ADAPTER *ioc;
1da177e4
LT
1959
1960 /* If we can't locate our host adapter structure, return FAILED status.
1961 */
e7eae9f6 1962 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
1963 printk(KERN_ERR MYNAM ": bus reset: "
1964 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1965 return FAILED;
1966 }
1967
958d4a32
EM
1968 ioc = hd->ioc;
1969 printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
1970 ioc->name, SCpnt);
466544d8 1971 scsi_print_command(SCpnt);
1da177e4
LT
1972
1973 if (hd->timeouts < -1)
1974 hd->timeouts++;
1975
a69de507 1976 vdevice = SCpnt->device->hostdata;
466544d8 1977 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
a69de507 1978 vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
1da177e4 1979
958d4a32
EM
1980 printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
1981 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
466544d8
MED
1982
1983 if (retval == 0)
1984 return SUCCESS;
cd2c6191
EM
1985 else
1986 return FAILED;
1da177e4
LT
1987}
1988
1989/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1990/**
d9489fb6 1991 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1da177e4
LT
1992 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1993 *
1994 * (linux scsi_host_template.eh_host_reset_handler routine)
1995 *
1996 * Returns SUCCESS or FAILED.
1997 */
0d0c7974 1998int
1da177e4
LT
1999mptscsih_host_reset(struct scsi_cmnd *SCpnt)
2000{
2001 MPT_SCSI_HOST * hd;
958d4a32
EM
2002 int retval;
2003 MPT_ADAPTER *ioc;
1da177e4
LT
2004
2005 /* If we can't locate the host to reset, then we failed. */
e7eae9f6 2006 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
2007 printk(KERN_ERR MYNAM ": host reset: "
2008 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
2009 return FAILED;
2010 }
2011
958d4a32
EM
2012 ioc = hd->ioc;
2013 printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
2014 ioc->name, SCpnt);
1da177e4
LT
2015
2016 /* If our attempts to reset the host failed, then return a failed
2017 * status. The host will be taken off line by the SCSI mid-layer.
2018 */
e80b002b 2019 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) {
958d4a32 2020 retval = FAILED;
1da177e4
LT
2021 } else {
2022 /* Make sure TM pending is cleared and TM state is set to
2023 * NONE.
2024 */
958d4a32 2025 retval = 0;
1da177e4
LT
2026 hd->tmPending = 0;
2027 hd->tmState = TM_STATE_NONE;
2028 }
1da177e4 2029
958d4a32
EM
2030 printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
2031 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1da177e4 2032
958d4a32 2033 return retval;
1da177e4
LT
2034}
2035
2036/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2037/**
d9489fb6 2038 * mptscsih_tm_pending_wait - wait for pending task management request to complete
1da177e4
LT
2039 * @hd: Pointer to MPT host structure.
2040 *
2041 * Returns {SUCCESS,FAILED}.
2042 */
2043static int
2044mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
2045{
2046 unsigned long flags;
2047 int loop_count = 4 * 10; /* Wait 10 seconds */
2048 int status = FAILED;
e80b002b 2049 MPT_ADAPTER *ioc = hd->ioc;
1da177e4
LT
2050
2051 do {
e80b002b 2052 spin_lock_irqsave(&ioc->FreeQlock, flags);
1da177e4
LT
2053 if (hd->tmState == TM_STATE_NONE) {
2054 hd->tmState = TM_STATE_IN_PROGRESS;
2055 hd->tmPending = 1;
e80b002b 2056 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
c6678e0c 2057 status = SUCCESS;
1da177e4
LT
2058 break;
2059 }
e80b002b 2060 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1da177e4
LT
2061 msleep(250);
2062 } while (--loop_count);
2063
2064 return status;
2065}
2066
2067/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2068/**
2069 * mptscsih_tm_wait_for_completion - wait for completion of TM task
2070 * @hd: Pointer to MPT host structure.
1544d677 2071 * @timeout: timeout value
1da177e4
LT
2072 *
2073 * Returns {SUCCESS,FAILED}.
2074 */
2075static int
2076mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2077{
2078 unsigned long flags;
2079 int loop_count = 4 * timeout;
2080 int status = FAILED;
e80b002b 2081 MPT_ADAPTER *ioc = hd->ioc;
1da177e4
LT
2082
2083 do {
e80b002b 2084 spin_lock_irqsave(&ioc->FreeQlock, flags);
1da177e4
LT
2085 if(hd->tmPending == 0) {
2086 status = SUCCESS;
e80b002b 2087 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1da177e4
LT
2088 break;
2089 }
e80b002b 2090 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
d6be06c8 2091 msleep(250);
1da177e4
LT
2092 } while (--loop_count);
2093
2094 return status;
2095}
2096
9f63bb73
ME
2097/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2098static void
2099mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2100{
2101 char *desc;
2102
2103 switch (response_code) {
2104 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2105 desc = "The task completed.";
2106 break;
2107 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2108 desc = "The IOC received an invalid frame status.";
2109 break;
2110 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2111 desc = "The task type is not supported.";
2112 break;
2113 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2114 desc = "The requested task failed.";
2115 break;
2116 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2117 desc = "The task completed successfully.";
2118 break;
2119 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2120 desc = "The LUN request is invalid.";
2121 break;
2122 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2123 desc = "The task is in the IOC queue and has not been sent to target.";
2124 break;
2125 default:
2126 desc = "unknown";
2127 break;
2128 }
2129 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2130 ioc->name, response_code, desc);
2131}
2132
1da177e4
LT
2133/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2134/**
2135 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2136 * @ioc: Pointer to MPT_ADAPTER structure
2137 * @mf: Pointer to SCSI task mgmt request frame
2138 * @mr: Pointer to SCSI task mgmt reply frame
2139 *
2140 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2141 * of any SCSI task management request.
2142 * This routine is registered with the MPT (base) driver at driver
2143 * load/init time via the mpt_register() API call.
2144 *
2145 * Returns 1 indicating alloc'd request frame ptr should be freed.
cd2c6191 2146 **/
0d0c7974 2147int
1da177e4
LT
2148mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2149{
2150 SCSITaskMgmtReply_t *pScsiTmReply;
2151 SCSITaskMgmt_t *pScsiTmReq;
2152 MPT_SCSI_HOST *hd;
2153 unsigned long flags;
2154 u16 iocstatus;
2155 u8 tmType;
cd2c6191 2156 u32 termination_count;
1da177e4 2157
6757d6b4 2158 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
cd2c6191
EM
2159 ioc->name, mf, mr));
2160 if (!ioc->sh) {
6757d6b4 2161 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
cd2c6191 2162 "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
1da177e4
LT
2163 return 1;
2164 }
2165
2166 if (mr == NULL) {
6757d6b4 2167 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
cd2c6191 2168 "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
1da177e4 2169 return 1;
cd2c6191 2170 }
1da177e4 2171
e7eae9f6 2172 hd = shost_priv(ioc->sh);
cd2c6191
EM
2173 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2174 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2175 tmType = pScsiTmReq->TaskType;
2176 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2177 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2178
2179 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2180 pScsiTmReply->ResponseCode)
2181 mptscsih_taskmgmt_response_code(ioc,
2182 pScsiTmReply->ResponseCode);
6757d6b4
PS
2183 DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
2184
2185#ifdef CONFIG_FUSION_LOGGING
2186 if ((ioc->debug_level & MPT_DEBUG_REPLY) ||
2187 (ioc->debug_level & MPT_DEBUG_TM ))
2188 printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2189 "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2190 "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
2191 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2192 le16_to_cpu(pScsiTmReply->IOCStatus),
2193 le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2194 le32_to_cpu(pScsiTmReply->TerminationCount));
cd2c6191
EM
2195#endif
2196 if (!iocstatus) {
6757d6b4 2197 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name));
cd2c6191
EM
2198 hd->abortSCpnt = NULL;
2199 goto out;
2200 }
1da177e4 2201
cd2c6191 2202 /* Error? (anything non-zero?) */
9f63bb73 2203
cd2c6191
EM
2204 /* clear flags and continue.
2205 */
2206 switch (tmType) {
1da177e4 2207
cd2c6191
EM
2208 case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2209 if (termination_count == 1)
2210 iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2211 hd->abortSCpnt = NULL;
2212 break;
1da177e4 2213
cd2c6191 2214 case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
1da177e4 2215
cd2c6191
EM
2216 /* If an internal command is present
2217 * or the TM failed - reload the FW.
2218 * FC FW may respond FAILED to an ABORT
2219 */
2220 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2221 hd->cmdPtr)
2222 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
29dd3609 2223 printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name);
cd2c6191 2224 break;
1da177e4 2225
cd2c6191
EM
2226 case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2227 default:
2228 break;
1da177e4
LT
2229 }
2230
cd2c6191 2231 out:
1da177e4
LT
2232 spin_lock_irqsave(&ioc->FreeQlock, flags);
2233 hd->tmPending = 0;
1da177e4 2234 hd->tmState = TM_STATE_NONE;
cd2c6191
EM
2235 hd->tm_iocstatus = iocstatus;
2236 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1da177e4
LT
2237
2238 return 1;
2239}
2240
2241/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2242/*
2243 * This is anyones guess quite frankly.
2244 */
0d0c7974 2245int
1da177e4
LT
2246mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2247 sector_t capacity, int geom[])
2248{
2249 int heads;
2250 int sectors;
2251 sector_t cylinders;
2252 ulong dummy;
2253
2254 heads = 64;
2255 sectors = 32;
2256
2257 dummy = heads * sectors;
2258 cylinders = capacity;
2259 sector_div(cylinders,dummy);
2260
2261 /*
2262 * Handle extended translation size for logical drives
2263 * > 1Gb
2264 */
2265 if ((ulong)capacity >= 0x200000) {
2266 heads = 255;
2267 sectors = 63;
2268 dummy = heads * sectors;
2269 cylinders = capacity;
2270 sector_div(cylinders,dummy);
2271 }
2272
2273 /* return result */
2274 geom[0] = heads;
2275 geom[1] = sectors;
2276 geom[2] = cylinders;
2277
1da177e4
LT
2278 return 0;
2279}
2280
f44e5461
ME
2281/* Search IOC page 3 to determine if this is hidden physical disk
2282 *
2283 */
2284int
793955f5 2285mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
f44e5461 2286{
b506ade9 2287 struct inactive_raid_component_info *component_info;
f44e5461 2288 int i;
793955f5 2289 int rc = 0;
f44e5461 2290
793955f5
EM
2291 if (!ioc->raid_data.pIocPg3)
2292 goto out;
f44e5461 2293 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
793955f5
EM
2294 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2295 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2296 rc = 1;
2297 goto out;
2298 }
c92f222e
JB
2299 }
2300
b506ade9
EM
2301 /*
2302 * Check inactive list for matching phys disks
2303 */
2304 if (list_empty(&ioc->raid_data.inactive_list))
2305 goto out;
2306
ed5f606f 2307 mutex_lock(&ioc->raid_data.inactive_list_mutex);
b506ade9
EM
2308 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2309 list) {
2310 if ((component_info->d.PhysDiskID == id) &&
2311 (component_info->d.PhysDiskBus == channel))
2312 rc = 1;
2313 }
ed5f606f 2314 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
b506ade9 2315
793955f5
EM
2316 out:
2317 return rc;
c7c82987 2318}
793955f5 2319EXPORT_SYMBOL(mptscsih_is_phys_disk);
c7c82987 2320
793955f5
EM
2321u8
2322mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
1da177e4 2323{
b506ade9 2324 struct inactive_raid_component_info *component_info;
793955f5
EM
2325 int i;
2326 int rc = -ENXIO;
c92f222e 2327
793955f5
EM
2328 if (!ioc->raid_data.pIocPg3)
2329 goto out;
2330 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2331 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2332 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2333 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2334 goto out;
1da177e4 2335 }
1da177e4 2336 }
1da177e4 2337
b506ade9
EM
2338 /*
2339 * Check inactive list for matching phys disks
2340 */
2341 if (list_empty(&ioc->raid_data.inactive_list))
2342 goto out;
2343
ed5f606f 2344 mutex_lock(&ioc->raid_data.inactive_list_mutex);
b506ade9
EM
2345 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2346 list) {
2347 if ((component_info->d.PhysDiskID == id) &&
2348 (component_info->d.PhysDiskBus == channel))
2349 rc = component_info->d.PhysDiskNum;
2350 }
ed5f606f 2351 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
b506ade9 2352
793955f5
EM
2353 out:
2354 return rc;
c7c82987 2355}
793955f5 2356EXPORT_SYMBOL(mptscsih_raid_id_to_num);
1da177e4 2357
c7c82987
MED
2358/*
2359 * OS entry point to allow for host driver to free allocated memory
2360 * Called if no device present or device being unloaded
2361 */
2362void
2363mptscsih_slave_destroy(struct scsi_device *sdev)
2364{
2365 struct Scsi_Host *host = sdev->host;
e7eae9f6 2366 MPT_SCSI_HOST *hd = shost_priv(host);
c7c82987
MED
2367 VirtTarget *vtarget;
2368 VirtDevice *vdevice;
2369 struct scsi_target *starget;
2370
2371 starget = scsi_target(sdev);
2372 vtarget = starget->hostdata;
2373 vdevice = sdev->hostdata;
2374
2375 mptscsih_search_running_cmds(hd, vdevice);
c7c82987 2376 vtarget->num_luns--;
c7c82987
MED
2377 mptscsih_synchronize_cache(hd, vdevice);
2378 kfree(vdevice);
2379 sdev->hostdata = NULL;
1da177e4
LT
2380}
2381
6e3815ba
MED
2382/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2383/*
2384 * mptscsih_change_queue_depth - This function will set a devices queue depth
2385 * @sdev: per scsi_device pointer
2386 * @qdepth: requested queue depth
2387 *
2388 * Adding support for new 'change_queue_depth' api.
2389*/
2390int
2391mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
1da177e4 2392{
e7eae9f6 2393 MPT_SCSI_HOST *hd = shost_priv(sdev->host);
c7c82987
MED
2394 VirtTarget *vtarget;
2395 struct scsi_target *starget;
2396 int max_depth;
2397 int tagged;
e80b002b 2398 MPT_ADAPTER *ioc = hd->ioc;
1da177e4 2399
c7c82987
MED
2400 starget = scsi_target(sdev);
2401 vtarget = starget->hostdata;
6e3815ba 2402
e80b002b 2403 if (ioc->bus_type == SPI) {
c92f222e 2404 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
1da177e4 2405 max_depth = 1;
c92f222e
JB
2406 else if (sdev->type == TYPE_DISK &&
2407 vtarget->minSyncFactor <= MPT_ULTRA160)
2408 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2409 else
2410 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
1da177e4
LT
2411 } else
2412 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2413
2414 if (qdepth > max_depth)
2415 qdepth = max_depth;
2416 if (qdepth == 1)
2417 tagged = 0;
2418 else
2419 tagged = MSG_SIMPLE_TAG;
2420
6e3815ba
MED
2421 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2422 return sdev->queue_depth;
1da177e4
LT
2423}
2424
1da177e4
LT
2425/*
2426 * OS entry point to adjust the queue_depths on a per-device basis.
2427 * Called once per device the bus scan. Use it to force the queue_depth
2428 * member to 1 if a device does not support Q tags.
2429 * Return non-zero if fails.
2430 */
0d0c7974 2431int
c7c82987 2432mptscsih_slave_configure(struct scsi_device *sdev)
1da177e4 2433{
c7c82987
MED
2434 struct Scsi_Host *sh = sdev->host;
2435 VirtTarget *vtarget;
2436 VirtDevice *vdevice;
2437 struct scsi_target *starget;
e7eae9f6 2438 MPT_SCSI_HOST *hd = shost_priv(sh);
e80b002b 2439 MPT_ADAPTER *ioc = hd->ioc;
1da177e4 2440
c7c82987
MED
2441 starget = scsi_target(sdev);
2442 vtarget = starget->hostdata;
2443 vdevice = sdev->hostdata;
1da177e4 2444
e80b002b 2445 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
793955f5 2446 "device @ %p, channel=%d, id=%d, lun=%d\n",
e80b002b
EM
2447 ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2448 if (ioc->bus_type == SPI)
2449 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c7c82987 2450 "sdtr %d wdtr %d ppr %d inq length=%d\n",
e80b002b 2451 ioc->name, sdev->sdtr, sdev->wdtr,
c7c82987
MED
2452 sdev->ppr, sdev->inquiry_len));
2453
2454 if (sdev->id > sh->max_id) {
1da177e4 2455 /* error case, should never happen */
c7c82987 2456 scsi_adjust_queue_depth(sdev, 0, 1);
1da177e4
LT
2457 goto slave_configure_exit;
2458 }
2459
793955f5 2460 vdevice->configured_lun = 1;
c7c82987 2461 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
1da177e4 2462
e80b002b 2463 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1da177e4 2464 "Queue depth=%d, tflags=%x\n",
e80b002b 2465 ioc->name, sdev->queue_depth, vtarget->tflags));
1da177e4 2466
e80b002b
EM
2467 if (ioc->bus_type == SPI)
2468 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c7c82987 2469 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
e80b002b 2470 ioc->name, vtarget->negoFlags, vtarget->maxOffset,
c7c82987 2471 vtarget->minSyncFactor));
1da177e4
LT
2472
2473slave_configure_exit:
2474
e80b002b 2475 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1da177e4 2476 "tagged %d, simple %d, ordered %d\n",
e80b002b 2477 ioc->name,sdev->tagged_supported, sdev->simple_tags,
c7c82987 2478 sdev->ordered_tags));
1da177e4
LT
2479
2480 return 0;
2481}
2482
1da177e4
LT
2483/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2484/*
2485 * Private routines...
2486 */
2487
2488/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2489/* Utility function to copy sense data from the scsi_cmnd buffer
2490 * to the FC and SCSI target structures.
2491 *
2492 */
2493static void
0d0c7974 2494mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
1da177e4 2495{
a69de507 2496 VirtDevice *vdevice;
1da177e4
LT
2497 SCSIIORequest_t *pReq;
2498 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
e80b002b 2499 MPT_ADAPTER *ioc = hd->ioc;
1da177e4
LT
2500
2501 /* Get target structure
2502 */
2503 pReq = (SCSIIORequest_t *) mf;
a69de507 2504 vdevice = sc->device->hostdata;
1da177e4
LT
2505
2506 if (sense_count) {
2507 u8 *sense_data;
2508 int req_index;
2509
2510 /* Copy the sense received into the scsi command block. */
2511 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
e80b002b 2512 sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
1da177e4
LT
2513 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2514
2515 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2516 */
e80b002b 2517 if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
a69de507 2518 if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) {
1da177e4 2519 int idx;
1da177e4 2520
5b5ef4f6 2521 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
1da177e4
LT
2522 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2523 ioc->events[idx].eventContext = ioc->eventContext;
2524
3d9780b9
DJ
2525 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2526 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2527 (sc->device->channel << 8) | sc->device->id;
1da177e4 2528
3d9780b9 2529 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
1da177e4
LT
2530
2531 ioc->eventContext++;
e80b002b 2532 if (ioc->pcidev->vendor ==
786899b0 2533 PCI_VENDOR_ID_IBM) {
e80b002b 2534 mptscsih_issue_sep_command(ioc,
a69de507
EM
2535 vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2536 vdevice->vtarget->tflags |=
786899b0
EM
2537 MPT_TARGET_FLAGS_LED_ON;
2538 }
1da177e4
LT
2539 }
2540 }
2541 } else {
e80b002b
EM
2542 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
2543 ioc->name));
1da177e4
LT
2544 }
2545}
2546
e8206381
EM
2547/**
2548 * mptscsih_get_scsi_lookup
e8206381
EM
2549 * @ioc: Pointer to MPT_ADAPTER structure
2550 * @i: index into the array
2551 *
7105a387 2552 * retrieves scmd entry from ScsiLookup[] array list
e8206381 2553 *
7105a387 2554 * Returns the scsi_cmd pointer
e8206381
EM
2555 **/
2556static struct scsi_cmnd *
2557mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
1da177e4 2558{
e8206381
EM
2559 unsigned long flags;
2560 struct scsi_cmnd *scmd;
2561
2562 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2563 scmd = ioc->ScsiLookup[i];
2564 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2565
2566 return scmd;
2567}
2568
2569/**
2570 * mptscsih_getclear_scsi_lookup
e8206381
EM
2571 * @ioc: Pointer to MPT_ADAPTER structure
2572 * @i: index into the array
2573 *
7105a387 2574 * retrieves and clears scmd entry from ScsiLookup[] array list
e8206381 2575 *
7105a387 2576 * Returns the scsi_cmd pointer
e8206381
EM
2577 **/
2578static struct scsi_cmnd *
2579mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
2580{
2581 unsigned long flags;
2582 struct scsi_cmnd *scmd;
2583
2584 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2585 scmd = ioc->ScsiLookup[i];
2586 ioc->ScsiLookup[i] = NULL;
2587 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2588
2589 return scmd;
2590}
2591
2592/**
2593 * mptscsih_set_scsi_lookup
2594 *
2595 * writes a scmd entry into the ScsiLookup[] array list
2596 *
2597 * @ioc: Pointer to MPT_ADAPTER structure
2598 * @i: index into the array
2599 * @scmd: scsi_cmnd pointer
2600 *
2601 **/
2602static void
2603mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
2604{
2605 unsigned long flags;
1da177e4 2606
e8206381
EM
2607 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2608 ioc->ScsiLookup[i] = scmd;
2609 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2610}
2611
2612/**
23f9b75e 2613 * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list
e8206381 2614 * @ioc: Pointer to MPT_ADAPTER structure
23f9b75e
RD
2615 * @sc: scsi_cmnd pointer
2616 */
e8206381
EM
2617static int
2618SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
2619{
2620 unsigned long flags;
2621 int i, index=-1;
1da177e4 2622
e8206381
EM
2623 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2624 for (i = 0; i < ioc->req_depth; i++) {
2625 if (ioc->ScsiLookup[i] == sc) {
2626 index = i;
2627 goto out;
1da177e4
LT
2628 }
2629 }
2630
e8206381
EM
2631 out:
2632 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2633 return index;
1da177e4
LT
2634}
2635
2636/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2637int
1da177e4
LT
2638mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2639{
2640 MPT_SCSI_HOST *hd;
2641 unsigned long flags;
2642
29dd3609
EM
2643 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2644 ": IOC %s_reset routed to SCSI host driver!\n",
2645 ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2646 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1da177e4
LT
2647
2648 /* If a FW reload request arrives after base installed but
2649 * before all scsi hosts have been attached, then an alt_ioc
2650 * may have a NULL sh pointer.
2651 */
e7eae9f6 2652 if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
1da177e4
LT
2653 return 0;
2654 else
e7eae9f6 2655 hd = shost_priv(ioc->sh);
1da177e4
LT
2656
2657 if (reset_phase == MPT_IOC_SETUP_RESET) {
6757d6b4 2658 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name));
1da177e4
LT
2659
2660 /* Clean Up:
2661 * 1. Set Hard Reset Pending Flag
2662 * All new commands go to doneQ
2663 */
2664 hd->resetPending = 1;
2665
2666 } else if (reset_phase == MPT_IOC_PRE_RESET) {
6757d6b4 2667 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name));
1da177e4
LT
2668
2669 /* 2. Flush running commands
2670 * Clean ScsiLookup (and associated memory)
2671 * AND clean mytaskQ
2672 */
2673
2674 /* 2b. Reply to OS all known outstanding I/O commands.
2675 */
2676 mptscsih_flush_running_cmds(hd);
2677
2678 /* 2c. If there was an internal command that
2679 * has not completed, configuration or io request,
2680 * free these resources.
2681 */
2682 if (hd->cmdPtr) {
2683 del_timer(&hd->timer);
2684 mpt_free_msg_frame(ioc, hd->cmdPtr);
2685 }
2686
6757d6b4 2687 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name));
1da177e4
LT
2688
2689 } else {
6757d6b4 2690 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name));
1da177e4
LT
2691
2692 /* Once a FW reload begins, all new OS commands are
2693 * redirected to the doneQ w/ a reset status.
2694 * Init all control structures.
2695 */
2696
1da177e4
LT
2697 /* 2. Chain Buffer initialization
2698 */
2699
a9b2937a 2700 /* 4. Renegotiate to all devices, if SPI
1da177e4 2701 */
1da177e4
LT
2702
2703 /* 5. Enable new commands to be posted
2704 */
2705 spin_lock_irqsave(&ioc->FreeQlock, flags);
2706 hd->tmPending = 0;
2707 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2708 hd->resetPending = 0;
2709 hd->tmState = TM_STATE_NONE;
2710
2711 /* 6. If there was an internal command,
2712 * wake this process up.
2713 */
2714 if (hd->cmdPtr) {
2715 /*
2716 * Wake up the original calling thread
2717 */
2718 hd->pLocal = &hd->localReply;
2719 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
0d0c7974
MED
2720 hd->scandv_wait_done = 1;
2721 wake_up(&hd->scandv_waitq);
1da177e4
LT
2722 hd->cmdPtr = NULL;
2723 }
2724
6757d6b4 2725 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name));
1da177e4
LT
2726
2727 }
2728
2729 return 1; /* currently means nothing really */
2730}
2731
2732/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2733int
1da177e4
LT
2734mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2735{
2736 MPT_SCSI_HOST *hd;
2737 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2738
6757d6b4 2739 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1da177e4
LT
2740 ioc->name, event));
2741
466544d8 2742 if (ioc->sh == NULL ||
e7eae9f6 2743 ((hd = shost_priv(ioc->sh)) == NULL))
466544d8
MED
2744 return 1;
2745
1da177e4
LT
2746 switch (event) {
2747 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2748 /* FIXME! */
2749 break;
2750 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2751 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
a9b2937a 2752 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
466544d8 2753 hd->soft_resets++;
1da177e4
LT
2754 break;
2755 case MPI_EVENT_LOGOUT: /* 09 */
2756 /* FIXME! */
2757 break;
2758
05e8ec17 2759 case MPI_EVENT_RESCAN: /* 06 */
05e8ec17
MR
2760 break;
2761
1da177e4
LT
2762 /*
2763 * CHECKME! Don't think we need to do
2764 * anything for these, but...
2765 */
1da177e4
LT
2766 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2767 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2768 /*
2769 * CHECKME! Falling thru...
2770 */
2771 break;
2772
2773 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
466544d8 2774 break;
1da177e4 2775
1da177e4
LT
2776 case MPI_EVENT_NONE: /* 00 */
2777 case MPI_EVENT_LOG_DATA: /* 01 */
2778 case MPI_EVENT_STATE_CHANGE: /* 02 */
2779 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2780 default:
29dd3609
EM
2781 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n",
2782 ioc->name, event));
1da177e4
LT
2783 break;
2784 }
2785
2786 return 1; /* currently means nothing really */
2787}
2788
1da177e4
LT
2789/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2790/*
2791 * Bus Scan and Domain Validation functionality ...
2792 */
2793
2794/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2795/*
2796 * mptscsih_scandv_complete - Scan and DV callback routine registered
2797 * to Fustion MPT (base) driver.
2798 *
2799 * @ioc: Pointer to MPT_ADAPTER structure
2800 * @mf: Pointer to original MPT request frame
2801 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2802 *
2803 * This routine is called from mpt.c::mpt_interrupt() at the completion
2804 * of any SCSI IO request.
2805 * This routine is registered with the Fusion MPT (base) driver at driver
2806 * load/init time via the mpt_register() API call.
2807 *
2808 * Returns 1 indicating alloc'd request frame ptr should be freed.
2809 *
2810 * Remark: Sets a completion code and (possibly) saves sense data
2811 * in the IOC member localReply structure.
2812 * Used ONLY for DV and other internal commands.
2813 */
0d0c7974 2814int
1da177e4
LT
2815mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2816{
2817 MPT_SCSI_HOST *hd;
2818 SCSIIORequest_t *pReq;
2819 int completionCode;
2820 u16 req_idx;
2821
e7eae9f6 2822 hd = shost_priv(ioc->sh);
0d0c7974 2823
1da177e4
LT
2824 if ((mf == NULL) ||
2825 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2826 printk(MYIOC_s_ERR_FMT
2827 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2828 ioc->name, mf?"BAD":"NULL", (void *) mf);
2829 goto wakeup;
2830 }
2831
1da177e4
LT
2832 del_timer(&hd->timer);
2833 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
e8206381 2834 mptscsih_set_scsi_lookup(ioc, req_idx, NULL);
1da177e4
LT
2835 pReq = (SCSIIORequest_t *) mf;
2836
2837 if (mf != hd->cmdPtr) {
2838 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
e80b002b 2839 ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
1da177e4
LT
2840 }
2841 hd->cmdPtr = NULL;
2842
6757d6b4 2843 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
e80b002b 2844 ioc->name, mf, mr, req_idx));
1da177e4
LT
2845
2846 hd->pLocal = &hd->localReply;
2847 hd->pLocal->scsiStatus = 0;
2848
2849 /* If target struct exists, clear sense valid flag.
2850 */
2851 if (mr == NULL) {
2852 completionCode = MPT_SCANDV_GOOD;
2853 } else {
2854 SCSIIOReply_t *pReply;
2855 u16 status;
2856 u8 scsi_status;
2857
2858 pReply = (SCSIIOReply_t *) mr;
2859
2860 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2861 scsi_status = pReply->SCSIStatus;
2862
1da177e4
LT
2863
2864 switch(status) {
2865
2866 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2867 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
2868 break;
2869
2870 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2871 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2872 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2873 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2874 completionCode = MPT_SCANDV_DID_RESET;
2875 break;
2876
2877 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2878 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2879 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2880 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2881 ConfigReply_t *pr = (ConfigReply_t *)mr;
2882 completionCode = MPT_SCANDV_GOOD;
2883 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2884 hd->pLocal->header.PageLength = pr->Header.PageLength;
2885 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2886 hd->pLocal->header.PageType = pr->Header.PageType;
2887
2888 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2889 /* If the RAID Volume request is successful,
2890 * return GOOD, else indicate that
2891 * some type of error occurred.
2892 */
2893 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
637fa99b 2894 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
1da177e4
LT
2895 completionCode = MPT_SCANDV_GOOD;
2896 else
2897 completionCode = MPT_SCANDV_SOME_ERROR;
c92f222e 2898 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
1da177e4
LT
2899
2900 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2901 u8 *sense_data;
2902 int sz;
2903
2904 /* save sense data in global structure
2905 */
2906 completionCode = MPT_SCANDV_SENSE;
2907 hd->pLocal->scsiStatus = scsi_status;
e80b002b 2908 sense_data = ((u8 *)ioc->sense_buf_pool +
1da177e4
LT
2909 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2910
2911 sz = min_t(int, pReq->SenseBufferLength,
2912 SCSI_STD_SENSE_BYTES);
2913 memcpy(hd->pLocal->sense, sense_data, sz);
2914
29dd3609
EM
2915 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Check Condition, sense ptr %p\n",
2916 ioc->name, sense_data));
1da177e4
LT
2917 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2918 if (pReq->CDB[0] == INQUIRY)
2919 completionCode = MPT_SCANDV_ISSUE_SENSE;
2920 else
2921 completionCode = MPT_SCANDV_DID_RESET;
2922 }
2923 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2924 completionCode = MPT_SCANDV_DID_RESET;
2925 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2926 completionCode = MPT_SCANDV_DID_RESET;
2927 else {
2928 completionCode = MPT_SCANDV_GOOD;
2929 hd->pLocal->scsiStatus = scsi_status;
2930 }
2931 break;
2932
2933 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2934 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2935 completionCode = MPT_SCANDV_DID_RESET;
2936 else
2937 completionCode = MPT_SCANDV_SOME_ERROR;
2938 break;
2939
2940 default:
2941 completionCode = MPT_SCANDV_SOME_ERROR;
2942 break;
2943
2944 } /* switch(status) */
2945
1da177e4
LT
2946 } /* end of address reply case */
2947
2948 hd->pLocal->completion = completionCode;
2949
2950 /* MF and RF are freed in mpt_interrupt
2951 */
2952wakeup:
2953 /* Free Chain buffers (will never chain) in scan or dv */
2954 //mptscsih_freeChainBuffers(ioc, req_idx);
2955
2956 /*
2957 * Wake up the original calling thread
2958 */
0d0c7974
MED
2959 hd->scandv_wait_done = 1;
2960 wake_up(&hd->scandv_waitq);
1da177e4
LT
2961
2962 return 1;
2963}
2964
2965/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2966/* mptscsih_timer_expired - Call back for timer process.
2967 * Used only for dv functionality.
2968 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2969 *
2970 */
0d0c7974
MED
2971void
2972mptscsih_timer_expired(unsigned long data)
1da177e4
LT
2973{
2974 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
e80b002b 2975 MPT_ADAPTER *ioc = hd->ioc;
1da177e4 2976
e80b002b 2977 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", ioc->name, hd->cmdPtr));
1da177e4
LT
2978
2979 if (hd->cmdPtr) {
2980 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2981
2982 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2983 /* Desire to issue a task management request here.
2984 * TM requests MUST be single threaded.
2985 * If old eh code and no TM current, issue request.
2986 * If new eh code, do nothing. Wait for OS cmd timeout
2987 * for bus reset.
2988 */
1da177e4
LT
2989 } else {
2990 /* Perform a FW reload */
e80b002b
EM
2991 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2992 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
1da177e4
LT
2993 }
2994 }
2995 } else {
2996 /* This should NEVER happen */
e80b002b 2997 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", ioc->name);
1da177e4
LT
2998 }
2999
3000 /* No more processing.
3001 * TM call will generate an interrupt for SCSI TM Management.
3002 * The FW will reply to all outstanding commands, callback will finish cleanup.
3003 * Hard reset clean-up will free all resources.
3004 */
e80b002b 3005 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", ioc->name));
1da177e4
LT
3006
3007 return;
3008}
3009
1da177e4
LT
3010
3011/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3012/**
3013 * mptscsih_do_cmd - Do internal command.
3014 * @hd: MPT_SCSI_HOST pointer
3015 * @io: INTERNAL_CMD pointer.
3016 *
3017 * Issue the specified internally generated command and do command
3018 * specific cleanup. For bus scan / DV only.
3019 * NOTES: If command is Inquiry and status is good,
3020 * initialize a target structure, save the data
3021 *
3022 * Remark: Single threaded access only.
3023 *
3024 * Return:
3025 * < 0 if an illegal command or no resources
3026 *
3027 * 0 if good
3028 *
3029 * > 0 if command complete but some type of completion error.
3030 */
3031static int
3032mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3033{
3034 MPT_FRAME_HDR *mf;
3035 SCSIIORequest_t *pScsiReq;
3036 SCSIIORequest_t ReqCopy;
3037 int my_idx, ii, dir;
3038 int rc, cmdTimeout;
3039 int in_isr;
3040 char cmdLen;
3041 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3042 char cmd = io->cmd;
e80b002b 3043 MPT_ADAPTER *ioc = hd->ioc;
1da177e4
LT
3044
3045 in_isr = in_interrupt();
3046 if (in_isr) {
e80b002b
EM
3047 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3048 ioc->name));
1da177e4
LT
3049 return -EPERM;
3050 }
3051
3052
3053 /* Set command specific information
3054 */
3055 switch (cmd) {
3056 case INQUIRY:
3057 cmdLen = 6;
3058 dir = MPI_SCSIIO_CONTROL_READ;
3059 CDB[0] = cmd;
3060 CDB[4] = io->size;
3061 cmdTimeout = 10;
3062 break;
3063
3064 case TEST_UNIT_READY:
3065 cmdLen = 6;
3066 dir = MPI_SCSIIO_CONTROL_READ;
3067 cmdTimeout = 10;
3068 break;
3069
3070 case START_STOP:
3071 cmdLen = 6;
3072 dir = MPI_SCSIIO_CONTROL_READ;
3073 CDB[0] = cmd;
3074 CDB[4] = 1; /*Spin up the disk */
3075 cmdTimeout = 15;
3076 break;
3077
3078 case REQUEST_SENSE:
3079 cmdLen = 6;
3080 CDB[0] = cmd;
3081 CDB[4] = io->size;
3082 dir = MPI_SCSIIO_CONTROL_READ;
3083 cmdTimeout = 10;
3084 break;
3085
3086 case READ_BUFFER:
3087 cmdLen = 10;
3088 dir = MPI_SCSIIO_CONTROL_READ;
3089 CDB[0] = cmd;
3090 if (io->flags & MPT_ICFLAG_ECHO) {
3091 CDB[1] = 0x0A;
3092 } else {
3093 CDB[1] = 0x02;
3094 }
3095
3096 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3097 CDB[1] |= 0x01;
3098 }
3099 CDB[6] = (io->size >> 16) & 0xFF;
3100 CDB[7] = (io->size >> 8) & 0xFF;
3101 CDB[8] = io->size & 0xFF;
3102 cmdTimeout = 10;
3103 break;
3104
3105 case WRITE_BUFFER:
3106 cmdLen = 10;
3107 dir = MPI_SCSIIO_CONTROL_WRITE;
3108 CDB[0] = cmd;
3109 if (io->flags & MPT_ICFLAG_ECHO) {
3110 CDB[1] = 0x0A;
3111 } else {
3112 CDB[1] = 0x02;
3113 }
3114 CDB[6] = (io->size >> 16) & 0xFF;
3115 CDB[7] = (io->size >> 8) & 0xFF;
3116 CDB[8] = io->size & 0xFF;
3117 cmdTimeout = 10;
3118 break;
3119
3120 case RESERVE:
3121 cmdLen = 6;
3122 dir = MPI_SCSIIO_CONTROL_READ;
3123 CDB[0] = cmd;
3124 cmdTimeout = 10;
3125 break;
3126
3127 case RELEASE:
3128 cmdLen = 6;
3129 dir = MPI_SCSIIO_CONTROL_READ;
3130 CDB[0] = cmd;
3131 cmdTimeout = 10;
3132 break;
3133
3134 case SYNCHRONIZE_CACHE:
3135 cmdLen = 10;
3136 dir = MPI_SCSIIO_CONTROL_READ;
3137 CDB[0] = cmd;
3138// CDB[1] = 0x02; /* set immediate bit */
3139 cmdTimeout = 10;
3140 break;
3141
3142 default:
3143 /* Error Case */
3144 return -EFAULT;
3145 }
3146
3147 /* Get and Populate a free Frame
3148 */
e80b002b
EM
3149 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
3150 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n",
3151 ioc->name));
1da177e4
LT
3152 return -EBUSY;
3153 }
3154
3155 pScsiReq = (SCSIIORequest_t *) mf;
3156
3157 /* Get the request index */
3158 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3159 ADD_INDEX_LOG(my_idx); /* for debug */
3160
3161 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3162 pScsiReq->TargetID = io->physDiskNum;
3163 pScsiReq->Bus = 0;
3164 pScsiReq->ChainOffset = 0;
3165 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3166 } else {
3167 pScsiReq->TargetID = io->id;
793955f5 3168 pScsiReq->Bus = io->channel;
1da177e4
LT
3169 pScsiReq->ChainOffset = 0;
3170 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3171 }
3172
3173 pScsiReq->CDBLength = cmdLen;
3174 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3175
3176 pScsiReq->Reserved = 0;
3177
3178 pScsiReq->MsgFlags = mpt_msg_flags();
3179 /* MsgContext set in mpt_get_msg_fram call */
3180
793955f5 3181 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
1da177e4
LT
3182
3183 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3184 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3185 else
3186 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3187
3188 if (cmd == REQUEST_SENSE) {
3189 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
e80b002b
EM
3190 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n",
3191 ioc->name, cmd));
1da177e4
LT
3192 }
3193
3194 for (ii=0; ii < 16; ii++)
3195 pScsiReq->CDB[ii] = CDB[ii];
3196
3197 pScsiReq->DataLength = cpu_to_le32(io->size);
e80b002b 3198 pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
1da177e4
LT
3199 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3200
e80b002b
EM
3201 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3202 ioc->name, cmd, io->channel, io->id, io->lun));
1da177e4
LT
3203
3204 if (dir == MPI_SCSIIO_CONTROL_READ) {
3205 mpt_add_sge((char *) &pScsiReq->SGL,
3206 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3207 io->data_dma);
3208 } else {
3209 mpt_add_sge((char *) &pScsiReq->SGL,
3210 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3211 io->data_dma);
3212 }
3213
3214 /* The ISR will free the request frame, but we need
3215 * the information to initialize the target. Duplicate.
3216 */
3217 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3218
3219 /* Issue this command after:
3220 * finish init
3221 * add timer
3222 * Wait until the reply has been received
3223 * ScsiScanDvCtx callback function will
3224 * set hd->pLocal;
3225 * set scandv_wait_done and call wake_up
3226 */
3227 hd->pLocal = NULL;
3228 hd->timer.expires = jiffies + HZ*cmdTimeout;
0d0c7974 3229 hd->scandv_wait_done = 0;
1da177e4
LT
3230
3231 /* Save cmd pointer, for resource free if timeout or
3232 * FW reload occurs
3233 */
3234 hd->cmdPtr = mf;
3235
3236 add_timer(&hd->timer);
e80b002b 3237 mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
0d0c7974 3238 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
1da177e4
LT
3239
3240 if (hd->pLocal) {
3241 rc = hd->pLocal->completion;
3242 hd->pLocal->skip = 0;
3243
3244 /* Always set fatal error codes in some cases.
3245 */
3246 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3247 rc = -ENXIO;
3248 else if (rc == MPT_SCANDV_SOME_ERROR)
3249 rc = -rc;
3250 } else {
3251 rc = -EFAULT;
3252 /* This should never happen. */
e80b002b
EM
3253 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n",
3254 ioc->name));
1da177e4
LT
3255 }
3256
3257 return rc;
3258}
3259
c7c82987
MED
3260/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3261/**
3262 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3263 * @hd: Pointer to a SCSI HOST structure
d9489fb6 3264 * @vdevice: virtual target device
c7c82987
MED
3265 *
3266 * Uses the ISR, but with special processing.
3267 * MUST be single-threaded.
3268 *
3269 */
3270static void
3271mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3272{
3273 INTERNAL_CMD iocmd;
1da177e4 3274
cc78d30a
EM
3275 /* Ignore hidden raid components, this is handled when the command
3276 * is sent to the volume
3277 */
3278 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
3279 return;
3280
3281 if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
3282 !vdevice->configured_lun)
3283 return;
3284
c7c82987
MED
3285 /* Following parameters will not change
3286 * in this routine.
3287 */
3288 iocmd.cmd = SYNCHRONIZE_CACHE;
3289 iocmd.flags = 0;
3290 iocmd.physDiskNum = -1;
3291 iocmd.data = NULL;
3292 iocmd.data_dma = -1;
3293 iocmd.size = 0;
3294 iocmd.rsvd = iocmd.rsvd2 = 0;
793955f5
EM
3295 iocmd.channel = vdevice->vtarget->channel;
3296 iocmd.id = vdevice->vtarget->id;
3297 iocmd.lun = vdevice->lun;
1da177e4 3298
cc78d30a 3299 mptscsih_do_cmd(hd, &iocmd);
1da177e4
LT
3300}
3301
edb9068d 3302static ssize_t
ee959b00
TJ
3303mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
3304 char *buf)
edb9068d 3305{
ee959b00 3306 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3307 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3308 MPT_ADAPTER *ioc = hd->ioc;
3309
3310 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
3311 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
3312 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
3313 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
3314 ioc->facts.FWVersion.Word & 0x000000FF);
3315}
ee959b00 3316static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
edb9068d
PS
3317
3318static ssize_t
ee959b00
TJ
3319mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr,
3320 char *buf)
edb9068d 3321{
ee959b00 3322 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3323 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3324 MPT_ADAPTER *ioc = hd->ioc;
3325
3326 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
3327 (ioc->biosVersion & 0xFF000000) >> 24,
3328 (ioc->biosVersion & 0x00FF0000) >> 16,
3329 (ioc->biosVersion & 0x0000FF00) >> 8,
3330 ioc->biosVersion & 0x000000FF);
3331}
ee959b00 3332static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
edb9068d
PS
3333
3334static ssize_t
ee959b00
TJ
3335mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr,
3336 char *buf)
edb9068d 3337{
ee959b00 3338 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3339 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3340 MPT_ADAPTER *ioc = hd->ioc;
3341
3342 return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
3343}
ee959b00 3344static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
edb9068d
PS
3345
3346static ssize_t
ee959b00
TJ
3347mptscsih_version_product_show(struct device *dev,
3348 struct device_attribute *attr,
3349char *buf)
edb9068d 3350{
ee959b00 3351 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3352 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3353 MPT_ADAPTER *ioc = hd->ioc;
3354
3355 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
3356}
ee959b00 3357static DEVICE_ATTR(version_product, S_IRUGO,
edb9068d
PS
3358 mptscsih_version_product_show, NULL);
3359
3360static ssize_t
ee959b00
TJ
3361mptscsih_version_nvdata_persistent_show(struct device *dev,
3362 struct device_attribute *attr,
3363 char *buf)
edb9068d 3364{
ee959b00 3365 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3366 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3367 MPT_ADAPTER *ioc = hd->ioc;
3368
3369 return snprintf(buf, PAGE_SIZE, "%02xh\n",
3370 ioc->nvdata_version_persistent);
3371}
ee959b00 3372static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
edb9068d
PS
3373 mptscsih_version_nvdata_persistent_show, NULL);
3374
3375static ssize_t
ee959b00
TJ
3376mptscsih_version_nvdata_default_show(struct device *dev,
3377 struct device_attribute *attr, char *buf)
edb9068d 3378{
ee959b00 3379 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3380 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3381 MPT_ADAPTER *ioc = hd->ioc;
3382
3383 return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
3384}
ee959b00 3385static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
edb9068d
PS
3386 mptscsih_version_nvdata_default_show, NULL);
3387
3388static ssize_t
ee959b00
TJ
3389mptscsih_board_name_show(struct device *dev, struct device_attribute *attr,
3390 char *buf)
edb9068d 3391{
ee959b00 3392 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3393 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3394 MPT_ADAPTER *ioc = hd->ioc;
3395
3396 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
3397}
ee959b00 3398static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
edb9068d
PS
3399
3400static ssize_t
ee959b00
TJ
3401mptscsih_board_assembly_show(struct device *dev,
3402 struct device_attribute *attr, char *buf)
edb9068d 3403{
ee959b00 3404 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3405 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3406 MPT_ADAPTER *ioc = hd->ioc;
3407
3408 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
3409}
ee959b00 3410static DEVICE_ATTR(board_assembly, S_IRUGO,
edb9068d
PS
3411 mptscsih_board_assembly_show, NULL);
3412
3413static ssize_t
ee959b00
TJ
3414mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr,
3415 char *buf)
edb9068d 3416{
ee959b00 3417 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3418 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3419 MPT_ADAPTER *ioc = hd->ioc;
3420
3421 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
3422}
ee959b00 3423static DEVICE_ATTR(board_tracer, S_IRUGO,
edb9068d
PS
3424 mptscsih_board_tracer_show, NULL);
3425
3426static ssize_t
ee959b00
TJ
3427mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr,
3428 char *buf)
edb9068d 3429{
ee959b00 3430 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3431 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3432 MPT_ADAPTER *ioc = hd->ioc;
3433
3434 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
3435}
ee959b00 3436static DEVICE_ATTR(io_delay, S_IRUGO,
edb9068d
PS
3437 mptscsih_io_delay_show, NULL);
3438
3439static ssize_t
ee959b00
TJ
3440mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr,
3441 char *buf)
edb9068d 3442{
ee959b00 3443 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3444 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3445 MPT_ADAPTER *ioc = hd->ioc;
3446
3447 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
3448}
ee959b00 3449static DEVICE_ATTR(device_delay, S_IRUGO,
edb9068d
PS
3450 mptscsih_device_delay_show, NULL);
3451
6757d6b4 3452static ssize_t
ee959b00
TJ
3453mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr,
3454 char *buf)
6757d6b4 3455{
ee959b00 3456 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3457 MPT_SCSI_HOST *hd = shost_priv(host);
6757d6b4
PS
3458 MPT_ADAPTER *ioc = hd->ioc;
3459
3460 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
3461}
3462static ssize_t
ee959b00
TJ
3463mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr,
3464 const char *buf, size_t count)
6757d6b4 3465{
ee959b00 3466 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3467 MPT_SCSI_HOST *hd = shost_priv(host);
6757d6b4
PS
3468 MPT_ADAPTER *ioc = hd->ioc;
3469 int val = 0;
3470
3471 if (sscanf(buf, "%x", &val) != 1)
3472 return -EINVAL;
3473
3474 ioc->debug_level = val;
3475 printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
3476 ioc->name, ioc->debug_level);
3477 return strlen(buf);
3478}
ee959b00
TJ
3479static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
3480 mptscsih_debug_level_show, mptscsih_debug_level_store);
3481
3482struct device_attribute *mptscsih_host_attrs[] = {
3483 &dev_attr_version_fw,
3484 &dev_attr_version_bios,
3485 &dev_attr_version_mpi,
3486 &dev_attr_version_product,
3487 &dev_attr_version_nvdata_persistent,
3488 &dev_attr_version_nvdata_default,
3489 &dev_attr_board_name,
3490 &dev_attr_board_assembly,
3491 &dev_attr_board_tracer,
3492 &dev_attr_io_delay,
3493 &dev_attr_device_delay,
3494 &dev_attr_debug_level,
edb9068d
PS
3495 NULL,
3496};
3497EXPORT_SYMBOL(mptscsih_host_attrs);
3498
0d0c7974
MED
3499EXPORT_SYMBOL(mptscsih_remove);
3500EXPORT_SYMBOL(mptscsih_shutdown);
3501#ifdef CONFIG_PM
3502EXPORT_SYMBOL(mptscsih_suspend);
3503EXPORT_SYMBOL(mptscsih_resume);
3504#endif
3505EXPORT_SYMBOL(mptscsih_proc_info);
3506EXPORT_SYMBOL(mptscsih_info);
3507EXPORT_SYMBOL(mptscsih_qcmd);
0d0c7974
MED
3508EXPORT_SYMBOL(mptscsih_slave_destroy);
3509EXPORT_SYMBOL(mptscsih_slave_configure);
3510EXPORT_SYMBOL(mptscsih_abort);
3511EXPORT_SYMBOL(mptscsih_dev_reset);
3512EXPORT_SYMBOL(mptscsih_bus_reset);
3513EXPORT_SYMBOL(mptscsih_host_reset);
3514EXPORT_SYMBOL(mptscsih_bios_param);
3515EXPORT_SYMBOL(mptscsih_io_done);
3516EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3517EXPORT_SYMBOL(mptscsih_scandv_complete);
3518EXPORT_SYMBOL(mptscsih_event_process);
3519EXPORT_SYMBOL(mptscsih_ioc_reset);
6e3815ba 3520EXPORT_SYMBOL(mptscsih_change_queue_depth);
0d0c7974 3521EXPORT_SYMBOL(mptscsih_timer_expired);
663e1aa1 3522EXPORT_SYMBOL(mptscsih_TMHandler);
1da177e4 3523
0d0c7974 3524/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/