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