2 * linux/drivers/message/fusion/mptbase.c
3 * This is the Fusion MPT base driver which supports multiple
4 * (SCSI + LAN) specialized protocol drivers.
5 * For use with LSI PCI chip/adapter(s)
6 * running LSI Fusion MPT (Message Passing Technology) firmware.
8 * Copyright (c) 1999-2008 LSI Corporation
9 * (mailto:DL-MPTFusionLinux@lsi.com)
12 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; version 2 of the License.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
24 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
25 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
26 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
27 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
28 solely responsible for determining the appropriateness of using and
29 distributing the Program and assumes all risks associated with its
30 exercise of rights under this Agreement, including but not limited to
31 the risks and costs of program errors, damage to or loss of data,
32 programs or equipment, and unavailability or interruption of operations.
34 DISCLAIMER OF LIABILITY
35 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
38 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
40 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
41 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
43 You should have received a copy of the GNU General Public License
44 along with this program; if not, write to the Free Software
45 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
49 #include <linux/kernel.h>
50 #include <linux/module.h>
51 #include <linux/errno.h>
52 #include <linux/init.h>
53 #include <linux/slab.h>
54 #include <linux/types.h>
55 #include <linux/pci.h>
56 #include <linux/kdev_t.h>
57 #include <linux/blkdev.h>
58 #include <linux/delay.h>
59 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
60 #include <linux/dma-mapping.h>
67 #include "lsi/mpi_log_fc.h"
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME "Fusion MPT base driver"
71 #define my_VERSION MPT_LINUX_VERSION_COMMON
72 #define MYNAM "mptbase"
74 MODULE_AUTHOR(MODULEAUTHOR
);
75 MODULE_DESCRIPTION(my_NAME
);
76 MODULE_LICENSE("GPL");
77 MODULE_VERSION(my_VERSION
);
83 static int mpt_msi_enable_spi
;
84 module_param(mpt_msi_enable_spi
, int, 0);
85 MODULE_PARM_DESC(mpt_msi_enable_spi
, " Enable MSI Support for SPI \
86 controllers (default=0)");
88 static int mpt_msi_enable_fc
;
89 module_param(mpt_msi_enable_fc
, int, 0);
90 MODULE_PARM_DESC(mpt_msi_enable_fc
, " Enable MSI Support for FC \
91 controllers (default=0)");
93 static int mpt_msi_enable_sas
;
94 module_param(mpt_msi_enable_sas
, int, 0);
95 MODULE_PARM_DESC(mpt_msi_enable_sas
, " Enable MSI Support for SAS \
96 controllers (default=0)");
99 static int mpt_channel_mapping
;
100 module_param(mpt_channel_mapping
, int, 0);
101 MODULE_PARM_DESC(mpt_channel_mapping
, " Mapping id's to channels (default=0)");
103 static int mpt_debug_level
;
104 static int mpt_set_debug_level(const char *val
, struct kernel_param
*kp
);
105 module_param_call(mpt_debug_level
, mpt_set_debug_level
, param_get_int
,
106 &mpt_debug_level
, 0600);
107 MODULE_PARM_DESC(mpt_debug_level
, " debug level - refer to mptdebug.h \
110 int mpt_fwfault_debug
;
111 EXPORT_SYMBOL(mpt_fwfault_debug
);
112 module_param_call(mpt_fwfault_debug
, param_set_int
, param_get_int
,
113 &mpt_fwfault_debug
, 0600);
114 MODULE_PARM_DESC(mpt_fwfault_debug
, "Enable detection of Firmware fault"
115 " and halt Firmware on fault - (default=0)");
120 static int mfcounter
= 0;
121 #define PRINT_MF_COUNT 20000
124 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
129 static struct proc_dir_entry
*mpt_proc_root_dir
;
131 #define WHOINIT_UNKNOWN 0xAA
133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
137 /* Adapter link list */
139 /* Callback lookup table */
140 static MPT_CALLBACK MptCallbacks
[MPT_MAX_PROTOCOL_DRIVERS
];
141 /* Protocol driver class lookup table */
142 static int MptDriverClass
[MPT_MAX_PROTOCOL_DRIVERS
];
143 /* Event handler lookup table */
144 static MPT_EVHANDLER MptEvHandlers
[MPT_MAX_PROTOCOL_DRIVERS
];
145 /* Reset handler lookup table */
146 static MPT_RESETHANDLER MptResetHandlers
[MPT_MAX_PROTOCOL_DRIVERS
];
147 static struct mpt_pci_driver
*MptDeviceDriverHandlers
[MPT_MAX_PROTOCOL_DRIVERS
];
149 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq
);
152 * Driver Callback Index's
154 static u8 mpt_base_index
= MPT_MAX_PROTOCOL_DRIVERS
;
155 static u8 last_drv_idx
;
157 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
161 static irqreturn_t
mpt_interrupt(int irq
, void *bus_id
);
162 static int mpt_base_reply(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*req
, MPT_FRAME_HDR
*reply
);
163 static int mpt_handshake_req_reply_wait(MPT_ADAPTER
*ioc
, int reqBytes
,
164 u32
*req
, int replyBytes
, u16
*u16reply
, int maxwait
,
166 static int mpt_do_ioc_recovery(MPT_ADAPTER
*ioc
, u32 reason
, int sleepFlag
);
167 static void mpt_detect_bound_ports(MPT_ADAPTER
*ioc
, struct pci_dev
*pdev
);
168 static void mpt_adapter_disable(MPT_ADAPTER
*ioc
);
169 static void mpt_adapter_dispose(MPT_ADAPTER
*ioc
);
171 static void MptDisplayIocCapabilities(MPT_ADAPTER
*ioc
);
172 static int MakeIocReady(MPT_ADAPTER
*ioc
, int force
, int sleepFlag
);
173 static int GetIocFacts(MPT_ADAPTER
*ioc
, int sleepFlag
, int reason
);
174 static int GetPortFacts(MPT_ADAPTER
*ioc
, int portnum
, int sleepFlag
);
175 static int SendIocInit(MPT_ADAPTER
*ioc
, int sleepFlag
);
176 static int SendPortEnable(MPT_ADAPTER
*ioc
, int portnum
, int sleepFlag
);
177 static int mpt_do_upload(MPT_ADAPTER
*ioc
, int sleepFlag
);
178 static int mpt_downloadboot(MPT_ADAPTER
*ioc
, MpiFwHeader_t
*pFwHeader
, int sleepFlag
);
179 static int mpt_diag_reset(MPT_ADAPTER
*ioc
, int ignore
, int sleepFlag
);
180 static int KickStart(MPT_ADAPTER
*ioc
, int ignore
, int sleepFlag
);
181 static int SendIocReset(MPT_ADAPTER
*ioc
, u8 reset_type
, int sleepFlag
);
182 static int PrimeIocFifos(MPT_ADAPTER
*ioc
);
183 static int WaitForDoorbellAck(MPT_ADAPTER
*ioc
, int howlong
, int sleepFlag
);
184 static int WaitForDoorbellInt(MPT_ADAPTER
*ioc
, int howlong
, int sleepFlag
);
185 static int WaitForDoorbellReply(MPT_ADAPTER
*ioc
, int howlong
, int sleepFlag
);
186 static int GetLanConfigPages(MPT_ADAPTER
*ioc
);
187 static int GetIoUnitPage2(MPT_ADAPTER
*ioc
);
188 int mptbase_sas_persist_operation(MPT_ADAPTER
*ioc
, u8 persist_opcode
);
189 static int mpt_GetScsiPortSettings(MPT_ADAPTER
*ioc
, int portnum
);
190 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER
*ioc
, int portnum
);
191 static void mpt_read_ioc_pg_1(MPT_ADAPTER
*ioc
);
192 static void mpt_read_ioc_pg_4(MPT_ADAPTER
*ioc
);
193 static void mpt_timer_expired(unsigned long data
);
194 static void mpt_get_manufacturing_pg_0(MPT_ADAPTER
*ioc
);
195 static int SendEventNotification(MPT_ADAPTER
*ioc
, u8 EvSwitch
);
196 static int SendEventAck(MPT_ADAPTER
*ioc
, EventNotificationReply_t
*evnp
);
197 static int mpt_host_page_access_control(MPT_ADAPTER
*ioc
, u8 access_control_value
, int sleepFlag
);
198 static int mpt_host_page_alloc(MPT_ADAPTER
*ioc
, pIOCInit_t ioc_init
);
200 #ifdef CONFIG_PROC_FS
201 static int procmpt_summary_read(char *buf
, char **start
, off_t offset
,
202 int request
, int *eof
, void *data
);
203 static int procmpt_version_read(char *buf
, char **start
, off_t offset
,
204 int request
, int *eof
, void *data
);
205 static int procmpt_iocinfo_read(char *buf
, char **start
, off_t offset
,
206 int request
, int *eof
, void *data
);
208 static void mpt_get_fw_exp_ver(char *buf
, MPT_ADAPTER
*ioc
);
210 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
211 static int ProcessEventNotification(MPT_ADAPTER
*ioc
, EventNotificationReply_t
*evReply
, int *evHandlers
);
212 static void mpt_iocstatus_info(MPT_ADAPTER
*ioc
, u32 ioc_status
, MPT_FRAME_HDR
*mf
);
213 static void mpt_fc_log_info(MPT_ADAPTER
*ioc
, u32 log_info
);
214 static void mpt_spi_log_info(MPT_ADAPTER
*ioc
, u32 log_info
);
215 static void mpt_sas_log_info(MPT_ADAPTER
*ioc
, u32 log_info
);
216 static int mpt_read_ioc_pg_3(MPT_ADAPTER
*ioc
);
217 static void mpt_inactive_raid_list_free(MPT_ADAPTER
*ioc
);
219 /* module entry point */
220 static int __init
fusion_init (void);
221 static void __exit
fusion_exit (void);
223 #define CHIPREG_READ32(addr) readl_relaxed(addr)
224 #define CHIPREG_READ32_dmasync(addr) readl(addr)
225 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
226 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
227 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
230 pci_disable_io_access(struct pci_dev
*pdev
)
234 pci_read_config_word(pdev
, PCI_COMMAND
, &command_reg
);
236 pci_write_config_word(pdev
, PCI_COMMAND
, command_reg
);
240 pci_enable_io_access(struct pci_dev
*pdev
)
244 pci_read_config_word(pdev
, PCI_COMMAND
, &command_reg
);
246 pci_write_config_word(pdev
, PCI_COMMAND
, command_reg
);
249 static int mpt_set_debug_level(const char *val
, struct kernel_param
*kp
)
251 int ret
= param_set_int(val
, kp
);
257 list_for_each_entry(ioc
, &ioc_list
, list
)
258 ioc
->debug_level
= mpt_debug_level
;
263 * mpt_get_cb_idx - obtain cb_idx for registered driver
264 * @dclass: class driver enum
266 * Returns cb_idx, or zero means it wasn't found
269 mpt_get_cb_idx(MPT_DRIVER_CLASS dclass
)
273 for (cb_idx
= MPT_MAX_PROTOCOL_DRIVERS
-1; cb_idx
; cb_idx
--)
274 if (MptDriverClass
[cb_idx
] == dclass
)
280 * mpt_fault_reset_work - work performed on workq after ioc fault
281 * @work: input argument, used to derive ioc
285 mpt_fault_reset_work(struct work_struct
*work
)
288 container_of(work
, MPT_ADAPTER
, fault_reset_work
.work
);
293 if (ioc
->diagPending
|| !ioc
->active
)
296 ioc_raw_state
= mpt_GetIocState(ioc
, 0);
297 if ((ioc_raw_state
& MPI_IOC_STATE_MASK
) == MPI_IOC_STATE_FAULT
) {
298 printk(MYIOC_s_WARN_FMT
"IOC is in FAULT state (%04xh)!!!\n",
299 ioc
->name
, ioc_raw_state
& MPI_DOORBELL_DATA_MASK
);
300 printk(MYIOC_s_WARN_FMT
"Issuing HardReset from %s!!\n",
301 ioc
->name
, __func__
);
302 rc
= mpt_HardResetHandler(ioc
, CAN_SLEEP
);
303 printk(MYIOC_s_WARN_FMT
"%s: HardReset: %s\n", ioc
->name
,
304 __func__
, (rc
== 0) ? "success" : "failed");
305 ioc_raw_state
= mpt_GetIocState(ioc
, 0);
306 if ((ioc_raw_state
& MPI_IOC_STATE_MASK
) == MPI_IOC_STATE_FAULT
)
307 printk(MYIOC_s_WARN_FMT
"IOC is in FAULT state after "
308 "reset (%04xh)\n", ioc
->name
, ioc_raw_state
&
309 MPI_DOORBELL_DATA_MASK
);
314 * Take turns polling alternate controller
319 /* rearm the timer */
320 spin_lock_irqsave(&ioc
->fault_reset_work_lock
, flags
);
321 if (ioc
->reset_work_q
)
322 queue_delayed_work(ioc
->reset_work_q
, &ioc
->fault_reset_work
,
323 msecs_to_jiffies(MPT_POLLING_INTERVAL
));
324 spin_unlock_irqrestore(&ioc
->fault_reset_work_lock
, flags
);
329 * Process turbo (context) reply...
332 mpt_turbo_reply(MPT_ADAPTER
*ioc
, u32 pa
)
334 MPT_FRAME_HDR
*mf
= NULL
;
335 MPT_FRAME_HDR
*mr
= NULL
;
339 dmfprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Got TURBO reply req_idx=%08x\n",
342 switch (pa
>> MPI_CONTEXT_REPLY_TYPE_SHIFT
) {
343 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT
:
344 req_idx
= pa
& 0x0000FFFF;
345 cb_idx
= (pa
& 0x00FF0000) >> 16;
346 mf
= MPT_INDEX_2_MFPTR(ioc
, req_idx
);
348 case MPI_CONTEXT_REPLY_TYPE_LAN
:
349 cb_idx
= mpt_get_cb_idx(MPTLAN_DRIVER
);
351 * Blind set of mf to NULL here was fatal
352 * after lan_reply says "freeme"
353 * Fix sort of combined with an optimization here;
354 * added explicit check for case where lan_reply
355 * was just returning 1 and doing nothing else.
356 * For this case skip the callback, but set up
357 * proper mf value first here:-)
359 if ((pa
& 0x58000000) == 0x58000000) {
360 req_idx
= pa
& 0x0000FFFF;
361 mf
= MPT_INDEX_2_MFPTR(ioc
, req_idx
);
362 mpt_free_msg_frame(ioc
, mf
);
367 mr
= (MPT_FRAME_HDR
*) CAST_U32_TO_PTR(pa
);
369 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET
:
370 cb_idx
= mpt_get_cb_idx(MPTSTM_DRIVER
);
371 mr
= (MPT_FRAME_HDR
*) CAST_U32_TO_PTR(pa
);
378 /* Check for (valid) IO callback! */
379 if (!cb_idx
|| cb_idx
>= MPT_MAX_PROTOCOL_DRIVERS
||
380 MptCallbacks
[cb_idx
] == NULL
) {
381 printk(MYIOC_s_WARN_FMT
"%s: Invalid cb_idx (%d)!\n",
382 __func__
, ioc
->name
, cb_idx
);
386 if (MptCallbacks
[cb_idx
](ioc
, mf
, mr
))
387 mpt_free_msg_frame(ioc
, mf
);
393 mpt_reply(MPT_ADAPTER
*ioc
, u32 pa
)
404 /* non-TURBO reply! Hmmm, something may be up...
405 * Newest turbo reply mechanism; get address
406 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
409 /* Map DMA address of reply header to cpu address.
410 * pa is 32 bits - but the dma address may be 32 or 64 bits
411 * get offset based only only the low addresses
414 reply_dma_low
= (pa
<<= 1);
415 mr
= (MPT_FRAME_HDR
*)((u8
*)ioc
->reply_frames
+
416 (reply_dma_low
- ioc
->reply_frames_low_dma
));
418 req_idx
= le16_to_cpu(mr
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
419 cb_idx
= mr
->u
.frame
.hwhdr
.msgctxu
.fld
.cb_idx
;
420 mf
= MPT_INDEX_2_MFPTR(ioc
, req_idx
);
422 dmfprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
423 ioc
->name
, mr
, req_idx
, cb_idx
, mr
->u
.hdr
.Function
));
424 DBG_DUMP_REPLY_FRAME(ioc
, (u32
*)mr
);
426 /* Check/log IOC log info
428 ioc_stat
= le16_to_cpu(mr
->u
.reply
.IOCStatus
);
429 if (ioc_stat
& MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE
) {
430 u32 log_info
= le32_to_cpu(mr
->u
.reply
.IOCLogInfo
);
431 if (ioc
->bus_type
== FC
)
432 mpt_fc_log_info(ioc
, log_info
);
433 else if (ioc
->bus_type
== SPI
)
434 mpt_spi_log_info(ioc
, log_info
);
435 else if (ioc
->bus_type
== SAS
)
436 mpt_sas_log_info(ioc
, log_info
);
439 if (ioc_stat
& MPI_IOCSTATUS_MASK
)
440 mpt_iocstatus_info(ioc
, (u32
)ioc_stat
, mf
);
442 /* Check for (valid) IO callback! */
443 if (!cb_idx
|| cb_idx
>= MPT_MAX_PROTOCOL_DRIVERS
||
444 MptCallbacks
[cb_idx
] == NULL
) {
445 printk(MYIOC_s_WARN_FMT
"%s: Invalid cb_idx (%d)!\n",
446 __func__
, ioc
->name
, cb_idx
);
451 freeme
= MptCallbacks
[cb_idx
](ioc
, mf
, mr
);
454 /* Flush (non-TURBO) reply with a WRITE! */
455 CHIPREG_WRITE32(&ioc
->chip
->ReplyFifo
, pa
);
458 mpt_free_msg_frame(ioc
, mf
);
462 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
464 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
465 * @irq: irq number (not used)
466 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
468 * This routine is registered via the request_irq() kernel API call,
469 * and handles all interrupts generated from a specific MPT adapter
470 * (also referred to as a IO Controller or IOC).
471 * This routine must clear the interrupt from the adapter and does
472 * so by reading the reply FIFO. Multiple replies may be processed
473 * per single call to this routine.
475 * This routine handles register-level access of the adapter but
476 * dispatches (calls) a protocol-specific callback routine to handle
477 * the protocol-specific details of the MPT request completion.
480 mpt_interrupt(int irq
, void *bus_id
)
482 MPT_ADAPTER
*ioc
= bus_id
;
483 u32 pa
= CHIPREG_READ32_dmasync(&ioc
->chip
->ReplyFifo
);
485 if (pa
== 0xFFFFFFFF)
489 * Drain the reply FIFO!
492 if (pa
& MPI_ADDRESS_REPLY_A_BIT
)
495 mpt_turbo_reply(ioc
, pa
);
496 pa
= CHIPREG_READ32_dmasync(&ioc
->chip
->ReplyFifo
);
497 } while (pa
!= 0xFFFFFFFF);
502 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
504 * mpt_base_reply - MPT base driver's callback routine
505 * @ioc: Pointer to MPT_ADAPTER structure
506 * @mf: Pointer to original MPT request frame
507 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
509 * MPT base driver's callback routine; all base driver
510 * "internal" request/reply processing is routed here.
511 * Currently used for EventNotification and EventAck handling.
513 * Returns 1 indicating original alloc'd request frame ptr
514 * should be freed, or 0 if it shouldn't.
517 mpt_base_reply(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
, MPT_FRAME_HDR
*reply
)
522 dmfprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mpt_base_reply() called\n", ioc
->name
));
523 #ifdef CONFIG_FUSION_LOGGING
524 if ((ioc
->debug_level
& MPT_DEBUG_MSG_FRAME
) &&
525 !(reply
->u
.hdr
.MsgFlags
& MPI_MSGFLAGS_CONTINUATION_REPLY
)) {
526 dmfprintk(ioc
, printk(MYIOC_s_INFO_FMT
": Original request frame (@%p) header\n",
528 DBG_DUMP_REQUEST_FRAME_HDR(ioc
, (u32
*)mf
);
532 func
= reply
->u
.hdr
.Function
;
533 dmfprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mpt_base_reply, Function=%02Xh\n",
536 if (func
== MPI_FUNCTION_EVENT_NOTIFICATION
) {
537 EventNotificationReply_t
*pEvReply
= (EventNotificationReply_t
*) reply
;
541 results
= ProcessEventNotification(ioc
, pEvReply
, &evHandlers
);
542 if (results
!= evHandlers
) {
543 /* CHECKME! Any special handling needed here? */
544 devtverboseprintk(ioc
, printk(MYIOC_s_WARN_FMT
"Called %d event handlers, sum results = %d\n",
545 ioc
->name
, evHandlers
, results
));
549 * Hmmm... It seems that EventNotificationReply is an exception
550 * to the rule of one reply per request.
552 if (pEvReply
->MsgFlags
& MPI_MSGFLAGS_CONTINUATION_REPLY
) {
555 devtverboseprintk(ioc
, printk(MYIOC_s_WARN_FMT
"EVENT_NOTIFICATION reply %p returns Request frame\n",
556 ioc
->name
, pEvReply
));
559 #ifdef CONFIG_PROC_FS
560 // LogEvent(ioc, pEvReply);
563 } else if (func
== MPI_FUNCTION_EVENT_ACK
) {
564 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mpt_base_reply, EventAck reply received\n",
566 } else if (func
== MPI_FUNCTION_CONFIG
) {
570 dcprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"config_complete (mf=%p,mr=%p)\n",
571 ioc
->name
, mf
, reply
));
573 pCfg
= * ((CONFIGPARMS
**)((u8
*) mf
+ ioc
->req_sz
- sizeof(void *)));
576 /* disable timer and remove from linked list */
577 del_timer(&pCfg
->timer
);
579 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
580 list_del(&pCfg
->linkage
);
581 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
584 * If IOC Status is SUCCESS, save the header
585 * and set the status code to GOOD.
587 pCfg
->status
= MPT_CONFIG_ERROR
;
589 ConfigReply_t
*pReply
= (ConfigReply_t
*)reply
;
592 status
= le16_to_cpu(pReply
->IOCStatus
) & MPI_IOCSTATUS_MASK
;
593 dcprintk(ioc
, printk(MYIOC_s_NOTE_FMT
" IOCStatus=%04xh, IOCLogInfo=%08xh\n",
594 ioc
->name
, status
, le32_to_cpu(pReply
->IOCLogInfo
)));
596 pCfg
->status
= status
;
597 if (status
== MPI_IOCSTATUS_SUCCESS
) {
598 if ((pReply
->Header
.PageType
&
599 MPI_CONFIG_PAGETYPE_MASK
) ==
600 MPI_CONFIG_PAGETYPE_EXTENDED
) {
601 pCfg
->cfghdr
.ehdr
->ExtPageLength
=
602 le16_to_cpu(pReply
->ExtPageLength
);
603 pCfg
->cfghdr
.ehdr
->ExtPageType
=
606 pCfg
->cfghdr
.hdr
->PageVersion
= pReply
->Header
.PageVersion
;
608 /* If this is a regular header, save PageLength. */
609 /* LMP Do this better so not using a reserved field! */
610 pCfg
->cfghdr
.hdr
->PageLength
= pReply
->Header
.PageLength
;
611 pCfg
->cfghdr
.hdr
->PageNumber
= pReply
->Header
.PageNumber
;
612 pCfg
->cfghdr
.hdr
->PageType
= pReply
->Header
.PageType
;
617 * Wake up the original calling thread
622 } else if (func
== MPI_FUNCTION_SAS_IO_UNIT_CONTROL
) {
623 /* we should be always getting a reply frame */
624 memcpy(ioc
->persist_reply_frame
, reply
,
625 min(MPT_DEFAULT_FRAME_SIZE
,
626 4*reply
->u
.reply
.MsgLength
));
627 del_timer(&ioc
->persist_timer
);
628 ioc
->persist_wait_done
= 1;
631 printk(MYIOC_s_ERR_FMT
"Unexpected msg function (=%02Xh) reply received!\n",
636 * Conditionally tell caller to free the original
637 * EventNotification/EventAck/unexpected request frame!
642 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
644 * mpt_register - Register protocol-specific main callback handler.
645 * @cbfunc: callback function pointer
646 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
648 * This routine is called by a protocol-specific driver (SCSI host,
649 * LAN, SCSI target) to register its reply callback routine. Each
650 * protocol-specific driver must do this before it will be able to
651 * use any IOC resources, such as obtaining request frames.
653 * NOTES: The SCSI protocol driver currently calls this routine thrice
654 * in order to register separate callbacks; one for "normal" SCSI IO;
655 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
657 * Returns u8 valued "handle" in the range (and S.O.D. order)
658 * {N,...,7,6,5,...,1} if successful.
659 * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
660 * considered an error by the caller.
663 mpt_register(MPT_CALLBACK cbfunc
, MPT_DRIVER_CLASS dclass
)
666 last_drv_idx
= MPT_MAX_PROTOCOL_DRIVERS
;
669 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
670 * (slot/handle 0 is reserved!)
672 for (cb_idx
= MPT_MAX_PROTOCOL_DRIVERS
-1; cb_idx
; cb_idx
--) {
673 if (MptCallbacks
[cb_idx
] == NULL
) {
674 MptCallbacks
[cb_idx
] = cbfunc
;
675 MptDriverClass
[cb_idx
] = dclass
;
676 MptEvHandlers
[cb_idx
] = NULL
;
677 last_drv_idx
= cb_idx
;
685 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
687 * mpt_deregister - Deregister a protocol drivers resources.
688 * @cb_idx: previously registered callback handle
690 * Each protocol-specific driver should call this routine when its
691 * module is unloaded.
694 mpt_deregister(u8 cb_idx
)
696 if (cb_idx
&& (cb_idx
< MPT_MAX_PROTOCOL_DRIVERS
)) {
697 MptCallbacks
[cb_idx
] = NULL
;
698 MptDriverClass
[cb_idx
] = MPTUNKNOWN_DRIVER
;
699 MptEvHandlers
[cb_idx
] = NULL
;
705 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
707 * mpt_event_register - Register protocol-specific event callback handler.
708 * @cb_idx: previously registered (via mpt_register) callback handle
709 * @ev_cbfunc: callback function
711 * This routine can be called by one or more protocol-specific drivers
712 * if/when they choose to be notified of MPT events.
714 * Returns 0 for success.
717 mpt_event_register(u8 cb_idx
, MPT_EVHANDLER ev_cbfunc
)
719 if (!cb_idx
|| cb_idx
>= MPT_MAX_PROTOCOL_DRIVERS
)
722 MptEvHandlers
[cb_idx
] = ev_cbfunc
;
726 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
728 * mpt_event_deregister - Deregister protocol-specific event callback handler
729 * @cb_idx: previously registered callback handle
731 * Each protocol-specific driver should call this routine
732 * when it does not (or can no longer) handle events,
733 * or when its module is unloaded.
736 mpt_event_deregister(u8 cb_idx
)
738 if (!cb_idx
|| cb_idx
>= MPT_MAX_PROTOCOL_DRIVERS
)
741 MptEvHandlers
[cb_idx
] = NULL
;
744 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
746 * mpt_reset_register - Register protocol-specific IOC reset handler.
747 * @cb_idx: previously registered (via mpt_register) callback handle
748 * @reset_func: reset function
750 * This routine can be called by one or more protocol-specific drivers
751 * if/when they choose to be notified of IOC resets.
753 * Returns 0 for success.
756 mpt_reset_register(u8 cb_idx
, MPT_RESETHANDLER reset_func
)
758 if (!cb_idx
|| cb_idx
>= MPT_MAX_PROTOCOL_DRIVERS
)
761 MptResetHandlers
[cb_idx
] = reset_func
;
765 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
767 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
768 * @cb_idx: previously registered callback handle
770 * Each protocol-specific driver should call this routine
771 * when it does not (or can no longer) handle IOC reset handling,
772 * or when its module is unloaded.
775 mpt_reset_deregister(u8 cb_idx
)
777 if (!cb_idx
|| cb_idx
>= MPT_MAX_PROTOCOL_DRIVERS
)
780 MptResetHandlers
[cb_idx
] = NULL
;
783 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
785 * mpt_device_driver_register - Register device driver hooks
786 * @dd_cbfunc: driver callbacks struct
787 * @cb_idx: MPT protocol driver index
790 mpt_device_driver_register(struct mpt_pci_driver
* dd_cbfunc
, u8 cb_idx
)
793 const struct pci_device_id
*id
;
795 if (!cb_idx
|| cb_idx
>= MPT_MAX_PROTOCOL_DRIVERS
)
798 MptDeviceDriverHandlers
[cb_idx
] = dd_cbfunc
;
800 /* call per pci device probe entry point */
801 list_for_each_entry(ioc
, &ioc_list
, list
) {
802 id
= ioc
->pcidev
->driver
?
803 ioc
->pcidev
->driver
->id_table
: NULL
;
804 if (dd_cbfunc
->probe
)
805 dd_cbfunc
->probe(ioc
->pcidev
, id
);
811 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
813 * mpt_device_driver_deregister - DeRegister device driver hooks
814 * @cb_idx: MPT protocol driver index
817 mpt_device_driver_deregister(u8 cb_idx
)
819 struct mpt_pci_driver
*dd_cbfunc
;
822 if (!cb_idx
|| cb_idx
>= MPT_MAX_PROTOCOL_DRIVERS
)
825 dd_cbfunc
= MptDeviceDriverHandlers
[cb_idx
];
827 list_for_each_entry(ioc
, &ioc_list
, list
) {
828 if (dd_cbfunc
->remove
)
829 dd_cbfunc
->remove(ioc
->pcidev
);
832 MptDeviceDriverHandlers
[cb_idx
] = NULL
;
836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
838 * mpt_get_msg_frame - Obtain an MPT request frame from the pool
839 * @cb_idx: Handle of registered MPT protocol driver
840 * @ioc: Pointer to MPT adapter structure
842 * Obtain an MPT request frame from the pool (of 1024) that are
843 * allocated per MPT adapter.
845 * Returns pointer to a MPT request frame or %NULL if none are available
846 * or IOC is not active.
849 mpt_get_msg_frame(u8 cb_idx
, MPT_ADAPTER
*ioc
)
853 u16 req_idx
; /* Request index */
855 /* validate handle and ioc identifier */
859 printk(MYIOC_s_WARN_FMT
"IOC Not Active! mpt_get_msg_frame "
860 "returning NULL!\n", ioc
->name
);
863 /* If interrupts are not attached, do not return a request frame */
867 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
868 if (!list_empty(&ioc
->FreeQ
)) {
871 mf
= list_entry(ioc
->FreeQ
.next
, MPT_FRAME_HDR
,
872 u
.frame
.linkage
.list
);
873 list_del(&mf
->u
.frame
.linkage
.list
);
874 mf
->u
.frame
.linkage
.arg1
= 0;
875 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.cb_idx
= cb_idx
; /* byte */
876 req_offset
= (u8
*)mf
- (u8
*)ioc
->req_frames
;
878 req_idx
= req_offset
/ ioc
->req_sz
;
879 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
= cpu_to_le16(req_idx
);
880 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.rsvd
= 0;
881 /* Default, will be changed if necessary in SG generation */
882 ioc
->RequestNB
[req_idx
] = ioc
->NB_for_64_byte_frame
;
889 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
893 printk(MYIOC_s_WARN_FMT
"IOC Active. No free Msg Frames! "
894 "Count 0x%x Max 0x%x\n", ioc
->name
, ioc
->mfcnt
,
897 if (mfcounter
== PRINT_MF_COUNT
)
898 printk(MYIOC_s_INFO_FMT
"MF Count 0x%x Max 0x%x \n", ioc
->name
,
899 ioc
->mfcnt
, ioc
->req_depth
);
902 dmfprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mpt_get_msg_frame(%d,%d), got mf=%p\n",
903 ioc
->name
, cb_idx
, ioc
->id
, mf
));
907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
909 * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
910 * @cb_idx: Handle of registered MPT protocol driver
911 * @ioc: Pointer to MPT adapter structure
912 * @mf: Pointer to MPT request frame
914 * This routine posts an MPT request frame to the request post FIFO of a
915 * specific MPT adapter.
918 mpt_put_msg_frame(u8 cb_idx
, MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
)
922 u16 req_idx
; /* Request index */
924 /* ensure values are reset properly! */
925 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.cb_idx
= cb_idx
; /* byte */
926 req_offset
= (u8
*)mf
- (u8
*)ioc
->req_frames
;
928 req_idx
= req_offset
/ ioc
->req_sz
;
929 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
= cpu_to_le16(req_idx
);
930 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.rsvd
= 0;
932 DBG_DUMP_PUT_MSG_FRAME(ioc
, (u32
*)mf
);
934 mf_dma_addr
= (ioc
->req_frames_low_dma
+ req_offset
) | ioc
->RequestNB
[req_idx
];
935 dsgprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mf_dma_addr=%x req_idx=%d "
936 "RequestNB=%x\n", ioc
->name
, mf_dma_addr
, req_idx
,
937 ioc
->RequestNB
[req_idx
]));
938 CHIPREG_WRITE32(&ioc
->chip
->RequestFifo
, mf_dma_addr
);
942 * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
943 * @cb_idx: Handle of registered MPT protocol driver
944 * @ioc: Pointer to MPT adapter structure
945 * @mf: Pointer to MPT request frame
947 * Send a protocol-specific MPT request frame to an IOC using
948 * hi-priority request queue.
950 * This routine posts an MPT request frame to the request post FIFO of a
951 * specific MPT adapter.
954 mpt_put_msg_frame_hi_pri(u8 cb_idx
, MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
)
958 u16 req_idx
; /* Request index */
960 /* ensure values are reset properly! */
961 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.cb_idx
= cb_idx
;
962 req_offset
= (u8
*)mf
- (u8
*)ioc
->req_frames
;
963 req_idx
= req_offset
/ ioc
->req_sz
;
964 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
= cpu_to_le16(req_idx
);
965 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.rsvd
= 0;
967 DBG_DUMP_PUT_MSG_FRAME(ioc
, (u32
*)mf
);
969 mf_dma_addr
= (ioc
->req_frames_low_dma
+ req_offset
);
970 dsgprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mf_dma_addr=%x req_idx=%d\n",
971 ioc
->name
, mf_dma_addr
, req_idx
));
972 CHIPREG_WRITE32(&ioc
->chip
->RequestHiPriFifo
, mf_dma_addr
);
975 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
977 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
978 * @ioc: Pointer to MPT adapter structure
979 * @mf: Pointer to MPT request frame
981 * This routine places a MPT request frame back on the MPT adapter's
985 mpt_free_msg_frame(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
)
989 /* Put Request back on FreeQ! */
990 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
991 mf
->u
.frame
.linkage
.arg1
= 0xdeadbeaf; /* signature to know if this mf is freed */
992 list_add_tail(&mf
->u
.frame
.linkage
.list
, &ioc
->FreeQ
);
996 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
999 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1001 * mpt_add_sge - Place a simple SGE at address pAddr.
1002 * @pAddr: virtual address for SGE
1003 * @flagslength: SGE flags and data transfer length
1004 * @dma_addr: Physical address
1006 * This routine places a MPT request frame back on the MPT adapter's
1010 mpt_add_sge(char *pAddr
, u32 flagslength
, dma_addr_t dma_addr
)
1012 if (sizeof(dma_addr_t
) == sizeof(u64
)) {
1013 SGESimple64_t
*pSge
= (SGESimple64_t
*) pAddr
;
1014 u32 tmp
= dma_addr
& 0xFFFFFFFF;
1016 pSge
->FlagsLength
= cpu_to_le32(flagslength
);
1017 pSge
->Address
.Low
= cpu_to_le32(tmp
);
1018 tmp
= (u32
) ((u64
)dma_addr
>> 32);
1019 pSge
->Address
.High
= cpu_to_le32(tmp
);
1022 SGESimple32_t
*pSge
= (SGESimple32_t
*) pAddr
;
1023 pSge
->FlagsLength
= cpu_to_le32(flagslength
);
1024 pSge
->Address
= cpu_to_le32(dma_addr
);
1028 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1030 * mpt_send_handshake_request - Send MPT request via doorbell handshake method.
1031 * @cb_idx: Handle of registered MPT protocol driver
1032 * @ioc: Pointer to MPT adapter structure
1033 * @reqBytes: Size of the request in bytes
1034 * @req: Pointer to MPT request frame
1035 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1037 * This routine is used exclusively to send MptScsiTaskMgmt
1038 * requests since they are required to be sent via doorbell handshake.
1040 * NOTE: It is the callers responsibility to byte-swap fields in the
1041 * request which are greater than 1 byte in size.
1043 * Returns 0 for success, non-zero for failure.
1046 mpt_send_handshake_request(u8 cb_idx
, MPT_ADAPTER
*ioc
, int reqBytes
, u32
*req
, int sleepFlag
)
1052 /* State is known to be good upon entering
1053 * this function so issue the bus reset
1058 * Emulate what mpt_put_msg_frame() does /wrt to sanity
1059 * setting cb_idx/req_idx. But ONLY if this request
1060 * is in proper (pre-alloc'd) request buffer range...
1062 ii
= MFPTR_2_MPT_INDEX(ioc
,(MPT_FRAME_HDR
*)req
);
1063 if (reqBytes
>= 12 && ii
>= 0 && ii
< ioc
->req_depth
) {
1064 MPT_FRAME_HDR
*mf
= (MPT_FRAME_HDR
*)req
;
1065 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
= cpu_to_le16(ii
);
1066 mf
->u
.frame
.hwhdr
.msgctxu
.fld
.cb_idx
= cb_idx
;
1069 /* Make sure there are no doorbells */
1070 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
1072 CHIPREG_WRITE32(&ioc
->chip
->Doorbell
,
1073 ((MPI_FUNCTION_HANDSHAKE
<<MPI_DOORBELL_FUNCTION_SHIFT
) |
1074 ((reqBytes
/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT
)));
1076 /* Wait for IOC doorbell int */
1077 if ((ii
= WaitForDoorbellInt(ioc
, 5, sleepFlag
)) < 0) {
1081 /* Read doorbell and check for active bit */
1082 if (!(CHIPREG_READ32(&ioc
->chip
->Doorbell
) & MPI_DOORBELL_ACTIVE
))
1085 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mpt_send_handshake_request start, WaitCnt=%d\n",
1088 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
1090 if ((r
= WaitForDoorbellAck(ioc
, 5, sleepFlag
)) < 0) {
1094 /* Send request via doorbell handshake */
1095 req_as_bytes
= (u8
*) req
;
1096 for (ii
= 0; ii
< reqBytes
/4; ii
++) {
1099 word
= ((req_as_bytes
[(ii
*4) + 0] << 0) |
1100 (req_as_bytes
[(ii
*4) + 1] << 8) |
1101 (req_as_bytes
[(ii
*4) + 2] << 16) |
1102 (req_as_bytes
[(ii
*4) + 3] << 24));
1103 CHIPREG_WRITE32(&ioc
->chip
->Doorbell
, word
);
1104 if ((r
= WaitForDoorbellAck(ioc
, 5, sleepFlag
)) < 0) {
1110 if (r
>= 0 && WaitForDoorbellInt(ioc
, 10, sleepFlag
) >= 0)
1115 /* Make sure there are no doorbells */
1116 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
1121 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1123 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1124 * @ioc: Pointer to MPT adapter structure
1125 * @access_control_value: define bits below
1126 * @sleepFlag: Specifies whether the process can sleep
1128 * Provides mechanism for the host driver to control the IOC's
1129 * Host Page Buffer access.
1131 * Access Control Value - bits[15:12]
1133 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1134 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1135 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1137 * Returns 0 for success, non-zero for failure.
1141 mpt_host_page_access_control(MPT_ADAPTER
*ioc
, u8 access_control_value
, int sleepFlag
)
1145 /* return if in use */
1146 if (CHIPREG_READ32(&ioc
->chip
->Doorbell
)
1147 & MPI_DOORBELL_ACTIVE
)
1150 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
1152 CHIPREG_WRITE32(&ioc
->chip
->Doorbell
,
1153 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1154 <<MPI_DOORBELL_FUNCTION_SHIFT
) |
1155 (access_control_value
<<12)));
1157 /* Wait for IOC to clear Doorbell Status bit */
1158 if ((r
= WaitForDoorbellAck(ioc
, 5, sleepFlag
)) < 0) {
1164 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1166 * mpt_host_page_alloc - allocate system memory for the fw
1167 * @ioc: Pointer to pointer to IOC adapter
1168 * @ioc_init: Pointer to ioc init config page
1170 * If we already allocated memory in past, then resend the same pointer.
1171 * Returns 0 for success, non-zero for failure.
1174 mpt_host_page_alloc(MPT_ADAPTER
*ioc
, pIOCInit_t ioc_init
)
1178 u32 host_page_buffer_sz
=0;
1180 if(!ioc
->HostPageBuffer
) {
1182 host_page_buffer_sz
=
1183 le32_to_cpu(ioc
->facts
.HostPageBufferSGE
.FlagsLength
) & 0xFFFFFF;
1185 if(!host_page_buffer_sz
)
1186 return 0; /* fw doesn't need any host buffers */
1188 /* spin till we get enough memory */
1189 while(host_page_buffer_sz
> 0) {
1191 if((ioc
->HostPageBuffer
= pci_alloc_consistent(
1193 host_page_buffer_sz
,
1194 &ioc
->HostPageBuffer_dma
)) != NULL
) {
1196 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
1197 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1198 ioc
->name
, ioc
->HostPageBuffer
,
1199 (u32
)ioc
->HostPageBuffer_dma
,
1200 host_page_buffer_sz
));
1201 ioc
->alloc_total
+= host_page_buffer_sz
;
1202 ioc
->HostPageBuffer_sz
= host_page_buffer_sz
;
1206 host_page_buffer_sz
-= (4*1024);
1210 if(!ioc
->HostPageBuffer
) {
1211 printk(MYIOC_s_ERR_FMT
1212 "Failed to alloc memory for host_page_buffer!\n",
1217 psge
= (char *)&ioc_init
->HostPageBufferSGE
;
1218 flags_length
= MPI_SGE_FLAGS_SIMPLE_ELEMENT
|
1219 MPI_SGE_FLAGS_SYSTEM_ADDRESS
|
1220 MPI_SGE_FLAGS_32_BIT_ADDRESSING
|
1221 MPI_SGE_FLAGS_HOST_TO_IOC
|
1222 MPI_SGE_FLAGS_END_OF_BUFFER
;
1223 if (sizeof(dma_addr_t
) == sizeof(u64
)) {
1224 flags_length
|= MPI_SGE_FLAGS_64_BIT_ADDRESSING
;
1226 flags_length
= flags_length
<< MPI_SGE_FLAGS_SHIFT
;
1227 flags_length
|= ioc
->HostPageBuffer_sz
;
1228 mpt_add_sge(psge
, flags_length
, ioc
->HostPageBuffer_dma
);
1229 ioc
->facts
.HostPageBufferSGE
= ioc_init
->HostPageBufferSGE
;
1234 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1236 * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1237 * @iocid: IOC unique identifier (integer)
1238 * @iocpp: Pointer to pointer to IOC adapter
1240 * Given a unique IOC identifier, set pointer to the associated MPT
1241 * adapter structure.
1243 * Returns iocid and sets iocpp if iocid is found.
1244 * Returns -1 if iocid is not found.
1247 mpt_verify_adapter(int iocid
, MPT_ADAPTER
**iocpp
)
1251 list_for_each_entry(ioc
,&ioc_list
,list
) {
1252 if (ioc
->id
== iocid
) {
1263 * mpt_get_product_name - returns product string
1264 * @vendor: pci vendor id
1265 * @device: pci device id
1266 * @revision: pci revision id
1267 * @prod_name: string returned
1269 * Returns product string displayed when driver loads,
1270 * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1274 mpt_get_product_name(u16 vendor
, u16 device
, u8 revision
, char *prod_name
)
1276 char *product_str
= NULL
;
1278 if (vendor
== PCI_VENDOR_ID_BROCADE
) {
1281 case MPI_MANUFACTPAGE_DEVICEID_FC949E
:
1285 product_str
= "BRE040 A0";
1288 product_str
= "BRE040 A1";
1291 product_str
= "BRE040";
1301 case MPI_MANUFACTPAGE_DEVICEID_FC909
:
1302 product_str
= "LSIFC909 B1";
1304 case MPI_MANUFACTPAGE_DEVICEID_FC919
:
1305 product_str
= "LSIFC919 B0";
1307 case MPI_MANUFACTPAGE_DEVICEID_FC929
:
1308 product_str
= "LSIFC929 B0";
1310 case MPI_MANUFACTPAGE_DEVICEID_FC919X
:
1311 if (revision
< 0x80)
1312 product_str
= "LSIFC919X A0";
1314 product_str
= "LSIFC919XL A1";
1316 case MPI_MANUFACTPAGE_DEVICEID_FC929X
:
1317 if (revision
< 0x80)
1318 product_str
= "LSIFC929X A0";
1320 product_str
= "LSIFC929XL A1";
1322 case MPI_MANUFACTPAGE_DEVICEID_FC939X
:
1323 product_str
= "LSIFC939X A1";
1325 case MPI_MANUFACTPAGE_DEVICEID_FC949X
:
1326 product_str
= "LSIFC949X A1";
1328 case MPI_MANUFACTPAGE_DEVICEID_FC949E
:
1332 product_str
= "LSIFC949E A0";
1335 product_str
= "LSIFC949E A1";
1338 product_str
= "LSIFC949E";
1342 case MPI_MANUFACTPAGE_DEVID_53C1030
:
1346 product_str
= "LSI53C1030 A0";
1349 product_str
= "LSI53C1030 B0";
1352 product_str
= "LSI53C1030 B1";
1355 product_str
= "LSI53C1030 B2";
1358 product_str
= "LSI53C1030 C0";
1361 product_str
= "LSI53C1030T A0";
1364 product_str
= "LSI53C1030T A2";
1367 product_str
= "LSI53C1030T A3";
1370 product_str
= "LSI53C1020A A1";
1373 product_str
= "LSI53C1030";
1377 case MPI_MANUFACTPAGE_DEVID_1030_53C1035
:
1381 product_str
= "LSI53C1035 A2";
1384 product_str
= "LSI53C1035 B0";
1387 product_str
= "LSI53C1035";
1391 case MPI_MANUFACTPAGE_DEVID_SAS1064
:
1395 product_str
= "LSISAS1064 A1";
1398 product_str
= "LSISAS1064 A2";
1401 product_str
= "LSISAS1064 A3";
1404 product_str
= "LSISAS1064 A4";
1407 product_str
= "LSISAS1064";
1411 case MPI_MANUFACTPAGE_DEVID_SAS1064E
:
1415 product_str
= "LSISAS1064E A0";
1418 product_str
= "LSISAS1064E B0";
1421 product_str
= "LSISAS1064E B1";
1424 product_str
= "LSISAS1064E B2";
1427 product_str
= "LSISAS1064E B3";
1430 product_str
= "LSISAS1064E";
1434 case MPI_MANUFACTPAGE_DEVID_SAS1068
:
1438 product_str
= "LSISAS1068 A0";
1441 product_str
= "LSISAS1068 B0";
1444 product_str
= "LSISAS1068 B1";
1447 product_str
= "LSISAS1068";
1451 case MPI_MANUFACTPAGE_DEVID_SAS1068E
:
1455 product_str
= "LSISAS1068E A0";
1458 product_str
= "LSISAS1068E B0";
1461 product_str
= "LSISAS1068E B1";
1464 product_str
= "LSISAS1068E B2";
1467 product_str
= "LSISAS1068E B3";
1470 product_str
= "LSISAS1068E";
1474 case MPI_MANUFACTPAGE_DEVID_SAS1078
:
1478 product_str
= "LSISAS1078 A0";
1481 product_str
= "LSISAS1078 B0";
1484 product_str
= "LSISAS1078 C0";
1487 product_str
= "LSISAS1078 C1";
1490 product_str
= "LSISAS1078 C2";
1493 product_str
= "LSISAS1078";
1501 sprintf(prod_name
, "%s", product_str
);
1505 * mpt_mapresources - map in memory mapped io
1506 * @ioc: Pointer to pointer to IOC adapter
1510 mpt_mapresources(MPT_ADAPTER
*ioc
)
1514 unsigned long mem_phys
;
1520 struct pci_dev
*pdev
;
1523 ioc
->bars
= pci_select_bars(pdev
, IORESOURCE_MEM
);
1524 if (pci_enable_device_mem(pdev
)) {
1525 printk(MYIOC_s_ERR_FMT
"pci_enable_device_mem() "
1526 "failed\n", ioc
->name
);
1529 if (pci_request_selected_regions(pdev
, ioc
->bars
, "mpt")) {
1530 printk(MYIOC_s_ERR_FMT
"pci_request_selected_regions() with "
1531 "MEM failed\n", ioc
->name
);
1535 pci_read_config_byte(pdev
, PCI_CLASS_REVISION
, &revision
);
1537 if (!pci_set_dma_mask(pdev
, DMA_BIT_MASK(64))
1538 && !pci_set_consistent_dma_mask(pdev
, DMA_BIT_MASK(64))) {
1539 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
1540 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1542 } else if (!pci_set_dma_mask(pdev
, DMA_32BIT_MASK
)
1543 && !pci_set_consistent_dma_mask(pdev
, DMA_32BIT_MASK
)) {
1544 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
1545 ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1548 printk(MYIOC_s_WARN_FMT
"no suitable DMA mask for %s\n",
1549 ioc
->name
, pci_name(pdev
));
1550 pci_release_selected_regions(pdev
, ioc
->bars
);
1554 mem_phys
= msize
= 0;
1556 for (ii
= 0; ii
< DEVICE_COUNT_RESOURCE
; ii
++) {
1557 if (pci_resource_flags(pdev
, ii
) & PCI_BASE_ADDRESS_SPACE_IO
) {
1560 /* Get I/O space! */
1561 port
= pci_resource_start(pdev
, ii
);
1562 psize
= pci_resource_len(pdev
, ii
);
1567 mem_phys
= pci_resource_start(pdev
, ii
);
1568 msize
= pci_resource_len(pdev
, ii
);
1571 ioc
->mem_size
= msize
;
1574 /* Get logical ptr for PciMem0 space */
1575 /*mem = ioremap(mem_phys, msize);*/
1576 mem
= ioremap(mem_phys
, msize
);
1578 printk(MYIOC_s_ERR_FMT
": ERROR - Unable to map adapter"
1579 " memory!\n", ioc
->name
);
1583 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
"mem = %p, mem_phys = %lx\n",
1584 ioc
->name
, mem
, mem_phys
));
1586 ioc
->mem_phys
= mem_phys
;
1587 ioc
->chip
= (SYSIF_REGS __iomem
*)mem
;
1589 /* Save Port IO values in case we need to do downloadboot */
1590 ioc
->pio_mem_phys
= port
;
1591 ioc
->pio_chip
= (SYSIF_REGS __iomem
*)port
;
1596 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1598 * mpt_attach - Install a PCI intelligent MPT adapter.
1599 * @pdev: Pointer to pci_dev structure
1600 * @id: PCI device ID information
1602 * This routine performs all the steps necessary to bring the IOC of
1603 * a MPT adapter to a OPERATIONAL state. This includes registering
1604 * memory regions, registering the interrupt, and allocating request
1605 * and reply memory pools.
1607 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1610 * Returns 0 for success, non-zero for failure.
1612 * TODO: Add support for polled controllers
1615 mpt_attach(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
1622 static int mpt_ids
= 0;
1623 #ifdef CONFIG_PROC_FS
1624 struct proc_dir_entry
*dent
, *ent
;
1627 ioc
= kzalloc(sizeof(MPT_ADAPTER
), GFP_ATOMIC
);
1629 printk(KERN_ERR MYNAM
": ERROR - Insufficient memory to add adapter!\n");
1633 ioc
->id
= mpt_ids
++;
1634 sprintf(ioc
->name
, "ioc%d", ioc
->id
);
1637 * set initial debug level
1638 * (refer to mptdebug.h)
1641 ioc
->debug_level
= mpt_debug_level
;
1642 if (mpt_debug_level
)
1643 printk(KERN_INFO
"mpt_debug_level=%xh\n", mpt_debug_level
);
1645 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
": mpt_adapter_install\n", ioc
->name
));
1648 if (mpt_mapresources(ioc
)) {
1653 ioc
->alloc_total
= sizeof(MPT_ADAPTER
);
1654 ioc
->req_sz
= MPT_DEFAULT_FRAME_SIZE
; /* avoid div by zero! */
1655 ioc
->reply_sz
= MPT_REPLY_FRAME_SIZE
;
1658 ioc
->diagPending
= 0;
1659 spin_lock_init(&ioc
->diagLock
);
1660 spin_lock_init(&ioc
->initializing_hba_lock
);
1662 /* Initialize the event logging.
1664 ioc
->eventTypes
= 0; /* None */
1665 ioc
->eventContext
= 0;
1666 ioc
->eventLogSize
= 0;
1673 ioc
->cached_fw
= NULL
;
1675 /* Initilize SCSI Config Data structure
1677 memset(&ioc
->spi_data
, 0, sizeof(SpiCfgData
));
1679 /* Initialize the running configQ head.
1681 INIT_LIST_HEAD(&ioc
->configQ
);
1683 /* Initialize the fc rport list head.
1685 INIT_LIST_HEAD(&ioc
->fc_rports
);
1687 /* Find lookup slot. */
1688 INIT_LIST_HEAD(&ioc
->list
);
1691 /* Initialize workqueue */
1692 INIT_DELAYED_WORK(&ioc
->fault_reset_work
, mpt_fault_reset_work
);
1693 spin_lock_init(&ioc
->fault_reset_work_lock
);
1695 snprintf(ioc
->reset_work_q_name
, sizeof(ioc
->reset_work_q_name
),
1696 "mpt_poll_%d", ioc
->id
);
1698 create_singlethread_workqueue(ioc
->reset_work_q_name
);
1699 if (!ioc
->reset_work_q
) {
1700 printk(MYIOC_s_ERR_FMT
"Insufficient memory to add adapter!\n",
1702 pci_release_selected_regions(pdev
, ioc
->bars
);
1707 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
"facts @ %p, pfacts[0] @ %p\n",
1708 ioc
->name
, &ioc
->facts
, &ioc
->pfacts
[0]));
1710 pci_read_config_byte(pdev
, PCI_CLASS_REVISION
, &revision
);
1711 mpt_get_product_name(pdev
->vendor
, pdev
->device
, revision
, ioc
->prod_name
);
1713 switch (pdev
->device
)
1715 case MPI_MANUFACTPAGE_DEVICEID_FC939X
:
1716 case MPI_MANUFACTPAGE_DEVICEID_FC949X
:
1717 ioc
->errata_flag_1064
= 1;
1718 case MPI_MANUFACTPAGE_DEVICEID_FC909
:
1719 case MPI_MANUFACTPAGE_DEVICEID_FC929
:
1720 case MPI_MANUFACTPAGE_DEVICEID_FC919
:
1721 case MPI_MANUFACTPAGE_DEVICEID_FC949E
:
1725 case MPI_MANUFACTPAGE_DEVICEID_FC929X
:
1726 if (revision
< XL_929
) {
1727 /* 929X Chip Fix. Set Split transactions level
1728 * for PCIX. Set MOST bits to zero.
1730 pci_read_config_byte(pdev
, 0x6a, &pcixcmd
);
1732 pci_write_config_byte(pdev
, 0x6a, pcixcmd
);
1734 /* 929XL Chip Fix. Set MMRBC to 0x08.
1736 pci_read_config_byte(pdev
, 0x6a, &pcixcmd
);
1738 pci_write_config_byte(pdev
, 0x6a, pcixcmd
);
1743 case MPI_MANUFACTPAGE_DEVICEID_FC919X
:
1744 /* 919X Chip Fix. Set Split transactions level
1745 * for PCIX. Set MOST bits to zero.
1747 pci_read_config_byte(pdev
, 0x6a, &pcixcmd
);
1749 pci_write_config_byte(pdev
, 0x6a, pcixcmd
);
1753 case MPI_MANUFACTPAGE_DEVID_53C1030
:
1754 /* 1030 Chip Fix. Disable Split transactions
1755 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1757 if (revision
< C0_1030
) {
1758 pci_read_config_byte(pdev
, 0x6a, &pcixcmd
);
1760 pci_write_config_byte(pdev
, 0x6a, pcixcmd
);
1763 case MPI_MANUFACTPAGE_DEVID_1030_53C1035
:
1764 ioc
->bus_type
= SPI
;
1767 case MPI_MANUFACTPAGE_DEVID_SAS1064
:
1768 case MPI_MANUFACTPAGE_DEVID_SAS1068
:
1769 ioc
->errata_flag_1064
= 1;
1771 case MPI_MANUFACTPAGE_DEVID_SAS1064E
:
1772 case MPI_MANUFACTPAGE_DEVID_SAS1068E
:
1773 case MPI_MANUFACTPAGE_DEVID_SAS1078
:
1774 ioc
->bus_type
= SAS
;
1778 switch (ioc
->bus_type
) {
1781 ioc
->msi_enable
= mpt_msi_enable_sas
;
1785 ioc
->msi_enable
= mpt_msi_enable_spi
;
1789 ioc
->msi_enable
= mpt_msi_enable_fc
;
1793 ioc
->msi_enable
= 0;
1796 if (ioc
->errata_flag_1064
)
1797 pci_disable_io_access(pdev
);
1799 spin_lock_init(&ioc
->FreeQlock
);
1802 CHIPREG_WRITE32(&ioc
->chip
->IntMask
, 0xFFFFFFFF);
1804 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
1806 /* Set IOC ptr in the pcidev's driver data. */
1807 pci_set_drvdata(ioc
->pcidev
, ioc
);
1809 /* Set lookup ptr. */
1810 list_add_tail(&ioc
->list
, &ioc_list
);
1812 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1814 mpt_detect_bound_ports(ioc
, pdev
);
1816 if ((r
= mpt_do_ioc_recovery(ioc
, MPT_HOSTEVENT_IOC_BRINGUP
,
1818 printk(MYIOC_s_ERR_FMT
"didn't initialize properly! (%d)\n",
1821 list_del(&ioc
->list
);
1823 ioc
->alt_ioc
->alt_ioc
= NULL
;
1824 iounmap(ioc
->memmap
);
1826 pci_release_selected_regions(pdev
, ioc
->bars
);
1828 destroy_workqueue(ioc
->reset_work_q
);
1829 ioc
->reset_work_q
= NULL
;
1832 pci_set_drvdata(pdev
, NULL
);
1836 /* call per device driver probe entry point */
1837 for(cb_idx
= 0; cb_idx
< MPT_MAX_PROTOCOL_DRIVERS
; cb_idx
++) {
1838 if(MptDeviceDriverHandlers
[cb_idx
] &&
1839 MptDeviceDriverHandlers
[cb_idx
]->probe
) {
1840 MptDeviceDriverHandlers
[cb_idx
]->probe(pdev
,id
);
1844 #ifdef CONFIG_PROC_FS
1846 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1848 dent
= proc_mkdir(ioc
->name
, mpt_proc_root_dir
);
1850 ent
= create_proc_entry("info", S_IFREG
|S_IRUGO
, dent
);
1852 ent
->read_proc
= procmpt_iocinfo_read
;
1855 ent
= create_proc_entry("summary", S_IFREG
|S_IRUGO
, dent
);
1857 ent
->read_proc
= procmpt_summary_read
;
1864 queue_delayed_work(ioc
->reset_work_q
, &ioc
->fault_reset_work
,
1865 msecs_to_jiffies(MPT_POLLING_INTERVAL
));
1870 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1872 * mpt_detach - Remove a PCI intelligent MPT adapter.
1873 * @pdev: Pointer to pci_dev structure
1877 mpt_detach(struct pci_dev
*pdev
)
1879 MPT_ADAPTER
*ioc
= pci_get_drvdata(pdev
);
1882 unsigned long flags
;
1883 struct workqueue_struct
*wq
;
1886 * Stop polling ioc for fault condition
1888 spin_lock_irqsave(&ioc
->fault_reset_work_lock
, flags
);
1889 wq
= ioc
->reset_work_q
;
1890 ioc
->reset_work_q
= NULL
;
1891 spin_unlock_irqrestore(&ioc
->fault_reset_work_lock
, flags
);
1892 cancel_delayed_work(&ioc
->fault_reset_work
);
1893 destroy_workqueue(wq
);
1896 sprintf(pname
, MPT_PROCFS_MPTBASEDIR
"/%s/summary", ioc
->name
);
1897 remove_proc_entry(pname
, NULL
);
1898 sprintf(pname
, MPT_PROCFS_MPTBASEDIR
"/%s/info", ioc
->name
);
1899 remove_proc_entry(pname
, NULL
);
1900 sprintf(pname
, MPT_PROCFS_MPTBASEDIR
"/%s", ioc
->name
);
1901 remove_proc_entry(pname
, NULL
);
1903 /* call per device driver remove entry point */
1904 for(cb_idx
= 0; cb_idx
< MPT_MAX_PROTOCOL_DRIVERS
; cb_idx
++) {
1905 if(MptDeviceDriverHandlers
[cb_idx
] &&
1906 MptDeviceDriverHandlers
[cb_idx
]->remove
) {
1907 MptDeviceDriverHandlers
[cb_idx
]->remove(pdev
);
1911 /* Disable interrupts! */
1912 CHIPREG_WRITE32(&ioc
->chip
->IntMask
, 0xFFFFFFFF);
1915 synchronize_irq(pdev
->irq
);
1917 /* Clear any lingering interrupt */
1918 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
1920 CHIPREG_READ32(&ioc
->chip
->IntStatus
);
1922 mpt_adapter_dispose(ioc
);
1924 pci_set_drvdata(pdev
, NULL
);
1927 /**************************************************************************
1931 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1933 * mpt_suspend - Fusion MPT base driver suspend routine.
1934 * @pdev: Pointer to pci_dev structure
1935 * @state: new state to enter
1938 mpt_suspend(struct pci_dev
*pdev
, pm_message_t state
)
1941 MPT_ADAPTER
*ioc
= pci_get_drvdata(pdev
);
1943 device_state
= pci_choose_state(pdev
, state
);
1944 printk(MYIOC_s_INFO_FMT
"pci-suspend: pdev=0x%p, slot=%s, Entering "
1945 "operating state [D%d]\n", ioc
->name
, pdev
, pci_name(pdev
),
1948 /* put ioc into READY_STATE */
1949 if(SendIocReset(ioc
, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET
, CAN_SLEEP
)) {
1950 printk(MYIOC_s_ERR_FMT
1951 "pci-suspend: IOC msg unit reset failed!\n", ioc
->name
);
1954 /* disable interrupts */
1955 CHIPREG_WRITE32(&ioc
->chip
->IntMask
, 0xFFFFFFFF);
1958 /* Clear any lingering interrupt */
1959 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
1961 free_irq(ioc
->pci_irq
, ioc
);
1962 if (ioc
->msi_enable
)
1963 pci_disable_msi(ioc
->pcidev
);
1965 pci_save_state(pdev
);
1966 pci_disable_device(pdev
);
1967 pci_release_selected_regions(pdev
, ioc
->bars
);
1968 pci_set_power_state(pdev
, device_state
);
1972 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1974 * mpt_resume - Fusion MPT base driver resume routine.
1975 * @pdev: Pointer to pci_dev structure
1978 mpt_resume(struct pci_dev
*pdev
)
1980 MPT_ADAPTER
*ioc
= pci_get_drvdata(pdev
);
1981 u32 device_state
= pdev
->current_state
;
1985 printk(MYIOC_s_INFO_FMT
"pci-resume: pdev=0x%p, slot=%s, Previous "
1986 "operating state [D%d]\n", ioc
->name
, pdev
, pci_name(pdev
),
1989 pci_set_power_state(pdev
, PCI_D0
);
1990 pci_enable_wake(pdev
, PCI_D0
, 0);
1991 pci_restore_state(pdev
);
1993 err
= mpt_mapresources(ioc
);
1997 printk(MYIOC_s_INFO_FMT
"pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1998 ioc
->name
, (mpt_GetIocState(ioc
, 1) >> MPI_IOC_STATE_SHIFT
),
1999 CHIPREG_READ32(&ioc
->chip
->Doorbell
));
2002 * Errata workaround for SAS pci express:
2003 * Upon returning to the D0 state, the contents of the doorbell will be
2004 * stale data, and this will incorrectly signal to the host driver that
2005 * the firmware is ready to process mpt commands. The workaround is
2006 * to issue a diagnostic reset.
2008 if (ioc
->bus_type
== SAS
&& (pdev
->device
==
2009 MPI_MANUFACTPAGE_DEVID_SAS1068E
|| pdev
->device
==
2010 MPI_MANUFACTPAGE_DEVID_SAS1064E
)) {
2011 if (KickStart(ioc
, 1, CAN_SLEEP
) < 0) {
2012 printk(MYIOC_s_WARN_FMT
"pci-resume: Cannot recover\n",
2018 /* bring ioc to operational state */
2019 printk(MYIOC_s_INFO_FMT
"Sending mpt_do_ioc_recovery\n", ioc
->name
);
2020 recovery_state
= mpt_do_ioc_recovery(ioc
, MPT_HOSTEVENT_IOC_BRINGUP
,
2022 if (recovery_state
!= 0)
2023 printk(MYIOC_s_WARN_FMT
"pci-resume: Cannot recover, "
2024 "error:[%x]\n", ioc
->name
, recovery_state
);
2026 printk(MYIOC_s_INFO_FMT
2027 "pci-resume: success\n", ioc
->name
);
2035 mpt_signal_reset(u8 index
, MPT_ADAPTER
*ioc
, int reset_phase
)
2037 if ((MptDriverClass
[index
] == MPTSPI_DRIVER
&&
2038 ioc
->bus_type
!= SPI
) ||
2039 (MptDriverClass
[index
] == MPTFC_DRIVER
&&
2040 ioc
->bus_type
!= FC
) ||
2041 (MptDriverClass
[index
] == MPTSAS_DRIVER
&&
2042 ioc
->bus_type
!= SAS
))
2043 /* make sure we only call the relevant reset handler
2046 return (MptResetHandlers
[index
])(ioc
, reset_phase
);
2049 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2051 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
2052 * @ioc: Pointer to MPT adapter structure
2053 * @reason: Event word / reason
2054 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
2056 * This routine performs all the steps necessary to bring the IOC
2057 * to a OPERATIONAL state.
2059 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
2064 * -1 if failed to get board READY
2065 * -2 if READY but IOCFacts Failed
2066 * -3 if READY but PrimeIOCFifos Failed
2067 * -4 if READY but IOCInit Failed
2068 * -5 if failed to enable_device and/or request_selected_regions
2069 * -6 if failed to upload firmware
2072 mpt_do_ioc_recovery(MPT_ADAPTER
*ioc
, u32 reason
, int sleepFlag
)
2074 int hard_reset_done
= 0;
2075 int alt_ioc_ready
= 0;
2082 int reset_alt_ioc_active
= 0;
2083 int irq_allocated
= 0;
2086 printk(MYIOC_s_INFO_FMT
"Initiating %s\n", ioc
->name
,
2087 reason
== MPT_HOSTEVENT_IOC_BRINGUP
? "bringup" : "recovery");
2089 /* Disable reply interrupts (also blocks FreeQ) */
2090 CHIPREG_WRITE32(&ioc
->chip
->IntMask
, 0xFFFFFFFF);
2094 if (ioc
->alt_ioc
->active
)
2095 reset_alt_ioc_active
= 1;
2097 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
2098 CHIPREG_WRITE32(&ioc
->alt_ioc
->chip
->IntMask
, 0xFFFFFFFF);
2099 ioc
->alt_ioc
->active
= 0;
2103 if (reason
== MPT_HOSTEVENT_IOC_BRINGUP
)
2106 if ((hard_reset_done
= MakeIocReady(ioc
, hard
, sleepFlag
)) < 0) {
2107 if (hard_reset_done
== -4) {
2108 printk(MYIOC_s_WARN_FMT
"Owned by PEER..skipping!\n",
2111 if (reset_alt_ioc_active
&& ioc
->alt_ioc
) {
2112 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
2113 dprintk(ioc
, printk(MYIOC_s_INFO_FMT
2114 "alt_ioc reply irq re-enabled\n", ioc
->alt_ioc
->name
));
2115 CHIPREG_WRITE32(&ioc
->alt_ioc
->chip
->IntMask
, MPI_HIM_DIM
);
2116 ioc
->alt_ioc
->active
= 1;
2120 printk(MYIOC_s_WARN_FMT
"NOT READY!\n", ioc
->name
);
2125 /* hard_reset_done = 0 if a soft reset was performed
2126 * and 1 if a hard reset was performed.
2128 if (hard_reset_done
&& reset_alt_ioc_active
&& ioc
->alt_ioc
) {
2129 if ((rc
= MakeIocReady(ioc
->alt_ioc
, 0, sleepFlag
)) == 0)
2132 printk(MYIOC_s_WARN_FMT
"alt_ioc not ready!\n", ioc
->alt_ioc
->name
);
2135 for (ii
=0; ii
<5; ii
++) {
2136 /* Get IOC facts! Allow 5 retries */
2137 if ((rc
= GetIocFacts(ioc
, sleepFlag
, reason
)) == 0)
2143 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2144 "Retry IocFacts failed rc=%x\n", ioc
->name
, rc
));
2146 } else if (reason
== MPT_HOSTEVENT_IOC_BRINGUP
) {
2147 MptDisplayIocCapabilities(ioc
);
2150 if (alt_ioc_ready
) {
2151 if ((rc
= GetIocFacts(ioc
->alt_ioc
, sleepFlag
, reason
)) != 0) {
2152 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2153 "Initial Alt IocFacts failed rc=%x\n", ioc
->name
, rc
));
2154 /* Retry - alt IOC was initialized once
2156 rc
= GetIocFacts(ioc
->alt_ioc
, sleepFlag
, reason
);
2159 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2160 "Retry Alt IocFacts failed rc=%x\n", ioc
->name
, rc
));
2162 reset_alt_ioc_active
= 0;
2163 } else if (reason
== MPT_HOSTEVENT_IOC_BRINGUP
) {
2164 MptDisplayIocCapabilities(ioc
->alt_ioc
);
2168 if ((ret
== 0) && (reason
== MPT_HOSTEVENT_IOC_BRINGUP
) &&
2169 (ioc
->facts
.Flags
& MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT
)) {
2170 pci_release_selected_regions(ioc
->pcidev
, ioc
->bars
);
2171 ioc
->bars
= pci_select_bars(ioc
->pcidev
, IORESOURCE_MEM
|
2173 if (pci_enable_device(ioc
->pcidev
))
2175 if (pci_request_selected_regions(ioc
->pcidev
, ioc
->bars
,
2181 * Device is reset now. It must have de-asserted the interrupt line
2182 * (if it was asserted) and it should be safe to register for the
2185 if ((ret
== 0) && (reason
== MPT_HOSTEVENT_IOC_BRINGUP
)) {
2187 if (ioc
->pcidev
->irq
) {
2188 if (ioc
->msi_enable
&& !pci_enable_msi(ioc
->pcidev
))
2189 printk(MYIOC_s_INFO_FMT
"PCI-MSI enabled\n",
2192 ioc
->msi_enable
= 0;
2193 rc
= request_irq(ioc
->pcidev
->irq
, mpt_interrupt
,
2194 IRQF_SHARED
, ioc
->name
, ioc
);
2196 printk(MYIOC_s_ERR_FMT
"Unable to allocate "
2197 "interrupt %d!\n", ioc
->name
, ioc
->pcidev
->irq
);
2198 if (ioc
->msi_enable
)
2199 pci_disable_msi(ioc
->pcidev
);
2203 ioc
->pci_irq
= ioc
->pcidev
->irq
;
2204 pci_set_master(ioc
->pcidev
); /* ?? */
2205 dprintk(ioc
, printk(MYIOC_s_INFO_FMT
"installed at interrupt "
2206 "%d\n", ioc
->name
, ioc
->pcidev
->irq
));
2210 /* Prime reply & request queues!
2211 * (mucho alloc's) Must be done prior to
2212 * init as upper addresses are needed for init.
2213 * If fails, continue with alt-ioc processing
2215 if ((ret
== 0) && ((rc
= PrimeIocFifos(ioc
)) != 0))
2218 /* May need to check/upload firmware & data here!
2219 * If fails, continue with alt-ioc processing
2221 if ((ret
== 0) && ((rc
= SendIocInit(ioc
, sleepFlag
)) != 0))
2224 if (alt_ioc_ready
&& ((rc
= PrimeIocFifos(ioc
->alt_ioc
)) != 0)) {
2225 printk(MYIOC_s_WARN_FMT
": alt_ioc (%d) FIFO mgmt alloc!\n",
2226 ioc
->alt_ioc
->name
, rc
);
2228 reset_alt_ioc_active
= 0;
2231 if (alt_ioc_ready
) {
2232 if ((rc
= SendIocInit(ioc
->alt_ioc
, sleepFlag
)) != 0) {
2234 reset_alt_ioc_active
= 0;
2235 printk(MYIOC_s_WARN_FMT
"alt_ioc (%d) init failure!\n",
2236 ioc
->alt_ioc
->name
, rc
);
2240 if (reason
== MPT_HOSTEVENT_IOC_BRINGUP
){
2241 if (ioc
->upload_fw
) {
2242 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2243 "firmware upload required!\n", ioc
->name
));
2245 /* Controller is not operational, cannot do upload
2248 rc
= mpt_do_upload(ioc
, sleepFlag
);
2250 if (ioc
->alt_ioc
&& ioc
->alt_ioc
->cached_fw
) {
2252 * Maintain only one pointer to FW memory
2253 * so there will not be two attempt to
2254 * downloadboot onboard dual function
2255 * chips (mpt_adapter_disable,
2258 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2259 "mpt_upload: alt_%s has cached_fw=%p \n",
2260 ioc
->name
, ioc
->alt_ioc
->name
, ioc
->alt_ioc
->cached_fw
));
2261 ioc
->cached_fw
= NULL
;
2264 printk(MYIOC_s_WARN_FMT
2265 "firmware upload failure!\n", ioc
->name
);
2273 /* Enable! (reply interrupt) */
2274 CHIPREG_WRITE32(&ioc
->chip
->IntMask
, MPI_HIM_DIM
);
2278 if (reset_alt_ioc_active
&& ioc
->alt_ioc
) {
2279 /* (re)Enable alt-IOC! (reply interrupt) */
2280 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
"alt_ioc reply irq re-enabled\n",
2281 ioc
->alt_ioc
->name
));
2282 CHIPREG_WRITE32(&ioc
->alt_ioc
->chip
->IntMask
, MPI_HIM_DIM
);
2283 ioc
->alt_ioc
->active
= 1;
2286 /* Enable MPT base driver management of EventNotification
2287 * and EventAck handling.
2289 if ((ret
== 0) && (!ioc
->facts
.EventState
))
2290 (void) SendEventNotification(ioc
, 1); /* 1=Enable EventNotification */
2292 if (ioc
->alt_ioc
&& alt_ioc_ready
&& !ioc
->alt_ioc
->facts
.EventState
)
2293 (void) SendEventNotification(ioc
->alt_ioc
, 1); /* 1=Enable EventNotification */
2295 /* Add additional "reason" check before call to GetLanConfigPages
2296 * (combined with GetIoUnitPage2 call). This prevents a somewhat
2297 * recursive scenario; GetLanConfigPages times out, timer expired
2298 * routine calls HardResetHandler, which calls into here again,
2299 * and we try GetLanConfigPages again...
2301 if ((ret
== 0) && (reason
== MPT_HOSTEVENT_IOC_BRINGUP
)) {
2304 * Initalize link list for inactive raid volumes.
2306 mutex_init(&ioc
->raid_data
.inactive_list_mutex
);
2307 INIT_LIST_HEAD(&ioc
->raid_data
.inactive_list
);
2309 if (ioc
->bus_type
== SAS
) {
2311 /* clear persistency table */
2312 if(ioc
->facts
.IOCExceptions
&
2313 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL
) {
2314 ret
= mptbase_sas_persist_operation(ioc
,
2315 MPI_SAS_OP_CLEAR_NOT_PRESENT
);
2322 mpt_findImVolumes(ioc
);
2324 } else if (ioc
->bus_type
== FC
) {
2325 if ((ioc
->pfacts
[0].ProtocolFlags
& MPI_PORTFACTS_PROTOCOL_LAN
) &&
2326 (ioc
->lan_cnfg_page0
.Header
.PageLength
== 0)) {
2328 * Pre-fetch the ports LAN MAC address!
2329 * (LANPage1_t stuff)
2331 (void) GetLanConfigPages(ioc
);
2332 a
= (u8
*)&ioc
->lan_cnfg_page1
.HardwareAddressLow
;
2333 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2334 "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
2335 ioc
->name
, a
[5], a
[4], a
[3], a
[2], a
[1], a
[0]));
2339 /* Get NVRAM and adapter maximums from SPP 0 and 2
2341 mpt_GetScsiPortSettings(ioc
, 0);
2343 /* Get version and length of SDP 1
2345 mpt_readScsiDevicePageHeaders(ioc
, 0);
2349 if (ioc
->facts
.MsgVersion
>= MPI_VERSION_01_02
)
2350 mpt_findImVolumes(ioc
);
2352 /* Check, and possibly reset, the coalescing value
2354 mpt_read_ioc_pg_1(ioc
);
2356 mpt_read_ioc_pg_4(ioc
);
2359 GetIoUnitPage2(ioc
);
2360 mpt_get_manufacturing_pg_0(ioc
);
2364 * Call each currently registered protocol IOC reset handler
2365 * with post-reset indication.
2366 * NOTE: If we're doing _IOC_BRINGUP, there can be no
2367 * MptResetHandlers[] registered yet.
2369 if (hard_reset_done
) {
2371 for (cb_idx
= MPT_MAX_PROTOCOL_DRIVERS
-1; cb_idx
; cb_idx
--) {
2372 if ((ret
== 0) && MptResetHandlers
[cb_idx
]) {
2373 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2374 "Calling IOC post_reset handler #%d\n",
2375 ioc
->name
, cb_idx
));
2376 rc
+= mpt_signal_reset(cb_idx
, ioc
, MPT_IOC_POST_RESET
);
2380 if (alt_ioc_ready
&& MptResetHandlers
[cb_idx
]) {
2381 drsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2382 "Calling IOC post_reset handler #%d\n",
2383 ioc
->alt_ioc
->name
, cb_idx
));
2384 rc
+= mpt_signal_reset(cb_idx
, ioc
->alt_ioc
, MPT_IOC_POST_RESET
);
2388 /* FIXME? Examine results here? */
2392 if ((ret
!= 0) && irq_allocated
) {
2393 free_irq(ioc
->pci_irq
, ioc
);
2394 if (ioc
->msi_enable
)
2395 pci_disable_msi(ioc
->pcidev
);
2400 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2402 * mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2403 * @ioc: Pointer to MPT adapter structure
2404 * @pdev: Pointer to (struct pci_dev) structure
2406 * Search for PCI bus/dev_function which matches
2407 * PCI bus/dev_function (+/-1) for newly discovered 929,
2408 * 929X, 1030 or 1035.
2410 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2411 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2414 mpt_detect_bound_ports(MPT_ADAPTER
*ioc
, struct pci_dev
*pdev
)
2416 struct pci_dev
*peer
=NULL
;
2417 unsigned int slot
= PCI_SLOT(pdev
->devfn
);
2418 unsigned int func
= PCI_FUNC(pdev
->devfn
);
2419 MPT_ADAPTER
*ioc_srch
;
2421 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"PCI device %s devfn=%x/%x,"
2422 " searching for devfn match on %x or %x\n",
2423 ioc
->name
, pci_name(pdev
), pdev
->bus
->number
,
2424 pdev
->devfn
, func
-1, func
+1));
2426 peer
= pci_get_slot(pdev
->bus
, PCI_DEVFN(slot
,func
-1));
2428 peer
= pci_get_slot(pdev
->bus
, PCI_DEVFN(slot
,func
+1));
2433 list_for_each_entry(ioc_srch
, &ioc_list
, list
) {
2434 struct pci_dev
*_pcidev
= ioc_srch
->pcidev
;
2435 if (_pcidev
== peer
) {
2436 /* Paranoia checks */
2437 if (ioc
->alt_ioc
!= NULL
) {
2438 printk(MYIOC_s_WARN_FMT
"Oops, already bound to %s!\n",
2439 ioc
->name
, ioc
->alt_ioc
->name
);
2441 } else if (ioc_srch
->alt_ioc
!= NULL
) {
2442 printk(MYIOC_s_WARN_FMT
"Oops, already bound to %s!\n",
2443 ioc_srch
->name
, ioc_srch
->alt_ioc
->name
);
2446 dprintk(ioc
, printk(MYIOC_s_INFO_FMT
"FOUND! binding to %s\n",
2447 ioc
->name
, ioc_srch
->name
));
2448 ioc_srch
->alt_ioc
= ioc
;
2449 ioc
->alt_ioc
= ioc_srch
;
2455 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2457 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2458 * @ioc: Pointer to MPT adapter structure
2461 mpt_adapter_disable(MPT_ADAPTER
*ioc
)
2466 if (ioc
->cached_fw
!= NULL
) {
2467 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"%s: Pushing FW onto "
2468 "adapter\n", __func__
, ioc
->name
));
2469 if ((ret
= mpt_downloadboot(ioc
, (MpiFwHeader_t
*)
2470 ioc
->cached_fw
, CAN_SLEEP
)) < 0) {
2471 printk(MYIOC_s_WARN_FMT
2472 ": firmware downloadboot failure (%d)!\n",
2477 /* Disable adapter interrupts! */
2478 CHIPREG_WRITE32(&ioc
->chip
->IntMask
, 0xFFFFFFFF);
2480 /* Clear any lingering interrupt */
2481 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
2483 if (ioc
->alloc
!= NULL
) {
2485 dexitprintk(ioc
, printk(MYIOC_s_INFO_FMT
"free @ %p, sz=%d bytes\n",
2486 ioc
->name
, ioc
->alloc
, ioc
->alloc_sz
));
2487 pci_free_consistent(ioc
->pcidev
, sz
,
2488 ioc
->alloc
, ioc
->alloc_dma
);
2489 ioc
->reply_frames
= NULL
;
2490 ioc
->req_frames
= NULL
;
2492 ioc
->alloc_total
-= sz
;
2495 if (ioc
->sense_buf_pool
!= NULL
) {
2496 sz
= (ioc
->req_depth
* MPT_SENSE_BUFFER_ALLOC
);
2497 pci_free_consistent(ioc
->pcidev
, sz
,
2498 ioc
->sense_buf_pool
, ioc
->sense_buf_pool_dma
);
2499 ioc
->sense_buf_pool
= NULL
;
2500 ioc
->alloc_total
-= sz
;
2503 if (ioc
->events
!= NULL
){
2504 sz
= MPTCTL_EVENT_LOG_SIZE
* sizeof(MPT_IOCTL_EVENTS
);
2507 ioc
->alloc_total
-= sz
;
2510 mpt_free_fw_memory(ioc
);
2512 kfree(ioc
->spi_data
.nvram
);
2513 mpt_inactive_raid_list_free(ioc
);
2514 kfree(ioc
->raid_data
.pIocPg2
);
2515 kfree(ioc
->raid_data
.pIocPg3
);
2516 ioc
->spi_data
.nvram
= NULL
;
2517 ioc
->raid_data
.pIocPg3
= NULL
;
2519 if (ioc
->spi_data
.pIocPg4
!= NULL
) {
2520 sz
= ioc
->spi_data
.IocPg4Sz
;
2521 pci_free_consistent(ioc
->pcidev
, sz
,
2522 ioc
->spi_data
.pIocPg4
,
2523 ioc
->spi_data
.IocPg4_dma
);
2524 ioc
->spi_data
.pIocPg4
= NULL
;
2525 ioc
->alloc_total
-= sz
;
2528 if (ioc
->ReqToChain
!= NULL
) {
2529 kfree(ioc
->ReqToChain
);
2530 kfree(ioc
->RequestNB
);
2531 ioc
->ReqToChain
= NULL
;
2534 kfree(ioc
->ChainToChain
);
2535 ioc
->ChainToChain
= NULL
;
2537 if (ioc
->HostPageBuffer
!= NULL
) {
2538 if((ret
= mpt_host_page_access_control(ioc
,
2539 MPI_DB_HPBAC_FREE_BUFFER
, NO_SLEEP
)) != 0) {
2540 printk(MYIOC_s_ERR_FMT
2541 "host page buffers free failed (%d)!\n",
2544 dexitprintk(ioc
, printk(MYIOC_s_INFO_FMT
"HostPageBuffer free @ %p, sz=%d bytes\n",
2545 ioc
->name
, ioc
->HostPageBuffer
, ioc
->HostPageBuffer_sz
));
2546 pci_free_consistent(ioc
->pcidev
, ioc
->HostPageBuffer_sz
,
2547 ioc
->HostPageBuffer
, ioc
->HostPageBuffer_dma
);
2548 ioc
->HostPageBuffer
= NULL
;
2549 ioc
->HostPageBuffer_sz
= 0;
2550 ioc
->alloc_total
-= ioc
->HostPageBuffer_sz
;
2554 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2556 * mpt_adapter_dispose - Free all resources associated with an MPT adapter
2557 * @ioc: Pointer to MPT adapter structure
2559 * This routine unregisters h/w resources and frees all alloc'd memory
2560 * associated with a MPT adapter structure.
2563 mpt_adapter_dispose(MPT_ADAPTER
*ioc
)
2565 int sz_first
, sz_last
;
2570 sz_first
= ioc
->alloc_total
;
2572 mpt_adapter_disable(ioc
);
2574 if (ioc
->pci_irq
!= -1) {
2575 free_irq(ioc
->pci_irq
, ioc
);
2576 if (ioc
->msi_enable
)
2577 pci_disable_msi(ioc
->pcidev
);
2581 if (ioc
->memmap
!= NULL
) {
2582 iounmap(ioc
->memmap
);
2586 pci_disable_device(ioc
->pcidev
);
2587 pci_release_selected_regions(ioc
->pcidev
, ioc
->bars
);
2589 #if defined(CONFIG_MTRR) && 0
2590 if (ioc
->mtrr_reg
> 0) {
2591 mtrr_del(ioc
->mtrr_reg
, 0, 0);
2592 dprintk(ioc
, printk(MYIOC_s_INFO_FMT
"MTRR region de-registered\n", ioc
->name
));
2596 /* Zap the adapter lookup ptr! */
2597 list_del(&ioc
->list
);
2599 sz_last
= ioc
->alloc_total
;
2600 dprintk(ioc
, printk(MYIOC_s_INFO_FMT
"free'd %d of %d bytes\n",
2601 ioc
->name
, sz_first
-sz_last
+(int)sizeof(*ioc
), sz_first
));
2604 ioc
->alt_ioc
->alt_ioc
= NULL
;
2609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2611 * MptDisplayIocCapabilities - Disply IOC's capabilities.
2612 * @ioc: Pointer to MPT adapter structure
2615 MptDisplayIocCapabilities(MPT_ADAPTER
*ioc
)
2619 printk(KERN_INFO
"%s: ", ioc
->name
);
2621 printk("%s: ", ioc
->prod_name
);
2622 printk("Capabilities={");
2624 if (ioc
->pfacts
[0].ProtocolFlags
& MPI_PORTFACTS_PROTOCOL_INITIATOR
) {
2625 printk("Initiator");
2629 if (ioc
->pfacts
[0].ProtocolFlags
& MPI_PORTFACTS_PROTOCOL_TARGET
) {
2630 printk("%sTarget", i
? "," : "");
2634 if (ioc
->pfacts
[0].ProtocolFlags
& MPI_PORTFACTS_PROTOCOL_LAN
) {
2635 printk("%sLAN", i
? "," : "");
2641 * This would probably evoke more questions than it's worth
2643 if (ioc
->pfacts
[0].ProtocolFlags
& MPI_PORTFACTS_PROTOCOL_TARGET
) {
2644 printk("%sLogBusAddr", i
? "," : "");
2652 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2654 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2655 * @ioc: Pointer to MPT_ADAPTER structure
2656 * @force: Force hard KickStart of IOC
2657 * @sleepFlag: Specifies whether the process can sleep
2660 * 1 - DIAG reset and READY
2661 * 0 - READY initially OR soft reset and READY
2662 * -1 - Any failure on KickStart
2663 * -2 - Msg Unit Reset Failed
2664 * -3 - IO Unit Reset Failed
2665 * -4 - IOC owned by a PEER
2668 MakeIocReady(MPT_ADAPTER
*ioc
, int force
, int sleepFlag
)
2673 int hard_reset_done
= 0;
2678 /* Get current [raw] IOC state */
2679 ioc_state
= mpt_GetIocState(ioc
, 0);
2680 dhsprintk(ioc
, printk(MYIOC_s_INFO_FMT
"MakeIocReady [raw] state=%08x\n", ioc
->name
, ioc_state
));
2683 * Check to see if IOC got left/stuck in doorbell handshake
2684 * grip of death. If so, hard reset the IOC.
2686 if (ioc_state
& MPI_DOORBELL_ACTIVE
) {
2688 printk(MYIOC_s_WARN_FMT
"Unexpected doorbell active!\n",
2692 /* Is it already READY? */
2693 if (!statefault
&& (ioc_state
& MPI_IOC_STATE_MASK
) == MPI_IOC_STATE_READY
)
2697 * Check to see if IOC is in FAULT state.
2699 if ((ioc_state
& MPI_IOC_STATE_MASK
) == MPI_IOC_STATE_FAULT
) {
2701 printk(MYIOC_s_WARN_FMT
"IOC is in FAULT state!!!\n",
2703 printk(MYIOC_s_WARN_FMT
" FAULT code = %04xh\n",
2704 ioc
->name
, ioc_state
& MPI_DOORBELL_DATA_MASK
);
2708 * Hmmm... Did it get left operational?
2710 if ((ioc_state
& MPI_IOC_STATE_MASK
) == MPI_IOC_STATE_OPERATIONAL
) {
2711 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"IOC operational unexpected\n",
2715 * If PCI Peer, exit.
2716 * Else, if no fault conditions are present, issue a MessageUnitReset
2717 * Else, fall through to KickStart case
2719 whoinit
= (ioc_state
& MPI_DOORBELL_WHO_INIT_MASK
) >> MPI_DOORBELL_WHO_INIT_SHIFT
;
2720 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
2721 "whoinit 0x%x statefault %d force %d\n",
2722 ioc
->name
, whoinit
, statefault
, force
));
2723 if (whoinit
== MPI_WHOINIT_PCI_PEER
)
2726 if ((statefault
== 0 ) && (force
== 0)) {
2727 if ((r
= SendIocReset(ioc
, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET
, sleepFlag
)) == 0)
2734 hard_reset_done
= KickStart(ioc
, statefault
||force
, sleepFlag
);
2735 if (hard_reset_done
< 0)
2739 * Loop here waiting for IOC to come READY.
2742 cntdn
= ((sleepFlag
== CAN_SLEEP
) ? HZ
: 1000) * 5; /* 5 seconds */
2744 while ((ioc_state
= mpt_GetIocState(ioc
, 1)) != MPI_IOC_STATE_READY
) {
2745 if (ioc_state
== MPI_IOC_STATE_OPERATIONAL
) {
2747 * BIOS or previous driver load left IOC in OP state.
2748 * Reset messaging FIFOs.
2750 if ((r
= SendIocReset(ioc
, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET
, sleepFlag
)) != 0) {
2751 printk(MYIOC_s_ERR_FMT
"IOC msg unit reset failed!\n", ioc
->name
);
2754 } else if (ioc_state
== MPI_IOC_STATE_RESET
) {
2756 * Something is wrong. Try to get IOC back
2759 if ((r
= SendIocReset(ioc
, MPI_FUNCTION_IO_UNIT_RESET
, sleepFlag
)) != 0) {
2760 printk(MYIOC_s_ERR_FMT
"IO unit reset failed!\n", ioc
->name
);
2767 printk(MYIOC_s_ERR_FMT
"Wait IOC_READY state timeout(%d)!\n",
2768 ioc
->name
, (int)((ii
+5)/HZ
));
2772 if (sleepFlag
== CAN_SLEEP
) {
2775 mdelay (1); /* 1 msec delay */
2780 if (statefault
< 3) {
2781 printk(MYIOC_s_INFO_FMT
"Recovered from %s\n",
2783 statefault
==1 ? "stuck handshake" : "IOC FAULT");
2786 return hard_reset_done
;
2789 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2791 * mpt_GetIocState - Get the current state of a MPT adapter.
2792 * @ioc: Pointer to MPT_ADAPTER structure
2793 * @cooked: Request raw or cooked IOC state
2795 * Returns all IOC Doorbell register bits if cooked==0, else just the
2796 * Doorbell bits in MPI_IOC_STATE_MASK.
2799 mpt_GetIocState(MPT_ADAPTER
*ioc
, int cooked
)
2804 s
= CHIPREG_READ32(&ioc
->chip
->Doorbell
);
2805 sc
= s
& MPI_IOC_STATE_MASK
;
2808 ioc
->last_state
= sc
;
2810 return cooked
? sc
: s
;
2813 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2815 * GetIocFacts - Send IOCFacts request to MPT adapter.
2816 * @ioc: Pointer to MPT_ADAPTER structure
2817 * @sleepFlag: Specifies whether the process can sleep
2818 * @reason: If recovery, only update facts.
2820 * Returns 0 for success, non-zero for failure.
2823 GetIocFacts(MPT_ADAPTER
*ioc
, int sleepFlag
, int reason
)
2825 IOCFacts_t get_facts
;
2826 IOCFactsReply_t
*facts
;
2834 /* IOC *must* NOT be in RESET state! */
2835 if (ioc
->last_state
== MPI_IOC_STATE_RESET
) {
2836 printk(MYIOC_s_ERR_FMT
"Can't get IOCFacts NOT READY! (%08x)\n",
2837 ioc
->name
, ioc
->last_state
);
2841 facts
= &ioc
->facts
;
2843 /* Destination (reply area)... */
2844 reply_sz
= sizeof(*facts
);
2845 memset(facts
, 0, reply_sz
);
2847 /* Request area (get_facts on the stack right now!) */
2848 req_sz
= sizeof(get_facts
);
2849 memset(&get_facts
, 0, req_sz
);
2851 get_facts
.Function
= MPI_FUNCTION_IOC_FACTS
;
2852 /* Assert: All other get_facts fields are zero! */
2854 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2855 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2856 ioc
->name
, req_sz
, reply_sz
));
2858 /* No non-zero fields in the get_facts request are greater than
2859 * 1 byte in size, so we can just fire it off as is.
2861 r
= mpt_handshake_req_reply_wait(ioc
, req_sz
, (u32
*)&get_facts
,
2862 reply_sz
, (u16
*)facts
, 5 /*seconds*/, sleepFlag
);
2867 * Now byte swap (GRRR) the necessary fields before any further
2868 * inspection of reply contents.
2870 * But need to do some sanity checks on MsgLength (byte) field
2871 * to make sure we don't zero IOC's req_sz!
2873 /* Did we get a valid reply? */
2874 if (facts
->MsgLength
> offsetof(IOCFactsReply_t
, RequestFrameSize
)/sizeof(u32
)) {
2875 if (reason
== MPT_HOSTEVENT_IOC_BRINGUP
) {
2877 * If not been here, done that, save off first WhoInit value
2879 if (ioc
->FirstWhoInit
== WHOINIT_UNKNOWN
)
2880 ioc
->FirstWhoInit
= facts
->WhoInit
;
2883 facts
->MsgVersion
= le16_to_cpu(facts
->MsgVersion
);
2884 facts
->MsgContext
= le32_to_cpu(facts
->MsgContext
);
2885 facts
->IOCExceptions
= le16_to_cpu(facts
->IOCExceptions
);
2886 facts
->IOCStatus
= le16_to_cpu(facts
->IOCStatus
);
2887 facts
->IOCLogInfo
= le32_to_cpu(facts
->IOCLogInfo
);
2888 status
= le16_to_cpu(facts
->IOCStatus
) & MPI_IOCSTATUS_MASK
;
2889 /* CHECKME! IOCStatus, IOCLogInfo */
2891 facts
->ReplyQueueDepth
= le16_to_cpu(facts
->ReplyQueueDepth
);
2892 facts
->RequestFrameSize
= le16_to_cpu(facts
->RequestFrameSize
);
2895 * FC f/w version changed between 1.1 and 1.2
2896 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2897 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2899 if (facts
->MsgVersion
< 0x0102) {
2901 * Handle old FC f/w style, convert to new...
2903 u16 oldv
= le16_to_cpu(facts
->Reserved_0101_FWVersion
);
2904 facts
->FWVersion
.Word
=
2905 ((oldv
<<12) & 0xFF000000) |
2906 ((oldv
<<8) & 0x000FFF00);
2908 facts
->FWVersion
.Word
= le32_to_cpu(facts
->FWVersion
.Word
);
2910 facts
->ProductID
= le16_to_cpu(facts
->ProductID
);
2911 if ((ioc
->facts
.ProductID
& MPI_FW_HEADER_PID_PROD_MASK
)
2912 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI
)
2913 ioc
->ir_firmware
= 1;
2914 facts
->CurrentHostMfaHighAddr
=
2915 le32_to_cpu(facts
->CurrentHostMfaHighAddr
);
2916 facts
->GlobalCredits
= le16_to_cpu(facts
->GlobalCredits
);
2917 facts
->CurrentSenseBufferHighAddr
=
2918 le32_to_cpu(facts
->CurrentSenseBufferHighAddr
);
2919 facts
->CurReplyFrameSize
=
2920 le16_to_cpu(facts
->CurReplyFrameSize
);
2921 facts
->IOCCapabilities
= le32_to_cpu(facts
->IOCCapabilities
);
2924 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2925 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2926 * to 14 in MPI-1.01.0x.
2928 if (facts
->MsgLength
>= (offsetof(IOCFactsReply_t
,FWImageSize
) + 7)/4 &&
2929 facts
->MsgVersion
> 0x0100) {
2930 facts
->FWImageSize
= le32_to_cpu(facts
->FWImageSize
);
2933 sz
= facts
->FWImageSize
;
2938 facts
->FWImageSize
= sz
;
2940 if (!facts
->RequestFrameSize
) {
2941 /* Something is wrong! */
2942 printk(MYIOC_s_ERR_FMT
"IOC reported invalid 0 request size!\n",
2947 r
= sz
= facts
->BlockSize
;
2948 vv
= ((63 / (sz
* 4)) + 1) & 0x03;
2949 ioc
->NB_for_64_byte_frame
= vv
;
2955 ioc
->NBShiftFactor
= shiftFactor
;
2956 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
2957 "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2958 ioc
->name
, vv
, shiftFactor
, r
));
2960 if (reason
== MPT_HOSTEVENT_IOC_BRINGUP
) {
2962 * Set values for this IOC's request & reply frame sizes,
2963 * and request & reply queue depths...
2965 ioc
->req_sz
= min(MPT_DEFAULT_FRAME_SIZE
, facts
->RequestFrameSize
* 4);
2966 ioc
->req_depth
= min_t(int, MPT_MAX_REQ_DEPTH
, facts
->GlobalCredits
);
2967 ioc
->reply_sz
= MPT_REPLY_FRAME_SIZE
;
2968 ioc
->reply_depth
= min_t(int, MPT_DEFAULT_REPLY_DEPTH
, facts
->ReplyQueueDepth
);
2970 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"reply_sz=%3d, reply_depth=%4d\n",
2971 ioc
->name
, ioc
->reply_sz
, ioc
->reply_depth
));
2972 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"req_sz =%3d, req_depth =%4d\n",
2973 ioc
->name
, ioc
->req_sz
, ioc
->req_depth
));
2975 /* Get port facts! */
2976 if ( (r
= GetPortFacts(ioc
, 0, sleepFlag
)) != 0 )
2980 printk(MYIOC_s_ERR_FMT
2981 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2982 ioc
->name
, facts
->MsgLength
, (offsetof(IOCFactsReply_t
,
2983 RequestFrameSize
)/sizeof(u32
)));
2990 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2992 * GetPortFacts - Send PortFacts request to MPT adapter.
2993 * @ioc: Pointer to MPT_ADAPTER structure
2994 * @portnum: Port number
2995 * @sleepFlag: Specifies whether the process can sleep
2997 * Returns 0 for success, non-zero for failure.
3000 GetPortFacts(MPT_ADAPTER
*ioc
, int portnum
, int sleepFlag
)
3002 PortFacts_t get_pfacts
;
3003 PortFactsReply_t
*pfacts
;
3009 /* IOC *must* NOT be in RESET state! */
3010 if (ioc
->last_state
== MPI_IOC_STATE_RESET
) {
3011 printk(MYIOC_s_ERR_FMT
"Can't get PortFacts NOT READY! (%08x)\n",
3012 ioc
->name
, ioc
->last_state
);
3016 pfacts
= &ioc
->pfacts
[portnum
];
3018 /* Destination (reply area)... */
3019 reply_sz
= sizeof(*pfacts
);
3020 memset(pfacts
, 0, reply_sz
);
3022 /* Request area (get_pfacts on the stack right now!) */
3023 req_sz
= sizeof(get_pfacts
);
3024 memset(&get_pfacts
, 0, req_sz
);
3026 get_pfacts
.Function
= MPI_FUNCTION_PORT_FACTS
;
3027 get_pfacts
.PortNumber
= portnum
;
3028 /* Assert: All other get_pfacts fields are zero! */
3030 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending get PortFacts(%d) request\n",
3031 ioc
->name
, portnum
));
3033 /* No non-zero fields in the get_pfacts request are greater than
3034 * 1 byte in size, so we can just fire it off as is.
3036 ii
= mpt_handshake_req_reply_wait(ioc
, req_sz
, (u32
*)&get_pfacts
,
3037 reply_sz
, (u16
*)pfacts
, 5 /*seconds*/, sleepFlag
);
3041 /* Did we get a valid reply? */
3043 /* Now byte swap the necessary fields in the response. */
3044 pfacts
->MsgContext
= le32_to_cpu(pfacts
->MsgContext
);
3045 pfacts
->IOCStatus
= le16_to_cpu(pfacts
->IOCStatus
);
3046 pfacts
->IOCLogInfo
= le32_to_cpu(pfacts
->IOCLogInfo
);
3047 pfacts
->MaxDevices
= le16_to_cpu(pfacts
->MaxDevices
);
3048 pfacts
->PortSCSIID
= le16_to_cpu(pfacts
->PortSCSIID
);
3049 pfacts
->ProtocolFlags
= le16_to_cpu(pfacts
->ProtocolFlags
);
3050 pfacts
->MaxPostedCmdBuffers
= le16_to_cpu(pfacts
->MaxPostedCmdBuffers
);
3051 pfacts
->MaxPersistentIDs
= le16_to_cpu(pfacts
->MaxPersistentIDs
);
3052 pfacts
->MaxLanBuckets
= le16_to_cpu(pfacts
->MaxLanBuckets
);
3054 max_id
= (ioc
->bus_type
== SAS
) ? pfacts
->PortSCSIID
:
3056 ioc
->devices_per_bus
= (max_id
> 255) ? 256 : max_id
;
3057 ioc
->number_of_buses
= (ioc
->devices_per_bus
< 256) ? 1 : max_id
/256;
3060 * Place all the devices on channels
3064 if (mpt_channel_mapping
) {
3065 ioc
->devices_per_bus
= 1;
3066 ioc
->number_of_buses
= (max_id
> 255) ? 255 : max_id
;
3072 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3074 * SendIocInit - Send IOCInit request to MPT adapter.
3075 * @ioc: Pointer to MPT_ADAPTER structure
3076 * @sleepFlag: Specifies whether the process can sleep
3078 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
3080 * Returns 0 for success, non-zero for failure.
3083 SendIocInit(MPT_ADAPTER
*ioc
, int sleepFlag
)
3086 MPIDefaultReply_t init_reply
;
3092 memset(&ioc_init
, 0, sizeof(ioc_init
));
3093 memset(&init_reply
, 0, sizeof(init_reply
));
3095 ioc_init
.WhoInit
= MPI_WHOINIT_HOST_DRIVER
;
3096 ioc_init
.Function
= MPI_FUNCTION_IOC_INIT
;
3098 /* If we are in a recovery mode and we uploaded the FW image,
3099 * then this pointer is not NULL. Skip the upload a second time.
3100 * Set this flag if cached_fw set for either IOC.
3102 if (ioc
->facts
.Flags
& MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT
)
3106 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"upload_fw %d facts.Flags=%x\n",
3107 ioc
->name
, ioc
->upload_fw
, ioc
->facts
.Flags
));
3109 ioc_init
.MaxDevices
= (U8
)ioc
->devices_per_bus
;
3110 ioc_init
.MaxBuses
= (U8
)ioc
->number_of_buses
;
3111 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"facts.MsgVersion=%x\n",
3112 ioc
->name
, ioc
->facts
.MsgVersion
));
3113 if (ioc
->facts
.MsgVersion
>= MPI_VERSION_01_05
) {
3114 // set MsgVersion and HeaderVersion host driver was built with
3115 ioc_init
.MsgVersion
= cpu_to_le16(MPI_VERSION
);
3116 ioc_init
.HeaderVersion
= cpu_to_le16(MPI_HEADER_VERSION
);
3118 if (ioc
->facts
.Flags
& MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT
) {
3119 ioc_init
.HostPageBufferSGE
= ioc
->facts
.HostPageBufferSGE
;
3120 } else if(mpt_host_page_alloc(ioc
, &ioc_init
))
3123 ioc_init
.ReplyFrameSize
= cpu_to_le16(ioc
->reply_sz
); /* in BYTES */
3125 if (sizeof(dma_addr_t
) == sizeof(u64
)) {
3126 /* Save the upper 32-bits of the request
3127 * (reply) and sense buffers.
3129 ioc_init
.HostMfaHighAddr
= cpu_to_le32((u32
)((u64
)ioc
->alloc_dma
>> 32));
3130 ioc_init
.SenseBufferHighAddr
= cpu_to_le32((u32
)((u64
)ioc
->sense_buf_pool_dma
>> 32));
3132 /* Force 32-bit addressing */
3133 ioc_init
.HostMfaHighAddr
= cpu_to_le32(0);
3134 ioc_init
.SenseBufferHighAddr
= cpu_to_le32(0);
3137 ioc
->facts
.CurrentHostMfaHighAddr
= ioc_init
.HostMfaHighAddr
;
3138 ioc
->facts
.CurrentSenseBufferHighAddr
= ioc_init
.SenseBufferHighAddr
;
3139 ioc
->facts
.MaxDevices
= ioc_init
.MaxDevices
;
3140 ioc
->facts
.MaxBuses
= ioc_init
.MaxBuses
;
3142 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending IOCInit (req @ %p)\n",
3143 ioc
->name
, &ioc_init
));
3145 r
= mpt_handshake_req_reply_wait(ioc
, sizeof(IOCInit_t
), (u32
*)&ioc_init
,
3146 sizeof(MPIDefaultReply_t
), (u16
*)&init_reply
, 10 /*seconds*/, sleepFlag
);
3148 printk(MYIOC_s_ERR_FMT
"Sending IOCInit failed(%d)!\n",ioc
->name
, r
);
3152 /* No need to byte swap the multibyte fields in the reply
3153 * since we don't even look at its contents.
3156 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending PortEnable (req @ %p)\n",
3157 ioc
->name
, &ioc_init
));
3159 if ((r
= SendPortEnable(ioc
, 0, sleepFlag
)) != 0) {
3160 printk(MYIOC_s_ERR_FMT
"Sending PortEnable failed(%d)!\n",ioc
->name
, r
);
3164 /* YIKES! SUPER IMPORTANT!!!
3165 * Poll IocState until _OPERATIONAL while IOC is doing
3166 * LoopInit and TargetDiscovery!
3169 cntdn
= ((sleepFlag
== CAN_SLEEP
) ? HZ
: 1000) * 60; /* 60 seconds */
3170 state
= mpt_GetIocState(ioc
, 1);
3171 while (state
!= MPI_IOC_STATE_OPERATIONAL
&& --cntdn
) {
3172 if (sleepFlag
== CAN_SLEEP
) {
3179 printk(MYIOC_s_ERR_FMT
"Wait IOC_OP state timeout(%d)!\n",
3180 ioc
->name
, (int)((count
+5)/HZ
));
3184 state
= mpt_GetIocState(ioc
, 1);
3187 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Wait IOC_OPERATIONAL state (cnt=%d)\n",
3190 ioc
->aen_event_read_flag
=0;
3194 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3196 * SendPortEnable - Send PortEnable request to MPT adapter port.
3197 * @ioc: Pointer to MPT_ADAPTER structure
3198 * @portnum: Port number to enable
3199 * @sleepFlag: Specifies whether the process can sleep
3201 * Send PortEnable to bring IOC to OPERATIONAL state.
3203 * Returns 0 for success, non-zero for failure.
3206 SendPortEnable(MPT_ADAPTER
*ioc
, int portnum
, int sleepFlag
)
3208 PortEnable_t port_enable
;
3209 MPIDefaultReply_t reply_buf
;
3214 /* Destination... */
3215 reply_sz
= sizeof(MPIDefaultReply_t
);
3216 memset(&reply_buf
, 0, reply_sz
);
3218 req_sz
= sizeof(PortEnable_t
);
3219 memset(&port_enable
, 0, req_sz
);
3221 port_enable
.Function
= MPI_FUNCTION_PORT_ENABLE
;
3222 port_enable
.PortNumber
= portnum
;
3223 /* port_enable.ChainOffset = 0; */
3224 /* port_enable.MsgFlags = 0; */
3225 /* port_enable.MsgContext = 0; */
3227 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending Port(%d)Enable (req @ %p)\n",
3228 ioc
->name
, portnum
, &port_enable
));
3230 /* RAID FW may take a long time to enable
3232 if (ioc
->ir_firmware
|| ioc
->bus_type
== SAS
) {
3233 rc
= mpt_handshake_req_reply_wait(ioc
, req_sz
,
3234 (u32
*)&port_enable
, reply_sz
, (u16
*)&reply_buf
,
3235 300 /*seconds*/, sleepFlag
);
3237 rc
= mpt_handshake_req_reply_wait(ioc
, req_sz
,
3238 (u32
*)&port_enable
, reply_sz
, (u16
*)&reply_buf
,
3239 30 /*seconds*/, sleepFlag
);
3245 * mpt_alloc_fw_memory - allocate firmware memory
3246 * @ioc: Pointer to MPT_ADAPTER structure
3247 * @size: total FW bytes
3249 * If memory has already been allocated, the same (cached) value
3252 * Return 0 if successfull, or non-zero for failure
3255 mpt_alloc_fw_memory(MPT_ADAPTER
*ioc
, int size
)
3259 if (ioc
->cached_fw
) {
3260 rc
= 0; /* use already allocated memory */
3263 else if (ioc
->alt_ioc
&& ioc
->alt_ioc
->cached_fw
) {
3264 ioc
->cached_fw
= ioc
->alt_ioc
->cached_fw
; /* use alt_ioc's memory */
3265 ioc
->cached_fw_dma
= ioc
->alt_ioc
->cached_fw_dma
;
3269 ioc
->cached_fw
= pci_alloc_consistent(ioc
->pcidev
, size
, &ioc
->cached_fw_dma
);
3270 if (!ioc
->cached_fw
) {
3271 printk(MYIOC_s_ERR_FMT
"Unable to allocate memory for the cached firmware image!\n",
3275 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"FW Image @ %p[%p], sz=%d[%x] bytes\n",
3276 ioc
->name
, ioc
->cached_fw
, (void *)(ulong
)ioc
->cached_fw_dma
, size
, size
));
3277 ioc
->alloc_total
+= size
;
3285 * mpt_free_fw_memory - free firmware memory
3286 * @ioc: Pointer to MPT_ADAPTER structure
3288 * If alt_img is NULL, delete from ioc structure.
3289 * Else, delete a secondary image in same format.
3292 mpt_free_fw_memory(MPT_ADAPTER
*ioc
)
3296 if (!ioc
->cached_fw
)
3299 sz
= ioc
->facts
.FWImageSize
;
3300 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3301 ioc
->name
, ioc
->cached_fw
, (void *)(ulong
)ioc
->cached_fw_dma
, sz
, sz
));
3302 pci_free_consistent(ioc
->pcidev
, sz
, ioc
->cached_fw
, ioc
->cached_fw_dma
);
3303 ioc
->alloc_total
-= sz
;
3304 ioc
->cached_fw
= NULL
;
3307 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3309 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3310 * @ioc: Pointer to MPT_ADAPTER structure
3311 * @sleepFlag: Specifies whether the process can sleep
3313 * Returns 0 for success, >0 for handshake failure
3314 * <0 for fw upload failure.
3316 * Remark: If bound IOC and a successful FWUpload was performed
3317 * on the bound IOC, the second image is discarded
3318 * and memory is free'd. Both channels must upload to prevent
3319 * IOC from running in degraded mode.
3322 mpt_do_upload(MPT_ADAPTER
*ioc
, int sleepFlag
)
3324 u8 reply
[sizeof(FWUploadReply_t
)];
3325 FWUpload_t
*prequest
;
3326 FWUploadReply_t
*preply
;
3327 FWUploadTCSGE_t
*ptcsge
;
3330 int ii
, sz
, reply_sz
;
3333 /* If the image size is 0, we are done.
3335 if ((sz
= ioc
->facts
.FWImageSize
) == 0)
3338 if (mpt_alloc_fw_memory(ioc
, ioc
->facts
.FWImageSize
) != 0)
3341 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3342 ioc
->name
, ioc
->cached_fw
, (void *)(ulong
)ioc
->cached_fw_dma
, sz
, sz
));
3344 prequest
= (sleepFlag
== NO_SLEEP
) ? kzalloc(ioc
->req_sz
, GFP_ATOMIC
) :
3345 kzalloc(ioc
->req_sz
, GFP_KERNEL
);
3347 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"fw upload failed "
3348 "while allocating memory \n", ioc
->name
));
3349 mpt_free_fw_memory(ioc
);
3353 preply
= (FWUploadReply_t
*)&reply
;
3355 reply_sz
= sizeof(reply
);
3356 memset(preply
, 0, reply_sz
);
3358 prequest
->ImageType
= MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM
;
3359 prequest
->Function
= MPI_FUNCTION_FW_UPLOAD
;
3361 ptcsge
= (FWUploadTCSGE_t
*) &prequest
->SGL
;
3362 ptcsge
->DetailsLength
= 12;
3363 ptcsge
->Flags
= MPI_SGE_FLAGS_TRANSACTION_ELEMENT
;
3364 ptcsge
->ImageSize
= cpu_to_le32(sz
);
3367 sgeoffset
= sizeof(FWUpload_t
) - sizeof(SGE_MPI_UNION
) + sizeof(FWUploadTCSGE_t
);
3369 flagsLength
= MPT_SGE_FLAGS_SSIMPLE_READ
| sz
;
3370 mpt_add_sge((char *)ptcsge
, flagsLength
, ioc
->cached_fw_dma
);
3372 sgeoffset
+= sizeof(u32
) + sizeof(dma_addr_t
);
3373 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
": Sending FW Upload (req @ %p) sgeoffset=%d \n",
3374 ioc
->name
, prequest
, sgeoffset
));
3375 DBG_DUMP_FW_REQUEST_FRAME(ioc
, (u32
*)prequest
);
3377 ii
= mpt_handshake_req_reply_wait(ioc
, sgeoffset
, (u32
*)prequest
,
3378 reply_sz
, (u16
*)preply
, 65 /*seconds*/, sleepFlag
);
3380 dinitprintk(ioc
, printk(MYIOC_s_INFO_FMT
": FW Upload completed rc=%x \n", ioc
->name
, ii
));
3382 cmdStatus
= -EFAULT
;
3384 /* Handshake transfer was complete and successful.
3385 * Check the Reply Frame.
3387 int status
, transfer_sz
;
3388 status
= le16_to_cpu(preply
->IOCStatus
);
3389 if (status
== MPI_IOCSTATUS_SUCCESS
) {
3390 transfer_sz
= le32_to_cpu(preply
->ActualImageSize
);
3391 if (transfer_sz
== sz
)
3395 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
": do_upload cmdStatus=%d \n",
3396 ioc
->name
, cmdStatus
));
3401 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
": fw upload failed, freeing image \n",
3403 mpt_free_fw_memory(ioc
);
3410 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3412 * mpt_downloadboot - DownloadBoot code
3413 * @ioc: Pointer to MPT_ADAPTER structure
3414 * @pFwHeader: Pointer to firmware header info
3415 * @sleepFlag: Specifies whether the process can sleep
3417 * FwDownloadBoot requires Programmed IO access.
3419 * Returns 0 for success
3420 * -1 FW Image size is 0
3421 * -2 No valid cached_fw Pointer
3422 * <0 for fw upload failure.
3425 mpt_downloadboot(MPT_ADAPTER
*ioc
, MpiFwHeader_t
*pFwHeader
, int sleepFlag
)
3427 MpiExtImageHeader_t
*pExtImage
;
3437 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3438 ioc
->name
, pFwHeader
->ImageSize
, pFwHeader
->ImageSize
, pFwHeader
));
3440 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, 0xFF);
3441 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_1ST_KEY_VALUE
);
3442 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_2ND_KEY_VALUE
);
3443 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_3RD_KEY_VALUE
);
3444 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_4TH_KEY_VALUE
);
3445 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_5TH_KEY_VALUE
);
3447 CHIPREG_WRITE32(&ioc
->chip
->Diagnostic
, (MPI_DIAG_PREVENT_IOC_BOOT
| MPI_DIAG_DISABLE_ARM
));
3450 if (sleepFlag
== CAN_SLEEP
) {
3456 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3457 CHIPREG_WRITE32(&ioc
->chip
->Diagnostic
, diag0val
| MPI_DIAG_RESET_ADAPTER
);
3459 for (count
= 0; count
< 30; count
++) {
3460 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3461 if (!(diag0val
& MPI_DIAG_RESET_ADAPTER
)) {
3462 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"RESET_ADAPTER cleared, count=%d\n",
3467 if (sleepFlag
== CAN_SLEEP
) {
3474 if ( count
== 30 ) {
3475 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"downloadboot failed! "
3476 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3477 ioc
->name
, diag0val
));
3481 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, 0xFF);
3482 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_1ST_KEY_VALUE
);
3483 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_2ND_KEY_VALUE
);
3484 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_3RD_KEY_VALUE
);
3485 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_4TH_KEY_VALUE
);
3486 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_5TH_KEY_VALUE
);
3488 /* Set the DiagRwEn and Disable ARM bits */
3489 CHIPREG_WRITE32(&ioc
->chip
->Diagnostic
, (MPI_DIAG_RW_ENABLE
| MPI_DIAG_DISABLE_ARM
));
3491 fwSize
= (pFwHeader
->ImageSize
+ 3)/4;
3492 ptrFw
= (u32
*) pFwHeader
;
3494 /* Write the LoadStartAddress to the DiagRw Address Register
3495 * using Programmed IO
3497 if (ioc
->errata_flag_1064
)
3498 pci_enable_io_access(ioc
->pcidev
);
3500 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwAddress
, pFwHeader
->LoadStartAddress
);
3501 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"LoadStart addr written 0x%x \n",
3502 ioc
->name
, pFwHeader
->LoadStartAddress
));
3504 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Write FW Image: 0x%x bytes @ %p\n",
3505 ioc
->name
, fwSize
*4, ptrFw
));
3507 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwData
, *ptrFw
++);
3510 nextImage
= pFwHeader
->NextImageHeaderOffset
;
3512 pExtImage
= (MpiExtImageHeader_t
*) ((char *)pFwHeader
+ nextImage
);
3514 load_addr
= pExtImage
->LoadStartAddress
;
3516 fwSize
= (pExtImage
->ImageSize
+ 3) >> 2;
3517 ptrFw
= (u32
*)pExtImage
;
3519 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3520 ioc
->name
, fwSize
*4, fwSize
*4, ptrFw
, load_addr
));
3521 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwAddress
, load_addr
);
3524 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwData
, *ptrFw
++);
3526 nextImage
= pExtImage
->NextImageHeaderOffset
;
3529 /* Write the IopResetVectorRegAddr */
3530 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Write IopResetVector Addr=%x! \n", ioc
->name
, pFwHeader
->IopResetRegAddr
));
3531 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwAddress
, pFwHeader
->IopResetRegAddr
);
3533 /* Write the IopResetVectorValue */
3534 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Write IopResetVector Value=%x! \n", ioc
->name
, pFwHeader
->IopResetVectorValue
));
3535 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwData
, pFwHeader
->IopResetVectorValue
);
3537 /* Clear the internal flash bad bit - autoincrementing register,
3538 * so must do two writes.
3540 if (ioc
->bus_type
== SPI
) {
3542 * 1030 and 1035 H/W errata, workaround to access
3543 * the ClearFlashBadSignatureBit
3545 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwAddress
, 0x3F000000);
3546 diagRwData
= CHIPREG_PIO_READ32(&ioc
->pio_chip
->DiagRwData
);
3547 diagRwData
|= 0x40000000;
3548 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwAddress
, 0x3F000000);
3549 CHIPREG_PIO_WRITE32(&ioc
->pio_chip
->DiagRwData
, diagRwData
);
3551 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3552 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3553 CHIPREG_WRITE32(&ioc
->chip
->Diagnostic
, diag0val
|
3554 MPI_DIAG_CLEAR_FLASH_BAD_SIG
);
3557 if (sleepFlag
== CAN_SLEEP
) {
3564 if (ioc
->errata_flag_1064
)
3565 pci_disable_io_access(ioc
->pcidev
);
3567 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3568 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"downloadboot diag0val=%x, "
3569 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3570 ioc
->name
, diag0val
));
3571 diag0val
&= ~(MPI_DIAG_PREVENT_IOC_BOOT
| MPI_DIAG_DISABLE_ARM
| MPI_DIAG_RW_ENABLE
);
3572 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"downloadboot now diag0val=%x\n",
3573 ioc
->name
, diag0val
));
3574 CHIPREG_WRITE32(&ioc
->chip
->Diagnostic
, diag0val
);
3576 /* Write 0xFF to reset the sequencer */
3577 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, 0xFF);
3579 if (ioc
->bus_type
== SAS
) {
3580 ioc_state
= mpt_GetIocState(ioc
, 0);
3581 if ( (GetIocFacts(ioc
, sleepFlag
,
3582 MPT_HOSTEVENT_IOC_BRINGUP
)) != 0 ) {
3583 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"GetIocFacts failed: IocState=%x\n",
3584 ioc
->name
, ioc_state
));
3589 for (count
=0; count
<HZ
*20; count
++) {
3590 if ((ioc_state
= mpt_GetIocState(ioc
, 0)) & MPI_IOC_STATE_READY
) {
3591 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
3592 "downloadboot successful! (count=%d) IocState=%x\n",
3593 ioc
->name
, count
, ioc_state
));
3594 if (ioc
->bus_type
== SAS
) {
3597 if ((SendIocInit(ioc
, sleepFlag
)) != 0) {
3598 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
3599 "downloadboot: SendIocInit failed\n",
3603 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
3604 "downloadboot: SendIocInit successful\n",
3608 if (sleepFlag
== CAN_SLEEP
) {
3614 ddlprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
3615 "downloadboot failed! IocState=%x\n",ioc
->name
, ioc_state
));
3619 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3621 * KickStart - Perform hard reset of MPT adapter.
3622 * @ioc: Pointer to MPT_ADAPTER structure
3623 * @force: Force hard reset
3624 * @sleepFlag: Specifies whether the process can sleep
3626 * This routine places MPT adapter in diagnostic mode via the
3627 * WriteSequence register, and then performs a hard reset of adapter
3628 * via the Diagnostic register.
3630 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3631 * or NO_SLEEP (interrupt thread, use mdelay)
3632 * force - 1 if doorbell active, board fault state
3633 * board operational, IOC_RECOVERY or
3634 * IOC_BRINGUP and there is an alt_ioc.
3638 * 1 - hard reset, READY
3639 * 0 - no reset due to History bit, READY
3640 * -1 - no reset due to History bit but not READY
3641 * OR reset but failed to come READY
3642 * -2 - no reset, could not enter DIAG mode
3643 * -3 - reset but bad FW bit
3646 KickStart(MPT_ADAPTER
*ioc
, int force
, int sleepFlag
)
3648 int hard_reset_done
= 0;
3652 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"KickStarting!\n", ioc
->name
));
3653 if (ioc
->bus_type
== SPI
) {
3654 /* Always issue a Msg Unit Reset first. This will clear some
3655 * SCSI bus hang conditions.
3657 SendIocReset(ioc
, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET
, sleepFlag
);
3659 if (sleepFlag
== CAN_SLEEP
) {
3666 hard_reset_done
= mpt_diag_reset(ioc
, force
, sleepFlag
);
3667 if (hard_reset_done
< 0)
3668 return hard_reset_done
;
3670 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Diagnostic reset successful!\n",
3673 cntdn
= ((sleepFlag
== CAN_SLEEP
) ? HZ
: 1000) * 2; /* 2 seconds */
3674 for (cnt
=0; cnt
<cntdn
; cnt
++) {
3675 ioc_state
= mpt_GetIocState(ioc
, 1);
3676 if ((ioc_state
== MPI_IOC_STATE_READY
) || (ioc_state
== MPI_IOC_STATE_OPERATIONAL
)) {
3677 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"KickStart successful! (cnt=%d)\n",
3679 return hard_reset_done
;
3681 if (sleepFlag
== CAN_SLEEP
) {
3688 dinitprintk(ioc
, printk(MYIOC_s_ERR_FMT
"Failed to come READY after reset! IocState=%x\n",
3689 ioc
->name
, mpt_GetIocState(ioc
, 0)));
3693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3695 * mpt_diag_reset - Perform hard reset of the adapter.
3696 * @ioc: Pointer to MPT_ADAPTER structure
3697 * @ignore: Set if to honor and clear to ignore
3698 * the reset history bit
3699 * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3700 * else set to NO_SLEEP (use mdelay instead)
3702 * This routine places the adapter in diagnostic mode via the
3703 * WriteSequence register and then performs a hard reset of adapter
3704 * via the Diagnostic register. Adapter should be in ready state
3705 * upon successful completion.
3707 * Returns: 1 hard reset successful
3708 * 0 no reset performed because reset history bit set
3709 * -2 enabling diagnostic mode failed
3710 * -3 diagnostic reset failed
3713 mpt_diag_reset(MPT_ADAPTER
*ioc
, int ignore
, int sleepFlag
)
3717 int hard_reset_done
= 0;
3720 MpiFwHeader_t
*cached_fw
; /* Pointer to FW */
3722 /* Clear any existing interrupts */
3723 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
3725 if (ioc
->pcidev
->device
== MPI_MANUFACTPAGE_DEVID_SAS1078
) {
3726 drsprintk(ioc
, printk(MYIOC_s_WARN_FMT
"%s: Doorbell=%p; 1078 reset "
3727 "address=%p\n", ioc
->name
, __func__
,
3728 &ioc
->chip
->Doorbell
, &ioc
->chip
->Reset_1078
));
3729 CHIPREG_WRITE32(&ioc
->chip
->Reset_1078
, 0x07);
3730 if (sleepFlag
== CAN_SLEEP
)
3735 for (count
= 0; count
< 60; count
++) {
3736 doorbell
= CHIPREG_READ32(&ioc
->chip
->Doorbell
);
3737 doorbell
&= MPI_IOC_STATE_MASK
;
3739 drsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
3740 "looking for READY STATE: doorbell=%x"
3742 ioc
->name
, doorbell
, count
));
3743 if (doorbell
== MPI_IOC_STATE_READY
) {
3748 if (sleepFlag
== CAN_SLEEP
)
3756 /* Use "Diagnostic reset" method! (only thing available!) */
3757 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3759 if (ioc
->debug_level
& MPT_DEBUG
) {
3761 diag1val
= CHIPREG_READ32(&ioc
->alt_ioc
->chip
->Diagnostic
);
3762 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"DbG1: diag0=%08x, diag1=%08x\n",
3763 ioc
->name
, diag0val
, diag1val
));
3766 /* Do the reset if we are told to ignore the reset history
3767 * or if the reset history is 0
3769 if (ignore
|| !(diag0val
& MPI_DIAG_RESET_HISTORY
)) {
3770 while ((diag0val
& MPI_DIAG_DRWE
) == 0) {
3771 /* Write magic sequence to WriteSequence register
3772 * Loop until in diagnostic mode
3774 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, 0xFF);
3775 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_1ST_KEY_VALUE
);
3776 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_2ND_KEY_VALUE
);
3777 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_3RD_KEY_VALUE
);
3778 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_4TH_KEY_VALUE
);
3779 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_5TH_KEY_VALUE
);
3782 if (sleepFlag
== CAN_SLEEP
) {
3790 printk(MYIOC_s_ERR_FMT
"Enable Diagnostic mode FAILED! (%02xh)\n",
3791 ioc
->name
, diag0val
);
3796 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3798 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Wrote magic DiagWriteEn sequence (%x)\n",
3799 ioc
->name
, diag0val
));
3802 if (ioc
->debug_level
& MPT_DEBUG
) {
3804 diag1val
= CHIPREG_READ32(&ioc
->alt_ioc
->chip
->Diagnostic
);
3805 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"DbG2: diag0=%08x, diag1=%08x\n",
3806 ioc
->name
, diag0val
, diag1val
));
3809 * Disable the ARM (Bug fix)
3812 CHIPREG_WRITE32(&ioc
->chip
->Diagnostic
, diag0val
| MPI_DIAG_DISABLE_ARM
);
3816 * Now hit the reset bit in the Diagnostic register
3817 * (THE BIG HAMMER!) (Clears DRWE bit).
3819 CHIPREG_WRITE32(&ioc
->chip
->Diagnostic
, diag0val
| MPI_DIAG_RESET_ADAPTER
);
3820 hard_reset_done
= 1;
3821 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Diagnostic reset performed\n",
3825 * Call each currently registered protocol IOC reset handler
3826 * with pre-reset indication.
3827 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3828 * MptResetHandlers[] registered yet.
3834 for (cb_idx
= MPT_MAX_PROTOCOL_DRIVERS
-1; cb_idx
; cb_idx
--) {
3835 if (MptResetHandlers
[cb_idx
]) {
3836 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
3837 "Calling IOC pre_reset handler #%d\n",
3838 ioc
->name
, cb_idx
));
3839 r
+= mpt_signal_reset(cb_idx
, ioc
, MPT_IOC_PRE_RESET
);
3841 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
3842 "Calling alt-%s pre_reset handler #%d\n",
3843 ioc
->name
, ioc
->alt_ioc
->name
, cb_idx
));
3844 r
+= mpt_signal_reset(cb_idx
, ioc
->alt_ioc
, MPT_IOC_PRE_RESET
);
3848 /* FIXME? Examine results here? */
3852 cached_fw
= (MpiFwHeader_t
*)ioc
->cached_fw
;
3853 else if (ioc
->alt_ioc
&& ioc
->alt_ioc
->cached_fw
)
3854 cached_fw
= (MpiFwHeader_t
*)ioc
->alt_ioc
->cached_fw
;
3858 /* If the DownloadBoot operation fails, the
3859 * IOC will be left unusable. This is a fatal error
3860 * case. _diag_reset will return < 0
3862 for (count
= 0; count
< 30; count
++) {
3863 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3864 if (!(diag0val
& MPI_DIAG_RESET_ADAPTER
)) {
3868 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"cached_fw: diag0val=%x count=%d\n",
3869 ioc
->name
, diag0val
, count
));
3871 if (sleepFlag
== CAN_SLEEP
) {
3877 if ((count
= mpt_downloadboot(ioc
, cached_fw
, sleepFlag
)) < 0) {
3878 printk(MYIOC_s_WARN_FMT
3879 "firmware downloadboot failure (%d)!\n", ioc
->name
, count
);
3883 /* Wait for FW to reload and for board
3884 * to go to the READY state.
3885 * Maximum wait is 60 seconds.
3886 * If fail, no error will check again
3887 * with calling program.
3889 for (count
= 0; count
< 60; count
++) {
3890 doorbell
= CHIPREG_READ32(&ioc
->chip
->Doorbell
);
3891 doorbell
&= MPI_IOC_STATE_MASK
;
3893 if (doorbell
== MPI_IOC_STATE_READY
) {
3898 if (sleepFlag
== CAN_SLEEP
) {
3907 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3908 if (ioc
->debug_level
& MPT_DEBUG
) {
3910 diag1val
= CHIPREG_READ32(&ioc
->alt_ioc
->chip
->Diagnostic
);
3911 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"DbG3: diag0=%08x, diag1=%08x\n",
3912 ioc
->name
, diag0val
, diag1val
));
3915 /* Clear RESET_HISTORY bit! Place board in the
3916 * diagnostic mode to update the diag register.
3918 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3920 while ((diag0val
& MPI_DIAG_DRWE
) == 0) {
3921 /* Write magic sequence to WriteSequence register
3922 * Loop until in diagnostic mode
3924 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, 0xFF);
3925 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_1ST_KEY_VALUE
);
3926 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_2ND_KEY_VALUE
);
3927 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_3RD_KEY_VALUE
);
3928 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_4TH_KEY_VALUE
);
3929 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, MPI_WRSEQ_5TH_KEY_VALUE
);
3932 if (sleepFlag
== CAN_SLEEP
) {
3940 printk(MYIOC_s_ERR_FMT
"Enable Diagnostic mode FAILED! (%02xh)\n",
3941 ioc
->name
, diag0val
);
3944 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3946 diag0val
&= ~MPI_DIAG_RESET_HISTORY
;
3947 CHIPREG_WRITE32(&ioc
->chip
->Diagnostic
, diag0val
);
3948 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3949 if (diag0val
& MPI_DIAG_RESET_HISTORY
) {
3950 printk(MYIOC_s_WARN_FMT
"ResetHistory bit failed to clear!\n",
3954 /* Disable Diagnostic Mode
3956 CHIPREG_WRITE32(&ioc
->chip
->WriteSequence
, 0xFFFFFFFF);
3958 /* Check FW reload status flags.
3960 diag0val
= CHIPREG_READ32(&ioc
->chip
->Diagnostic
);
3961 if (diag0val
& (MPI_DIAG_FLASH_BAD_SIG
| MPI_DIAG_RESET_ADAPTER
| MPI_DIAG_DISABLE_ARM
)) {
3962 printk(MYIOC_s_ERR_FMT
"Diagnostic reset FAILED! (%02xh)\n",
3963 ioc
->name
, diag0val
);
3967 if (ioc
->debug_level
& MPT_DEBUG
) {
3969 diag1val
= CHIPREG_READ32(&ioc
->alt_ioc
->chip
->Diagnostic
);
3970 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"DbG4: diag0=%08x, diag1=%08x\n",
3971 ioc
->name
, diag0val
, diag1val
));
3975 * Reset flag that says we've enabled event notification
3977 ioc
->facts
.EventState
= 0;
3980 ioc
->alt_ioc
->facts
.EventState
= 0;
3982 return hard_reset_done
;
3985 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3987 * SendIocReset - Send IOCReset request to MPT adapter.
3988 * @ioc: Pointer to MPT_ADAPTER structure
3989 * @reset_type: reset type, expected values are
3990 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3991 * @sleepFlag: Specifies whether the process can sleep
3993 * Send IOCReset request to the MPT adapter.
3995 * Returns 0 for success, non-zero for failure.
3998 SendIocReset(MPT_ADAPTER
*ioc
, u8 reset_type
, int sleepFlag
)
4004 drsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending IOC reset(0x%02x)!\n",
4005 ioc
->name
, reset_type
));
4006 CHIPREG_WRITE32(&ioc
->chip
->Doorbell
, reset_type
<<MPI_DOORBELL_FUNCTION_SHIFT
);
4007 if ((r
= WaitForDoorbellAck(ioc
, 5, sleepFlag
)) < 0)
4010 /* FW ACK'd request, wait for READY state
4013 cntdn
= ((sleepFlag
== CAN_SLEEP
) ? HZ
: 1000) * 15; /* 15 seconds */
4015 while ((state
= mpt_GetIocState(ioc
, 1)) != MPI_IOC_STATE_READY
) {
4019 if (sleepFlag
!= CAN_SLEEP
)
4022 printk(MYIOC_s_ERR_FMT
"Wait IOC_READY state timeout(%d)!\n",
4023 ioc
->name
, (int)((count
+5)/HZ
));
4027 if (sleepFlag
== CAN_SLEEP
) {
4030 mdelay (1); /* 1 msec delay */
4035 * Cleanup all event stuff for this IOC; re-issue EventNotification
4036 * request if needed.
4038 if (ioc
->facts
.Function
)
4039 ioc
->facts
.EventState
= 0;
4044 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4046 * initChainBuffers - Allocate memory for and initialize chain buffers
4047 * @ioc: Pointer to MPT_ADAPTER structure
4049 * Allocates memory for and initializes chain buffers,
4050 * chain buffer control arrays and spinlock.
4053 initChainBuffers(MPT_ADAPTER
*ioc
)
4056 int sz
, ii
, num_chain
;
4057 int scale
, num_sge
, numSGE
;
4059 /* ReqToChain size must equal the req_depth
4062 if (ioc
->ReqToChain
== NULL
) {
4063 sz
= ioc
->req_depth
* sizeof(int);
4064 mem
= kmalloc(sz
, GFP_ATOMIC
);
4068 ioc
->ReqToChain
= (int *) mem
;
4069 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ReqToChain alloc @ %p, sz=%d bytes\n",
4070 ioc
->name
, mem
, sz
));
4071 mem
= kmalloc(sz
, GFP_ATOMIC
);
4075 ioc
->RequestNB
= (int *) mem
;
4076 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"RequestNB alloc @ %p, sz=%d bytes\n",
4077 ioc
->name
, mem
, sz
));
4079 for (ii
= 0; ii
< ioc
->req_depth
; ii
++) {
4080 ioc
->ReqToChain
[ii
] = MPT_HOST_NO_CHAIN
;
4083 /* ChainToChain size must equal the total number
4084 * of chain buffers to be allocated.
4087 * Calculate the number of chain buffers needed(plus 1) per I/O
4088 * then multiply the maximum number of simultaneous cmds
4090 * num_sge = num sge in request frame + last chain buffer
4091 * scale = num sge per chain buffer if no chain element
4093 scale
= ioc
->req_sz
/(sizeof(dma_addr_t
) + sizeof(u32
));
4094 if (sizeof(dma_addr_t
) == sizeof(u64
))
4095 num_sge
= scale
+ (ioc
->req_sz
- 60) / (sizeof(dma_addr_t
) + sizeof(u32
));
4097 num_sge
= 1+ scale
+ (ioc
->req_sz
- 64) / (sizeof(dma_addr_t
) + sizeof(u32
));
4099 if (sizeof(dma_addr_t
) == sizeof(u64
)) {
4100 numSGE
= (scale
- 1) * (ioc
->facts
.MaxChainDepth
-1) + scale
+
4101 (ioc
->req_sz
- 60) / (sizeof(dma_addr_t
) + sizeof(u32
));
4103 numSGE
= 1 + (scale
- 1) * (ioc
->facts
.MaxChainDepth
-1) + scale
+
4104 (ioc
->req_sz
- 64) / (sizeof(dma_addr_t
) + sizeof(u32
));
4106 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"num_sge=%d numSGE=%d\n",
4107 ioc
->name
, num_sge
, numSGE
));
4109 if ( numSGE
> MPT_SCSI_SG_DEPTH
)
4110 numSGE
= MPT_SCSI_SG_DEPTH
;
4113 while (numSGE
- num_sge
> 0) {
4115 num_sge
+= (scale
- 1);
4119 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Now numSGE=%d num_sge=%d num_chain=%d\n",
4120 ioc
->name
, numSGE
, num_sge
, num_chain
));
4122 if (ioc
->bus_type
== SPI
)
4123 num_chain
*= MPT_SCSI_CAN_QUEUE
;
4125 num_chain
*= MPT_FC_CAN_QUEUE
;
4127 ioc
->num_chain
= num_chain
;
4129 sz
= num_chain
* sizeof(int);
4130 if (ioc
->ChainToChain
== NULL
) {
4131 mem
= kmalloc(sz
, GFP_ATOMIC
);
4135 ioc
->ChainToChain
= (int *) mem
;
4136 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ChainToChain alloc @ %p, sz=%d bytes\n",
4137 ioc
->name
, mem
, sz
));
4139 mem
= (u8
*) ioc
->ChainToChain
;
4141 memset(mem
, 0xFF, sz
);
4145 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4147 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
4148 * @ioc: Pointer to MPT_ADAPTER structure
4150 * This routine allocates memory for the MPT reply and request frame
4151 * pools (if necessary), and primes the IOC reply FIFO with
4154 * Returns 0 for success, non-zero for failure.
4157 PrimeIocFifos(MPT_ADAPTER
*ioc
)
4160 unsigned long flags
;
4161 dma_addr_t alloc_dma
;
4163 int i
, reply_sz
, sz
, total_size
, num_chain
;
4165 /* Prime reply FIFO... */
4167 if (ioc
->reply_frames
== NULL
) {
4168 if ( (num_chain
= initChainBuffers(ioc
)) < 0)
4171 total_size
= reply_sz
= (ioc
->reply_sz
* ioc
->reply_depth
);
4172 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4173 ioc
->name
, ioc
->reply_sz
, ioc
->reply_depth
));
4174 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ReplyBuffer sz=%d[%x] bytes\n",
4175 ioc
->name
, reply_sz
, reply_sz
));
4177 sz
= (ioc
->req_sz
* ioc
->req_depth
);
4178 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4179 ioc
->name
, ioc
->req_sz
, ioc
->req_depth
));
4180 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"RequestBuffer sz=%d[%x] bytes\n",
4181 ioc
->name
, sz
, sz
));
4184 sz
= num_chain
* ioc
->req_sz
; /* chain buffer pool size */
4185 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4186 ioc
->name
, ioc
->req_sz
, num_chain
));
4187 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4188 ioc
->name
, sz
, sz
, num_chain
));
4191 mem
= pci_alloc_consistent(ioc
->pcidev
, total_size
, &alloc_dma
);
4193 printk(MYIOC_s_ERR_FMT
"Unable to allocate Reply, Request, Chain Buffers!\n",
4198 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4199 ioc
->name
, mem
, (void *)(ulong
)alloc_dma
, total_size
, total_size
));
4201 memset(mem
, 0, total_size
);
4202 ioc
->alloc_total
+= total_size
;
4204 ioc
->alloc_dma
= alloc_dma
;
4205 ioc
->alloc_sz
= total_size
;
4206 ioc
->reply_frames
= (MPT_FRAME_HDR
*) mem
;
4207 ioc
->reply_frames_low_dma
= (u32
) (alloc_dma
& 0xFFFFFFFF);
4209 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ReplyBuffers @ %p[%p]\n",
4210 ioc
->name
, ioc
->reply_frames
, (void *)(ulong
)alloc_dma
));
4212 alloc_dma
+= reply_sz
;
4215 /* Request FIFO - WE manage this! */
4217 ioc
->req_frames
= (MPT_FRAME_HDR
*) mem
;
4218 ioc
->req_frames_dma
= alloc_dma
;
4220 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"RequestBuffers @ %p[%p]\n",
4221 ioc
->name
, mem
, (void *)(ulong
)alloc_dma
));
4223 ioc
->req_frames_low_dma
= (u32
) (alloc_dma
& 0xFFFFFFFF);
4225 #if defined(CONFIG_MTRR) && 0
4227 * Enable Write Combining MTRR for IOC's memory region.
4228 * (at least as much as we can; "size and base must be
4229 * multiples of 4 kiB"
4231 ioc
->mtrr_reg
= mtrr_add(ioc
->req_frames_dma
,
4233 MTRR_TYPE_WRCOMB
, 1);
4234 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"MTRR region registered (base:size=%08x:%x)\n",
4235 ioc
->name
, ioc
->req_frames_dma
, sz
));
4238 for (i
= 0; i
< ioc
->req_depth
; i
++) {
4239 alloc_dma
+= ioc
->req_sz
;
4243 ioc
->ChainBuffer
= mem
;
4244 ioc
->ChainBufferDMA
= alloc_dma
;
4246 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ChainBuffers @ %p(%p)\n",
4247 ioc
->name
, ioc
->ChainBuffer
, (void *)(ulong
)ioc
->ChainBufferDMA
));
4249 /* Initialize the free chain Q.
4252 INIT_LIST_HEAD(&ioc
->FreeChainQ
);
4254 /* Post the chain buffers to the FreeChainQ.
4256 mem
= (u8
*)ioc
->ChainBuffer
;
4257 for (i
=0; i
< num_chain
; i
++) {
4258 mf
= (MPT_FRAME_HDR
*) mem
;
4259 list_add_tail(&mf
->u
.frame
.linkage
.list
, &ioc
->FreeChainQ
);
4263 /* Initialize Request frames linked list
4265 alloc_dma
= ioc
->req_frames_dma
;
4266 mem
= (u8
*) ioc
->req_frames
;
4268 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
4269 INIT_LIST_HEAD(&ioc
->FreeQ
);
4270 for (i
= 0; i
< ioc
->req_depth
; i
++) {
4271 mf
= (MPT_FRAME_HDR
*) mem
;
4273 /* Queue REQUESTs *internally*! */
4274 list_add_tail(&mf
->u
.frame
.linkage
.list
, &ioc
->FreeQ
);
4278 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
4280 sz
= (ioc
->req_depth
* MPT_SENSE_BUFFER_ALLOC
);
4281 ioc
->sense_buf_pool
=
4282 pci_alloc_consistent(ioc
->pcidev
, sz
, &ioc
->sense_buf_pool_dma
);
4283 if (ioc
->sense_buf_pool
== NULL
) {
4284 printk(MYIOC_s_ERR_FMT
"Unable to allocate Sense Buffers!\n",
4289 ioc
->sense_buf_low_dma
= (u32
) (ioc
->sense_buf_pool_dma
& 0xFFFFFFFF);
4290 ioc
->alloc_total
+= sz
;
4291 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"SenseBuffers @ %p[%p]\n",
4292 ioc
->name
, ioc
->sense_buf_pool
, (void *)(ulong
)ioc
->sense_buf_pool_dma
));
4296 /* Post Reply frames to FIFO
4298 alloc_dma
= ioc
->alloc_dma
;
4299 dinitprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"ReplyBuffers @ %p[%p]\n",
4300 ioc
->name
, ioc
->reply_frames
, (void *)(ulong
)alloc_dma
));
4302 for (i
= 0; i
< ioc
->reply_depth
; i
++) {
4303 /* Write each address to the IOC! */
4304 CHIPREG_WRITE32(&ioc
->chip
->ReplyFifo
, alloc_dma
);
4305 alloc_dma
+= ioc
->reply_sz
;
4311 if (ioc
->alloc
!= NULL
) {
4313 pci_free_consistent(ioc
->pcidev
,
4315 ioc
->alloc
, ioc
->alloc_dma
);
4316 ioc
->reply_frames
= NULL
;
4317 ioc
->req_frames
= NULL
;
4318 ioc
->alloc_total
-= sz
;
4320 if (ioc
->sense_buf_pool
!= NULL
) {
4321 sz
= (ioc
->req_depth
* MPT_SENSE_BUFFER_ALLOC
);
4322 pci_free_consistent(ioc
->pcidev
,
4324 ioc
->sense_buf_pool
, ioc
->sense_buf_pool_dma
);
4325 ioc
->sense_buf_pool
= NULL
;
4330 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4332 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4333 * from IOC via doorbell handshake method.
4334 * @ioc: Pointer to MPT_ADAPTER structure
4335 * @reqBytes: Size of the request in bytes
4336 * @req: Pointer to MPT request frame
4337 * @replyBytes: Expected size of the reply in bytes
4338 * @u16reply: Pointer to area where reply should be written
4339 * @maxwait: Max wait time for a reply (in seconds)
4340 * @sleepFlag: Specifies whether the process can sleep
4342 * NOTES: It is the callers responsibility to byte-swap fields in the
4343 * request which are greater than 1 byte in size. It is also the
4344 * callers responsibility to byte-swap response fields which are
4345 * greater than 1 byte in size.
4347 * Returns 0 for success, non-zero for failure.
4350 mpt_handshake_req_reply_wait(MPT_ADAPTER
*ioc
, int reqBytes
, u32
*req
,
4351 int replyBytes
, u16
*u16reply
, int maxwait
, int sleepFlag
)
4353 MPIDefaultReply_t
*mptReply
;
4358 * Get ready to cache a handshake reply
4360 ioc
->hs_reply_idx
= 0;
4361 mptReply
= (MPIDefaultReply_t
*) ioc
->hs_reply
;
4362 mptReply
->MsgLength
= 0;
4365 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4366 * then tell IOC that we want to handshake a request of N words.
4367 * (WRITE u32val to Doorbell reg).
4369 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
4370 CHIPREG_WRITE32(&ioc
->chip
->Doorbell
,
4371 ((MPI_FUNCTION_HANDSHAKE
<<MPI_DOORBELL_FUNCTION_SHIFT
) |
4372 ((reqBytes
/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT
)));
4375 * Wait for IOC's doorbell handshake int
4377 if ((t
= WaitForDoorbellInt(ioc
, 5, sleepFlag
)) < 0)
4380 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4381 ioc
->name
, reqBytes
, t
, failcnt
? " - MISSING DOORBELL HANDSHAKE!" : ""));
4383 /* Read doorbell and check for active bit */
4384 if (!(CHIPREG_READ32(&ioc
->chip
->Doorbell
) & MPI_DOORBELL_ACTIVE
))
4388 * Clear doorbell int (WRITE 0 to IntStatus reg),
4389 * then wait for IOC to ACKnowledge that it's ready for
4390 * our handshake request.
4392 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
4393 if (!failcnt
&& (t
= WaitForDoorbellAck(ioc
, 5, sleepFlag
)) < 0)
4398 u8
*req_as_bytes
= (u8
*) req
;
4401 * Stuff request words via doorbell handshake,
4402 * with ACK from IOC for each.
4404 for (ii
= 0; !failcnt
&& ii
< reqBytes
/4; ii
++) {
4405 u32 word
= ((req_as_bytes
[(ii
*4) + 0] << 0) |
4406 (req_as_bytes
[(ii
*4) + 1] << 8) |
4407 (req_as_bytes
[(ii
*4) + 2] << 16) |
4408 (req_as_bytes
[(ii
*4) + 3] << 24));
4410 CHIPREG_WRITE32(&ioc
->chip
->Doorbell
, word
);
4411 if ((t
= WaitForDoorbellAck(ioc
, 5, sleepFlag
)) < 0)
4415 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Handshake request frame (@%p) header\n", ioc
->name
, req
));
4416 DBG_DUMP_REQUEST_FRAME_HDR(ioc
, (u32
*)req
);
4418 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"HandShake request post done, WaitCnt=%d%s\n",
4419 ioc
->name
, t
, failcnt
? " - MISSING DOORBELL ACK!" : ""));
4422 * Wait for completion of doorbell handshake reply from the IOC
4424 if (!failcnt
&& (t
= WaitForDoorbellReply(ioc
, maxwait
, sleepFlag
)) < 0)
4427 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"HandShake reply count=%d%s\n",
4428 ioc
->name
, t
, failcnt
? " - MISSING DOORBELL REPLY!" : ""));
4431 * Copy out the cached reply...
4433 for (ii
=0; ii
< min(replyBytes
/2,mptReply
->MsgLength
*2); ii
++)
4434 u16reply
[ii
] = ioc
->hs_reply
[ii
];
4442 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4444 * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4445 * @ioc: Pointer to MPT_ADAPTER structure
4446 * @howlong: How long to wait (in seconds)
4447 * @sleepFlag: Specifies whether the process can sleep
4449 * This routine waits (up to ~2 seconds max) for IOC doorbell
4450 * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4451 * bit in its IntStatus register being clear.
4453 * Returns a negative value on failure, else wait loop count.
4456 WaitForDoorbellAck(MPT_ADAPTER
*ioc
, int howlong
, int sleepFlag
)
4462 cntdn
= 1000 * howlong
;
4464 if (sleepFlag
== CAN_SLEEP
) {
4467 intstat
= CHIPREG_READ32(&ioc
->chip
->IntStatus
);
4468 if (! (intstat
& MPI_HIS_IOP_DOORBELL_STATUS
))
4475 intstat
= CHIPREG_READ32(&ioc
->chip
->IntStatus
);
4476 if (! (intstat
& MPI_HIS_IOP_DOORBELL_STATUS
))
4483 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"WaitForDoorbell ACK (count=%d)\n",
4488 printk(MYIOC_s_ERR_FMT
"Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4489 ioc
->name
, count
, intstat
);
4493 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4495 * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4496 * @ioc: Pointer to MPT_ADAPTER structure
4497 * @howlong: How long to wait (in seconds)
4498 * @sleepFlag: Specifies whether the process can sleep
4500 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4501 * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4503 * Returns a negative value on failure, else wait loop count.
4506 WaitForDoorbellInt(MPT_ADAPTER
*ioc
, int howlong
, int sleepFlag
)
4512 cntdn
= 1000 * howlong
;
4513 if (sleepFlag
== CAN_SLEEP
) {
4515 intstat
= CHIPREG_READ32(&ioc
->chip
->IntStatus
);
4516 if (intstat
& MPI_HIS_DOORBELL_INTERRUPT
)
4523 intstat
= CHIPREG_READ32(&ioc
->chip
->IntStatus
);
4524 if (intstat
& MPI_HIS_DOORBELL_INTERRUPT
)
4532 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4533 ioc
->name
, count
, howlong
));
4537 printk(MYIOC_s_ERR_FMT
"Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4538 ioc
->name
, count
, intstat
);
4542 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4544 * WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4545 * @ioc: Pointer to MPT_ADAPTER structure
4546 * @howlong: How long to wait (in seconds)
4547 * @sleepFlag: Specifies whether the process can sleep
4549 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4550 * Reply is cached to IOC private area large enough to hold a maximum
4551 * of 128 bytes of reply data.
4553 * Returns a negative value on failure, else size of reply in WORDS.
4556 WaitForDoorbellReply(MPT_ADAPTER
*ioc
, int howlong
, int sleepFlag
)
4561 u16
*hs_reply
= ioc
->hs_reply
;
4562 volatile MPIDefaultReply_t
*mptReply
= (MPIDefaultReply_t
*) ioc
->hs_reply
;
4565 hs_reply
[0] = hs_reply
[1] = hs_reply
[7] = 0;
4568 * Get first two u16's so we can look at IOC's intended reply MsgLength
4571 if ((t
= WaitForDoorbellInt(ioc
, howlong
, sleepFlag
)) < 0) {
4574 hs_reply
[u16cnt
++] = le16_to_cpu(CHIPREG_READ32(&ioc
->chip
->Doorbell
) & 0x0000FFFF);
4575 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
4576 if ((t
= WaitForDoorbellInt(ioc
, 5, sleepFlag
)) < 0)
4579 hs_reply
[u16cnt
++] = le16_to_cpu(CHIPREG_READ32(&ioc
->chip
->Doorbell
) & 0x0000FFFF);
4580 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
4584 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"WaitCnt=%d First handshake reply word=%08x%s\n",
4585 ioc
->name
, t
, le32_to_cpu(*(u32
*)hs_reply
),
4586 failcnt
? " - MISSING DOORBELL HANDSHAKE!" : ""));
4589 * If no error (and IOC said MsgLength is > 0), piece together
4590 * reply 16 bits at a time.
4592 for (u16cnt
=2; !failcnt
&& u16cnt
< (2 * mptReply
->MsgLength
); u16cnt
++) {
4593 if ((t
= WaitForDoorbellInt(ioc
, 5, sleepFlag
)) < 0)
4595 hword
= le16_to_cpu(CHIPREG_READ32(&ioc
->chip
->Doorbell
) & 0x0000FFFF);
4596 /* don't overflow our IOC hs_reply[] buffer! */
4597 if (u16cnt
< ARRAY_SIZE(ioc
->hs_reply
))
4598 hs_reply
[u16cnt
] = hword
;
4599 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
4602 if (!failcnt
&& (t
= WaitForDoorbellInt(ioc
, 5, sleepFlag
)) < 0)
4604 CHIPREG_WRITE32(&ioc
->chip
->IntStatus
, 0);
4607 printk(MYIOC_s_ERR_FMT
"Handshake reply failure!\n",
4612 else if (u16cnt
!= (2 * mptReply
->MsgLength
)) {
4615 else if ((mptReply
->IOCStatus
& MPI_IOCSTATUS_MASK
) != MPI_IOCSTATUS_SUCCESS
) {
4620 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Got Handshake reply:\n", ioc
->name
));
4621 DBG_DUMP_REPLY_FRAME(ioc
, (u32
*)mptReply
);
4623 dhsprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4624 ioc
->name
, t
, u16cnt
/2));
4628 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4630 * GetLanConfigPages - Fetch LANConfig pages.
4631 * @ioc: Pointer to MPT_ADAPTER structure
4633 * Return: 0 for success
4634 * -ENOMEM if no memory available
4635 * -EPERM if not allowed due to ISR context
4636 * -EAGAIN if no msg frames currently available
4637 * -EFAULT for non-successful reply or no reply (timeout)
4640 GetLanConfigPages(MPT_ADAPTER
*ioc
)
4642 ConfigPageHeader_t hdr
;
4644 LANPage0_t
*ppage0_alloc
;
4645 dma_addr_t page0_dma
;
4646 LANPage1_t
*ppage1_alloc
;
4647 dma_addr_t page1_dma
;
4652 /* Get LAN Page 0 header */
4653 hdr
.PageVersion
= 0;
4656 hdr
.PageType
= MPI_CONFIG_PAGETYPE_LAN
;
4657 cfg
.cfghdr
.hdr
= &hdr
;
4659 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
4664 if ((rc
= mpt_config(ioc
, &cfg
)) != 0)
4667 if (hdr
.PageLength
> 0) {
4668 data_sz
= hdr
.PageLength
* 4;
4669 ppage0_alloc
= (LANPage0_t
*) pci_alloc_consistent(ioc
->pcidev
, data_sz
, &page0_dma
);
4672 memset((u8
*)ppage0_alloc
, 0, data_sz
);
4673 cfg
.physAddr
= page0_dma
;
4674 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
4676 if ((rc
= mpt_config(ioc
, &cfg
)) == 0) {
4678 copy_sz
= min_t(int, sizeof(LANPage0_t
), data_sz
);
4679 memcpy(&ioc
->lan_cnfg_page0
, ppage0_alloc
, copy_sz
);
4683 pci_free_consistent(ioc
->pcidev
, data_sz
, (u8
*) ppage0_alloc
, page0_dma
);
4686 * Normalize endianness of structure data,
4687 * by byte-swapping all > 1 byte fields!
4696 /* Get LAN Page 1 header */
4697 hdr
.PageVersion
= 0;
4700 hdr
.PageType
= MPI_CONFIG_PAGETYPE_LAN
;
4701 cfg
.cfghdr
.hdr
= &hdr
;
4703 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
4707 if ((rc
= mpt_config(ioc
, &cfg
)) != 0)
4710 if (hdr
.PageLength
== 0)
4713 data_sz
= hdr
.PageLength
* 4;
4715 ppage1_alloc
= (LANPage1_t
*) pci_alloc_consistent(ioc
->pcidev
, data_sz
, &page1_dma
);
4717 memset((u8
*)ppage1_alloc
, 0, data_sz
);
4718 cfg
.physAddr
= page1_dma
;
4719 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
4721 if ((rc
= mpt_config(ioc
, &cfg
)) == 0) {
4723 copy_sz
= min_t(int, sizeof(LANPage1_t
), data_sz
);
4724 memcpy(&ioc
->lan_cnfg_page1
, ppage1_alloc
, copy_sz
);
4727 pci_free_consistent(ioc
->pcidev
, data_sz
, (u8
*) ppage1_alloc
, page1_dma
);
4730 * Normalize endianness of structure data,
4731 * by byte-swapping all > 1 byte fields!
4739 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4741 * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
4742 * @ioc: Pointer to MPT_ADAPTER structure
4743 * @persist_opcode: see below
4745 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4746 * devices not currently present.
4747 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4749 * NOTE: Don't use not this function during interrupt time.
4751 * Returns 0 for success, non-zero error
4754 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4756 mptbase_sas_persist_operation(MPT_ADAPTER
*ioc
, u8 persist_opcode
)
4758 SasIoUnitControlRequest_t
*sasIoUnitCntrReq
;
4759 SasIoUnitControlReply_t
*sasIoUnitCntrReply
;
4760 MPT_FRAME_HDR
*mf
= NULL
;
4761 MPIHeader_t
*mpi_hdr
;
4764 /* insure garbage is not sent to fw */
4765 switch(persist_opcode
) {
4767 case MPI_SAS_OP_CLEAR_NOT_PRESENT
:
4768 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT
:
4776 printk("%s: persist_opcode=%x\n",__func__
, persist_opcode
);
4778 /* Get a MF for this command.
4780 if ((mf
= mpt_get_msg_frame(mpt_base_index
, ioc
)) == NULL
) {
4781 printk("%s: no msg frames!\n",__func__
);
4785 mpi_hdr
= (MPIHeader_t
*) mf
;
4786 sasIoUnitCntrReq
= (SasIoUnitControlRequest_t
*)mf
;
4787 memset(sasIoUnitCntrReq
,0,sizeof(SasIoUnitControlRequest_t
));
4788 sasIoUnitCntrReq
->Function
= MPI_FUNCTION_SAS_IO_UNIT_CONTROL
;
4789 sasIoUnitCntrReq
->MsgContext
= mpi_hdr
->MsgContext
;
4790 sasIoUnitCntrReq
->Operation
= persist_opcode
;
4792 init_timer(&ioc
->persist_timer
);
4793 ioc
->persist_timer
.data
= (unsigned long) ioc
;
4794 ioc
->persist_timer
.function
= mpt_timer_expired
;
4795 ioc
->persist_timer
.expires
= jiffies
+ HZ
*10 /* 10 sec */;
4796 ioc
->persist_wait_done
=0;
4797 add_timer(&ioc
->persist_timer
);
4798 mpt_put_msg_frame(mpt_base_index
, ioc
, mf
);
4799 wait_event(mpt_waitq
, ioc
->persist_wait_done
);
4801 sasIoUnitCntrReply
=
4802 (SasIoUnitControlReply_t
*)ioc
->persist_reply_frame
;
4803 if (le16_to_cpu(sasIoUnitCntrReply
->IOCStatus
) != MPI_IOCSTATUS_SUCCESS
) {
4804 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4806 sasIoUnitCntrReply
->IOCStatus
,
4807 sasIoUnitCntrReply
->IOCLogInfo
);
4811 printk("%s: success\n",__func__
);
4815 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4818 mptbase_raid_process_event_data(MPT_ADAPTER
*ioc
,
4819 MpiEventDataRaid_t
* pRaidEventData
)
4828 volume
= pRaidEventData
->VolumeID
;
4829 reason
= pRaidEventData
->ReasonCode
;
4830 disk
= pRaidEventData
->PhysDiskNum
;
4831 status
= le32_to_cpu(pRaidEventData
->SettingsStatus
);
4832 flags
= (status
>> 0) & 0xff;
4833 state
= (status
>> 8) & 0xff;
4835 if (reason
== MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED
) {
4839 if ((reason
>= MPI_EVENT_RAID_RC_PHYSDISK_CREATED
&&
4840 reason
<= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED
) ||
4841 (reason
== MPI_EVENT_RAID_RC_SMART_DATA
)) {
4842 printk(MYIOC_s_INFO_FMT
"RAID STATUS CHANGE for PhysDisk %d id=%d\n",
4843 ioc
->name
, disk
, volume
);
4845 printk(MYIOC_s_INFO_FMT
"RAID STATUS CHANGE for VolumeID %d\n",
4850 case MPI_EVENT_RAID_RC_VOLUME_CREATED
:
4851 printk(MYIOC_s_INFO_FMT
" volume has been created\n",
4855 case MPI_EVENT_RAID_RC_VOLUME_DELETED
:
4857 printk(MYIOC_s_INFO_FMT
" volume has been deleted\n",
4861 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED
:
4862 printk(MYIOC_s_INFO_FMT
" volume settings have been changed\n",
4866 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED
:
4867 printk(MYIOC_s_INFO_FMT
" volume is now %s%s%s%s\n",
4869 state
== MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4871 : state
== MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4873 : state
== MPI_RAIDVOL0_STATUS_STATE_FAILED
4876 flags
& MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4878 flags
& MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4879 ? ", quiesced" : "",
4880 flags
& MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4881 ? ", resync in progress" : "" );
4884 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED
:
4885 printk(MYIOC_s_INFO_FMT
" volume membership of PhysDisk %d has changed\n",
4889 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED
:
4890 printk(MYIOC_s_INFO_FMT
" PhysDisk has been created\n",
4894 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED
:
4895 printk(MYIOC_s_INFO_FMT
" PhysDisk has been deleted\n",
4899 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED
:
4900 printk(MYIOC_s_INFO_FMT
" PhysDisk settings have been changed\n",
4904 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED
:
4905 printk(MYIOC_s_INFO_FMT
" PhysDisk is now %s%s%s\n",
4907 state
== MPI_PHYSDISK0_STATUS_ONLINE
4909 : state
== MPI_PHYSDISK0_STATUS_MISSING
4911 : state
== MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4913 : state
== MPI_PHYSDISK0_STATUS_FAILED
4915 : state
== MPI_PHYSDISK0_STATUS_INITIALIZING
4917 : state
== MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4918 ? "offline requested"
4919 : state
== MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4920 ? "failed requested"
4921 : state
== MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4924 flags
& MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4925 ? ", out of sync" : "",
4926 flags
& MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4927 ? ", quiesced" : "" );
4930 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED
:
4931 printk(MYIOC_s_INFO_FMT
" Domain Validation needed for PhysDisk %d\n",
4935 case MPI_EVENT_RAID_RC_SMART_DATA
:
4936 printk(MYIOC_s_INFO_FMT
" SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4937 ioc
->name
, pRaidEventData
->ASC
, pRaidEventData
->ASCQ
);
4940 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED
:
4941 printk(MYIOC_s_INFO_FMT
" replacement of PhysDisk %d has started\n",
4947 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4949 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4950 * @ioc: Pointer to MPT_ADAPTER structure
4952 * Returns: 0 for success
4953 * -ENOMEM if no memory available
4954 * -EPERM if not allowed due to ISR context
4955 * -EAGAIN if no msg frames currently available
4956 * -EFAULT for non-successful reply or no reply (timeout)
4959 GetIoUnitPage2(MPT_ADAPTER
*ioc
)
4961 ConfigPageHeader_t hdr
;
4963 IOUnitPage2_t
*ppage_alloc
;
4964 dma_addr_t page_dma
;
4968 /* Get the page header */
4969 hdr
.PageVersion
= 0;
4972 hdr
.PageType
= MPI_CONFIG_PAGETYPE_IO_UNIT
;
4973 cfg
.cfghdr
.hdr
= &hdr
;
4975 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
4980 if ((rc
= mpt_config(ioc
, &cfg
)) != 0)
4983 if (hdr
.PageLength
== 0)
4986 /* Read the config page */
4987 data_sz
= hdr
.PageLength
* 4;
4989 ppage_alloc
= (IOUnitPage2_t
*) pci_alloc_consistent(ioc
->pcidev
, data_sz
, &page_dma
);
4991 memset((u8
*)ppage_alloc
, 0, data_sz
);
4992 cfg
.physAddr
= page_dma
;
4993 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
4995 /* If Good, save data */
4996 if ((rc
= mpt_config(ioc
, &cfg
)) == 0)
4997 ioc
->biosVersion
= le32_to_cpu(ppage_alloc
->BiosVersion
);
4999 pci_free_consistent(ioc
->pcidev
, data_sz
, (u8
*) ppage_alloc
, page_dma
);
5005 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5007 * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
5008 * @ioc: Pointer to a Adapter Strucutre
5009 * @portnum: IOC port number
5011 * Return: -EFAULT if read of config page header fails
5013 * If read of SCSI Port Page 0 fails,
5014 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5015 * Adapter settings: async, narrow
5017 * If read of SCSI Port Page 2 fails,
5018 * Adapter settings valid
5019 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
5024 * CHECK - what type of locking mechanisms should be used????
5027 mpt_GetScsiPortSettings(MPT_ADAPTER
*ioc
, int portnum
)
5032 ConfigPageHeader_t header
;
5038 if (!ioc
->spi_data
.nvram
) {
5041 sz
= MPT_MAX_SCSI_DEVICES
* sizeof(int);
5042 mem
= kmalloc(sz
, GFP_ATOMIC
);
5046 ioc
->spi_data
.nvram
= (int *) mem
;
5048 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"SCSI device NVRAM settings @ %p, sz=%d\n",
5049 ioc
->name
, ioc
->spi_data
.nvram
, sz
));
5052 /* Invalidate NVRAM information
5054 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
5055 ioc
->spi_data
.nvram
[ii
] = MPT_HOST_NVRAM_INVALID
;
5058 /* Read SPP0 header, allocate memory, then read page.
5060 header
.PageVersion
= 0;
5061 header
.PageLength
= 0;
5062 header
.PageNumber
= 0;
5063 header
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_PORT
;
5064 cfg
.cfghdr
.hdr
= &header
;
5066 cfg
.pageAddr
= portnum
;
5067 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5069 cfg
.timeout
= 0; /* use default */
5070 if (mpt_config(ioc
, &cfg
) != 0)
5073 if (header
.PageLength
> 0) {
5074 pbuf
= pci_alloc_consistent(ioc
->pcidev
, header
.PageLength
* 4, &buf_dma
);
5076 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
5077 cfg
.physAddr
= buf_dma
;
5078 if (mpt_config(ioc
, &cfg
) != 0) {
5079 ioc
->spi_data
.maxBusWidth
= MPT_NARROW
;
5080 ioc
->spi_data
.maxSyncOffset
= 0;
5081 ioc
->spi_data
.minSyncFactor
= MPT_ASYNC
;
5082 ioc
->spi_data
.busType
= MPT_HOST_BUS_UNKNOWN
;
5084 ddvprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
5085 "Unable to read PortPage0 minSyncFactor=%x\n",
5086 ioc
->name
, ioc
->spi_data
.minSyncFactor
));
5088 /* Save the Port Page 0 data
5090 SCSIPortPage0_t
*pPP0
= (SCSIPortPage0_t
*) pbuf
;
5091 pPP0
->Capabilities
= le32_to_cpu(pPP0
->Capabilities
);
5092 pPP0
->PhysicalInterface
= le32_to_cpu(pPP0
->PhysicalInterface
);
5094 if ( (pPP0
->Capabilities
& MPI_SCSIPORTPAGE0_CAP_QAS
) == 0 ) {
5095 ioc
->spi_data
.noQas
|= MPT_TARGET_NO_NEGO_QAS
;
5096 ddvprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
5097 "noQas due to Capabilities=%x\n",
5098 ioc
->name
, pPP0
->Capabilities
));
5100 ioc
->spi_data
.maxBusWidth
= pPP0
->Capabilities
& MPI_SCSIPORTPAGE0_CAP_WIDE
? 1 : 0;
5101 data
= pPP0
->Capabilities
& MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK
;
5103 ioc
->spi_data
.maxSyncOffset
= (u8
) (data
>> 16);
5104 data
= pPP0
->Capabilities
& MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK
;
5105 ioc
->spi_data
.minSyncFactor
= (u8
) (data
>> 8);
5106 ddvprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
5107 "PortPage0 minSyncFactor=%x\n",
5108 ioc
->name
, ioc
->spi_data
.minSyncFactor
));
5110 ioc
->spi_data
.maxSyncOffset
= 0;
5111 ioc
->spi_data
.minSyncFactor
= MPT_ASYNC
;
5114 ioc
->spi_data
.busType
= pPP0
->PhysicalInterface
& MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK
;
5116 /* Update the minSyncFactor based on bus type.
5118 if ((ioc
->spi_data
.busType
== MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD
) ||
5119 (ioc
->spi_data
.busType
== MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE
)) {
5121 if (ioc
->spi_data
.minSyncFactor
< MPT_ULTRA
) {
5122 ioc
->spi_data
.minSyncFactor
= MPT_ULTRA
;
5123 ddvprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
5124 "HVD or SE detected, minSyncFactor=%x\n",
5125 ioc
->name
, ioc
->spi_data
.minSyncFactor
));
5130 pci_free_consistent(ioc
->pcidev
, header
.PageLength
* 4, pbuf
, buf_dma
);
5135 /* SCSI Port Page 2 - Read the header then the page.
5137 header
.PageVersion
= 0;
5138 header
.PageLength
= 0;
5139 header
.PageNumber
= 2;
5140 header
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_PORT
;
5141 cfg
.cfghdr
.hdr
= &header
;
5143 cfg
.pageAddr
= portnum
;
5144 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5146 if (mpt_config(ioc
, &cfg
) != 0)
5149 if (header
.PageLength
> 0) {
5150 /* Allocate memory and read SCSI Port Page 2
5152 pbuf
= pci_alloc_consistent(ioc
->pcidev
, header
.PageLength
* 4, &buf_dma
);
5154 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_NVRAM
;
5155 cfg
.physAddr
= buf_dma
;
5156 if (mpt_config(ioc
, &cfg
) != 0) {
5157 /* Nvram data is left with INVALID mark
5160 } else if (ioc
->pcidev
->vendor
== PCI_VENDOR_ID_ATTO
) {
5162 /* This is an ATTO adapter, read Page2 accordingly
5164 ATTO_SCSIPortPage2_t
*pPP2
= (ATTO_SCSIPortPage2_t
*) pbuf
;
5165 ATTODeviceInfo_t
*pdevice
= NULL
;
5168 /* Save the Port Page 2 data
5169 * (reformat into a 32bit quantity)
5171 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
5172 pdevice
= &pPP2
->DeviceSettings
[ii
];
5173 ATTOFlags
= le16_to_cpu(pdevice
->ATTOFlags
);
5176 /* Translate ATTO device flags to LSI format
5178 if (ATTOFlags
& ATTOFLAG_DISC
)
5179 data
|= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE
);
5180 if (ATTOFlags
& ATTOFLAG_ID_ENB
)
5181 data
|= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE
);
5182 if (ATTOFlags
& ATTOFLAG_LUN_ENB
)
5183 data
|= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE
);
5184 if (ATTOFlags
& ATTOFLAG_TAGGED
)
5185 data
|= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE
);
5186 if (!(ATTOFlags
& ATTOFLAG_WIDE_ENB
))
5187 data
|= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE
);
5189 data
= (data
<< 16) | (pdevice
->Period
<< 8) | 10;
5190 ioc
->spi_data
.nvram
[ii
] = data
;
5193 SCSIPortPage2_t
*pPP2
= (SCSIPortPage2_t
*) pbuf
;
5194 MpiDeviceInfo_t
*pdevice
= NULL
;
5197 * Save "Set to Avoid SCSI Bus Resets" flag
5199 ioc
->spi_data
.bus_reset
=
5200 (le32_to_cpu(pPP2
->PortFlags
) &
5201 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET
) ?
5204 /* Save the Port Page 2 data
5205 * (reformat into a 32bit quantity)
5207 data
= le32_to_cpu(pPP2
->PortFlags
) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK
;
5208 ioc
->spi_data
.PortFlags
= data
;
5209 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
5210 pdevice
= &pPP2
->DeviceSettings
[ii
];
5211 data
= (le16_to_cpu(pdevice
->DeviceFlags
) << 16) |
5212 (pdevice
->SyncFactor
<< 8) | pdevice
->Timeout
;
5213 ioc
->spi_data
.nvram
[ii
] = data
;
5217 pci_free_consistent(ioc
->pcidev
, header
.PageLength
* 4, pbuf
, buf_dma
);
5221 /* Update Adapter limits with those from NVRAM
5222 * Comment: Don't need to do this. Target performance
5223 * parameters will never exceed the adapters limits.
5229 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5231 * mpt_readScsiDevicePageHeaders - save version and length of SDP1
5232 * @ioc: Pointer to a Adapter Strucutre
5233 * @portnum: IOC port number
5235 * Return: -EFAULT if read of config page header fails
5239 mpt_readScsiDevicePageHeaders(MPT_ADAPTER
*ioc
, int portnum
)
5242 ConfigPageHeader_t header
;
5244 /* Read the SCSI Device Page 1 header
5246 header
.PageVersion
= 0;
5247 header
.PageLength
= 0;
5248 header
.PageNumber
= 1;
5249 header
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
5250 cfg
.cfghdr
.hdr
= &header
;
5252 cfg
.pageAddr
= portnum
;
5253 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5256 if (mpt_config(ioc
, &cfg
) != 0)
5259 ioc
->spi_data
.sdp1version
= cfg
.cfghdr
.hdr
->PageVersion
;
5260 ioc
->spi_data
.sdp1length
= cfg
.cfghdr
.hdr
->PageLength
;
5262 header
.PageVersion
= 0;
5263 header
.PageLength
= 0;
5264 header
.PageNumber
= 0;
5265 header
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
5266 if (mpt_config(ioc
, &cfg
) != 0)
5269 ioc
->spi_data
.sdp0version
= cfg
.cfghdr
.hdr
->PageVersion
;
5270 ioc
->spi_data
.sdp0length
= cfg
.cfghdr
.hdr
->PageLength
;
5272 dcprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Headers: 0: version %d length %d\n",
5273 ioc
->name
, ioc
->spi_data
.sdp0version
, ioc
->spi_data
.sdp0length
));
5275 dcprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Headers: 1: version %d length %d\n",
5276 ioc
->name
, ioc
->spi_data
.sdp1version
, ioc
->spi_data
.sdp1length
));
5281 * mpt_inactive_raid_list_free - This clears this link list.
5282 * @ioc : pointer to per adapter structure
5285 mpt_inactive_raid_list_free(MPT_ADAPTER
*ioc
)
5287 struct inactive_raid_component_info
*component_info
, *pNext
;
5289 if (list_empty(&ioc
->raid_data
.inactive_list
))
5292 mutex_lock(&ioc
->raid_data
.inactive_list_mutex
);
5293 list_for_each_entry_safe(component_info
, pNext
,
5294 &ioc
->raid_data
.inactive_list
, list
) {
5295 list_del(&component_info
->list
);
5296 kfree(component_info
);
5298 mutex_unlock(&ioc
->raid_data
.inactive_list_mutex
);
5302 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5304 * @ioc : pointer to per adapter structure
5305 * @channel : volume channel
5306 * @id : volume target id
5309 mpt_inactive_raid_volumes(MPT_ADAPTER
*ioc
, u8 channel
, u8 id
)
5312 ConfigPageHeader_t hdr
;
5313 dma_addr_t dma_handle
;
5314 pRaidVolumePage0_t buffer
= NULL
;
5316 RaidPhysDiskPage0_t phys_disk
;
5317 struct inactive_raid_component_info
*component_info
;
5318 int handle_inactive_volumes
;
5320 memset(&cfg
, 0 , sizeof(CONFIGPARMS
));
5321 memset(&hdr
, 0 , sizeof(ConfigPageHeader_t
));
5322 hdr
.PageType
= MPI_CONFIG_PAGETYPE_RAID_VOLUME
;
5323 cfg
.pageAddr
= (channel
<< 8) + id
;
5324 cfg
.cfghdr
.hdr
= &hdr
;
5325 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5327 if (mpt_config(ioc
, &cfg
) != 0)
5330 if (!hdr
.PageLength
)
5333 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.PageLength
* 4,
5339 cfg
.physAddr
= dma_handle
;
5340 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
5342 if (mpt_config(ioc
, &cfg
) != 0)
5345 if (!buffer
->NumPhysDisks
)
5348 handle_inactive_volumes
=
5349 (buffer
->VolumeStatus
.Flags
& MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
||
5350 (buffer
->VolumeStatus
.Flags
& MPI_RAIDVOL0_STATUS_FLAG_ENABLED
) == 0 ||
5351 buffer
->VolumeStatus
.State
== MPI_RAIDVOL0_STATUS_STATE_FAILED
||
5352 buffer
->VolumeStatus
.State
== MPI_RAIDVOL0_STATUS_STATE_MISSING
) ? 1 : 0;
5354 if (!handle_inactive_volumes
)
5357 mutex_lock(&ioc
->raid_data
.inactive_list_mutex
);
5358 for (i
= 0; i
< buffer
->NumPhysDisks
; i
++) {
5359 if(mpt_raid_phys_disk_pg0(ioc
,
5360 buffer
->PhysDisk
[i
].PhysDiskNum
, &phys_disk
) != 0)
5363 if ((component_info
= kmalloc(sizeof (*component_info
),
5364 GFP_KERNEL
)) == NULL
)
5367 component_info
->volumeID
= id
;
5368 component_info
->volumeBus
= channel
;
5369 component_info
->d
.PhysDiskNum
= phys_disk
.PhysDiskNum
;
5370 component_info
->d
.PhysDiskBus
= phys_disk
.PhysDiskBus
;
5371 component_info
->d
.PhysDiskID
= phys_disk
.PhysDiskID
;
5372 component_info
->d
.PhysDiskIOC
= phys_disk
.PhysDiskIOC
;
5374 list_add_tail(&component_info
->list
,
5375 &ioc
->raid_data
.inactive_list
);
5377 mutex_unlock(&ioc
->raid_data
.inactive_list_mutex
);
5381 pci_free_consistent(ioc
->pcidev
, hdr
.PageLength
* 4, buffer
,
5386 * mpt_raid_phys_disk_pg0 - returns phys disk page zero
5387 * @ioc: Pointer to a Adapter Structure
5388 * @phys_disk_num: io unit unique phys disk num generated by the ioc
5389 * @phys_disk: requested payload data returned
5393 * -EFAULT if read of config page header fails or data pointer not NULL
5394 * -ENOMEM if pci_alloc failed
5397 mpt_raid_phys_disk_pg0(MPT_ADAPTER
*ioc
, u8 phys_disk_num
, pRaidPhysDiskPage0_t phys_disk
)
5400 ConfigPageHeader_t hdr
;
5401 dma_addr_t dma_handle
;
5402 pRaidPhysDiskPage0_t buffer
= NULL
;
5405 memset(&cfg
, 0 , sizeof(CONFIGPARMS
));
5406 memset(&hdr
, 0 , sizeof(ConfigPageHeader_t
));
5408 hdr
.PageType
= MPI_CONFIG_PAGETYPE_RAID_PHYSDISK
;
5409 cfg
.cfghdr
.hdr
= &hdr
;
5411 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5413 if (mpt_config(ioc
, &cfg
) != 0) {
5418 if (!hdr
.PageLength
) {
5423 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.PageLength
* 4,
5431 cfg
.physAddr
= dma_handle
;
5432 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
5433 cfg
.pageAddr
= phys_disk_num
;
5435 if (mpt_config(ioc
, &cfg
) != 0) {
5441 memcpy(phys_disk
, buffer
, sizeof(*buffer
));
5442 phys_disk
->MaxLBA
= le32_to_cpu(buffer
->MaxLBA
);
5447 pci_free_consistent(ioc
->pcidev
, hdr
.PageLength
* 4, buffer
,
5454 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5455 * @ioc: Pointer to a Adapter Strucutre
5459 * -EFAULT if read of config page header fails or data pointer not NULL
5460 * -ENOMEM if pci_alloc failed
5463 mpt_findImVolumes(MPT_ADAPTER
*ioc
)
5467 dma_addr_t ioc2_dma
;
5469 ConfigPageHeader_t header
;
5474 if (!ioc
->ir_firmware
)
5477 /* Free the old page
5479 kfree(ioc
->raid_data
.pIocPg2
);
5480 ioc
->raid_data
.pIocPg2
= NULL
;
5481 mpt_inactive_raid_list_free(ioc
);
5483 /* Read IOCP2 header then the page.
5485 header
.PageVersion
= 0;
5486 header
.PageLength
= 0;
5487 header
.PageNumber
= 2;
5488 header
.PageType
= MPI_CONFIG_PAGETYPE_IOC
;
5489 cfg
.cfghdr
.hdr
= &header
;
5492 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5495 if (mpt_config(ioc
, &cfg
) != 0)
5498 if (header
.PageLength
== 0)
5501 iocpage2sz
= header
.PageLength
* 4;
5502 pIoc2
= pci_alloc_consistent(ioc
->pcidev
, iocpage2sz
, &ioc2_dma
);
5506 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
5507 cfg
.physAddr
= ioc2_dma
;
5508 if (mpt_config(ioc
, &cfg
) != 0)
5511 mem
= kmalloc(iocpage2sz
, GFP_KERNEL
);
5515 memcpy(mem
, (u8
*)pIoc2
, iocpage2sz
);
5516 ioc
->raid_data
.pIocPg2
= (IOCPage2_t
*) mem
;
5518 mpt_read_ioc_pg_3(ioc
);
5520 for (i
= 0; i
< pIoc2
->NumActiveVolumes
; i
++)
5521 mpt_inactive_raid_volumes(ioc
,
5522 pIoc2
->RaidVolume
[i
].VolumeBus
,
5523 pIoc2
->RaidVolume
[i
].VolumeID
);
5526 pci_free_consistent(ioc
->pcidev
, iocpage2sz
, pIoc2
, ioc2_dma
);
5532 mpt_read_ioc_pg_3(MPT_ADAPTER
*ioc
)
5537 ConfigPageHeader_t header
;
5538 dma_addr_t ioc3_dma
;
5541 /* Free the old page
5543 kfree(ioc
->raid_data
.pIocPg3
);
5544 ioc
->raid_data
.pIocPg3
= NULL
;
5546 /* There is at least one physical disk.
5547 * Read and save IOC Page 3
5549 header
.PageVersion
= 0;
5550 header
.PageLength
= 0;
5551 header
.PageNumber
= 3;
5552 header
.PageType
= MPI_CONFIG_PAGETYPE_IOC
;
5553 cfg
.cfghdr
.hdr
= &header
;
5556 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5559 if (mpt_config(ioc
, &cfg
) != 0)
5562 if (header
.PageLength
== 0)
5565 /* Read Header good, alloc memory
5567 iocpage3sz
= header
.PageLength
* 4;
5568 pIoc3
= pci_alloc_consistent(ioc
->pcidev
, iocpage3sz
, &ioc3_dma
);
5572 /* Read the Page and save the data
5573 * into malloc'd memory.
5575 cfg
.physAddr
= ioc3_dma
;
5576 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
5577 if (mpt_config(ioc
, &cfg
) == 0) {
5578 mem
= kmalloc(iocpage3sz
, GFP_KERNEL
);
5580 memcpy(mem
, (u8
*)pIoc3
, iocpage3sz
);
5581 ioc
->raid_data
.pIocPg3
= (IOCPage3_t
*) mem
;
5585 pci_free_consistent(ioc
->pcidev
, iocpage3sz
, pIoc3
, ioc3_dma
);
5591 mpt_read_ioc_pg_4(MPT_ADAPTER
*ioc
)
5595 ConfigPageHeader_t header
;
5596 dma_addr_t ioc4_dma
;
5599 /* Read and save IOC Page 4
5601 header
.PageVersion
= 0;
5602 header
.PageLength
= 0;
5603 header
.PageNumber
= 4;
5604 header
.PageType
= MPI_CONFIG_PAGETYPE_IOC
;
5605 cfg
.cfghdr
.hdr
= &header
;
5608 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5611 if (mpt_config(ioc
, &cfg
) != 0)
5614 if (header
.PageLength
== 0)
5617 if ( (pIoc4
= ioc
->spi_data
.pIocPg4
) == NULL
) {
5618 iocpage4sz
= (header
.PageLength
+ 4) * 4; /* Allow 4 additional SEP's */
5619 pIoc4
= pci_alloc_consistent(ioc
->pcidev
, iocpage4sz
, &ioc4_dma
);
5622 ioc
->alloc_total
+= iocpage4sz
;
5624 ioc4_dma
= ioc
->spi_data
.IocPg4_dma
;
5625 iocpage4sz
= ioc
->spi_data
.IocPg4Sz
;
5628 /* Read the Page into dma memory.
5630 cfg
.physAddr
= ioc4_dma
;
5631 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
5632 if (mpt_config(ioc
, &cfg
) == 0) {
5633 ioc
->spi_data
.pIocPg4
= (IOCPage4_t
*) pIoc4
;
5634 ioc
->spi_data
.IocPg4_dma
= ioc4_dma
;
5635 ioc
->spi_data
.IocPg4Sz
= iocpage4sz
;
5637 pci_free_consistent(ioc
->pcidev
, iocpage4sz
, pIoc4
, ioc4_dma
);
5638 ioc
->spi_data
.pIocPg4
= NULL
;
5639 ioc
->alloc_total
-= iocpage4sz
;
5644 mpt_read_ioc_pg_1(MPT_ADAPTER
*ioc
)
5648 ConfigPageHeader_t header
;
5649 dma_addr_t ioc1_dma
;
5653 /* Check the Coalescing Timeout in IOC Page 1
5655 header
.PageVersion
= 0;
5656 header
.PageLength
= 0;
5657 header
.PageNumber
= 1;
5658 header
.PageType
= MPI_CONFIG_PAGETYPE_IOC
;
5659 cfg
.cfghdr
.hdr
= &header
;
5662 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5665 if (mpt_config(ioc
, &cfg
) != 0)
5668 if (header
.PageLength
== 0)
5671 /* Read Header good, alloc memory
5673 iocpage1sz
= header
.PageLength
* 4;
5674 pIoc1
= pci_alloc_consistent(ioc
->pcidev
, iocpage1sz
, &ioc1_dma
);
5678 /* Read the Page and check coalescing timeout
5680 cfg
.physAddr
= ioc1_dma
;
5681 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
5682 if (mpt_config(ioc
, &cfg
) == 0) {
5684 tmp
= le32_to_cpu(pIoc1
->Flags
) & MPI_IOCPAGE1_REPLY_COALESCING
;
5685 if (tmp
== MPI_IOCPAGE1_REPLY_COALESCING
) {
5686 tmp
= le32_to_cpu(pIoc1
->CoalescingTimeout
);
5688 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Coalescing Enabled Timeout = %d\n",
5691 if (tmp
> MPT_COALESCING_TIMEOUT
) {
5692 pIoc1
->CoalescingTimeout
= cpu_to_le32(MPT_COALESCING_TIMEOUT
);
5694 /* Write NVRAM and current
5697 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
5698 if (mpt_config(ioc
, &cfg
) == 0) {
5699 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Reset Current Coalescing Timeout to = %d\n",
5700 ioc
->name
, MPT_COALESCING_TIMEOUT
));
5702 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM
;
5703 if (mpt_config(ioc
, &cfg
) == 0) {
5704 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
5705 "Reset NVRAM Coalescing Timeout to = %d\n",
5706 ioc
->name
, MPT_COALESCING_TIMEOUT
));
5708 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
5709 "Reset NVRAM Coalescing Timeout Failed\n",
5714 dprintk(ioc
, printk(MYIOC_s_WARN_FMT
5715 "Reset of Current Coalescing Timeout Failed!\n",
5721 dprintk(ioc
, printk(MYIOC_s_WARN_FMT
"Coalescing Disabled\n", ioc
->name
));
5725 pci_free_consistent(ioc
->pcidev
, iocpage1sz
, pIoc1
, ioc1_dma
);
5731 mpt_get_manufacturing_pg_0(MPT_ADAPTER
*ioc
)
5734 ConfigPageHeader_t hdr
;
5736 ManufacturingPage0_t
*pbuf
= NULL
;
5738 memset(&cfg
, 0 , sizeof(CONFIGPARMS
));
5739 memset(&hdr
, 0 , sizeof(ConfigPageHeader_t
));
5741 hdr
.PageType
= MPI_CONFIG_PAGETYPE_MANUFACTURING
;
5742 cfg
.cfghdr
.hdr
= &hdr
;
5744 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
5747 if (mpt_config(ioc
, &cfg
) != 0)
5750 if (!cfg
.cfghdr
.hdr
->PageLength
)
5753 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
5754 pbuf
= pci_alloc_consistent(ioc
->pcidev
, hdr
.PageLength
* 4, &buf_dma
);
5758 cfg
.physAddr
= buf_dma
;
5760 if (mpt_config(ioc
, &cfg
) != 0)
5763 memcpy(ioc
->board_name
, pbuf
->BoardName
, sizeof(ioc
->board_name
));
5764 memcpy(ioc
->board_assembly
, pbuf
->BoardAssembly
, sizeof(ioc
->board_assembly
));
5765 memcpy(ioc
->board_tracer
, pbuf
->BoardTracerNumber
, sizeof(ioc
->board_tracer
));
5770 pci_free_consistent(ioc
->pcidev
, hdr
.PageLength
* 4, pbuf
, buf_dma
);
5773 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5775 * SendEventNotification - Send EventNotification (on or off) request to adapter
5776 * @ioc: Pointer to MPT_ADAPTER structure
5777 * @EvSwitch: Event switch flags
5780 SendEventNotification(MPT_ADAPTER
*ioc
, u8 EvSwitch
)
5782 EventNotification_t
*evnp
;
5784 evnp
= (EventNotification_t
*) mpt_get_msg_frame(mpt_base_index
, ioc
);
5786 devtverboseprintk(ioc
, printk(MYIOC_s_WARN_FMT
"Unable to allocate event request frame!\n",
5790 memset(evnp
, 0, sizeof(*evnp
));
5792 devtverboseprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending EventNotification (%d) request %p\n", ioc
->name
, EvSwitch
, evnp
));
5794 evnp
->Function
= MPI_FUNCTION_EVENT_NOTIFICATION
;
5795 evnp
->ChainOffset
= 0;
5797 evnp
->Switch
= EvSwitch
;
5799 mpt_put_msg_frame(mpt_base_index
, ioc
, (MPT_FRAME_HDR
*)evnp
);
5804 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5806 * SendEventAck - Send EventAck request to MPT adapter.
5807 * @ioc: Pointer to MPT_ADAPTER structure
5808 * @evnp: Pointer to original EventNotification request
5811 SendEventAck(MPT_ADAPTER
*ioc
, EventNotificationReply_t
*evnp
)
5815 if ((pAck
= (EventAck_t
*) mpt_get_msg_frame(mpt_base_index
, ioc
)) == NULL
) {
5816 dfailprintk(ioc
, printk(MYIOC_s_WARN_FMT
"%s, no msg frames!!\n",
5817 ioc
->name
,__func__
));
5821 devtverboseprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending EventAck\n", ioc
->name
));
5823 pAck
->Function
= MPI_FUNCTION_EVENT_ACK
;
5824 pAck
->ChainOffset
= 0;
5825 pAck
->Reserved
[0] = pAck
->Reserved
[1] = 0;
5827 pAck
->Reserved1
[0] = pAck
->Reserved1
[1] = pAck
->Reserved1
[2] = 0;
5828 pAck
->Event
= evnp
->Event
;
5829 pAck
->EventContext
= evnp
->EventContext
;
5831 mpt_put_msg_frame(mpt_base_index
, ioc
, (MPT_FRAME_HDR
*)pAck
);
5836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5838 * mpt_config - Generic function to issue config message
5839 * @ioc: Pointer to an adapter structure
5840 * @pCfg: Pointer to a configuration structure. Struct contains
5841 * action, page address, direction, physical address
5842 * and pointer to a configuration page header
5843 * Page header is updated.
5845 * Returns 0 for success
5846 * -EPERM if not allowed due to ISR context
5847 * -EAGAIN if no msg frames currently available
5848 * -EFAULT for non-successful reply or no reply (timeout)
5851 mpt_config(MPT_ADAPTER
*ioc
, CONFIGPARMS
*pCfg
)
5854 ConfigExtendedPageHeader_t
*pExtHdr
= NULL
;
5856 unsigned long flags
;
5861 /* Prevent calling wait_event() (below), if caller happens
5862 * to be in ISR context, because that is fatal!
5864 in_isr
= in_interrupt();
5866 dcprintk(ioc
, printk(MYIOC_s_WARN_FMT
"Config request not allowed in ISR context!\n",
5871 /* Get and Populate a free Frame
5873 if ((mf
= mpt_get_msg_frame(mpt_base_index
, ioc
)) == NULL
) {
5874 dcprintk(ioc
, printk(MYIOC_s_WARN_FMT
"mpt_config: no msg frames!\n",
5878 pReq
= (Config_t
*)mf
;
5879 pReq
->Action
= pCfg
->action
;
5881 pReq
->ChainOffset
= 0;
5882 pReq
->Function
= MPI_FUNCTION_CONFIG
;
5884 /* Assume page type is not extended and clear "reserved" fields. */
5885 pReq
->ExtPageLength
= 0;
5886 pReq
->ExtPageType
= 0;
5889 for (ii
=0; ii
< 8; ii
++)
5890 pReq
->Reserved2
[ii
] = 0;
5892 pReq
->Header
.PageVersion
= pCfg
->cfghdr
.hdr
->PageVersion
;
5893 pReq
->Header
.PageLength
= pCfg
->cfghdr
.hdr
->PageLength
;
5894 pReq
->Header
.PageNumber
= pCfg
->cfghdr
.hdr
->PageNumber
;
5895 pReq
->Header
.PageType
= (pCfg
->cfghdr
.hdr
->PageType
& MPI_CONFIG_PAGETYPE_MASK
);
5897 if ((pCfg
->cfghdr
.hdr
->PageType
& MPI_CONFIG_PAGETYPE_MASK
) == MPI_CONFIG_PAGETYPE_EXTENDED
) {
5898 pExtHdr
= (ConfigExtendedPageHeader_t
*)pCfg
->cfghdr
.ehdr
;
5899 pReq
->ExtPageLength
= cpu_to_le16(pExtHdr
->ExtPageLength
);
5900 pReq
->ExtPageType
= pExtHdr
->ExtPageType
;
5901 pReq
->Header
.PageType
= MPI_CONFIG_PAGETYPE_EXTENDED
;
5903 /* Page Length must be treated as a reserved field for the extended header. */
5904 pReq
->Header
.PageLength
= 0;
5907 pReq
->PageAddress
= cpu_to_le32(pCfg
->pageAddr
);
5909 /* Add a SGE to the config request.
5912 flagsLength
= MPT_SGE_FLAGS_SSIMPLE_WRITE
;
5914 flagsLength
= MPT_SGE_FLAGS_SSIMPLE_READ
;
5916 if ((pCfg
->cfghdr
.hdr
->PageType
& MPI_CONFIG_PAGETYPE_MASK
) == MPI_CONFIG_PAGETYPE_EXTENDED
) {
5917 flagsLength
|= pExtHdr
->ExtPageLength
* 4;
5919 dcprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending Config request type %d, page %d and action %d\n",
5920 ioc
->name
, pReq
->ExtPageType
, pReq
->Header
.PageNumber
, pReq
->Action
));
5923 flagsLength
|= pCfg
->cfghdr
.hdr
->PageLength
* 4;
5925 dcprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Sending Config request type %d, page %d and action %d\n",
5926 ioc
->name
, pReq
->Header
.PageType
, pReq
->Header
.PageNumber
, pReq
->Action
));
5929 mpt_add_sge((char *)&pReq
->PageBufferSGE
, flagsLength
, pCfg
->physAddr
);
5931 /* Append pCfg pointer to end of mf
5933 *((void **) (((u8
*) mf
) + (ioc
->req_sz
- sizeof(void *)))) = (void *) pCfg
;
5935 /* Initalize the timer
5937 init_timer(&pCfg
->timer
);
5938 pCfg
->timer
.data
= (unsigned long) ioc
;
5939 pCfg
->timer
.function
= mpt_timer_expired
;
5940 pCfg
->wait_done
= 0;
5942 /* Set the timer; ensure 10 second minimum */
5943 if (pCfg
->timeout
< 10)
5944 pCfg
->timer
.expires
= jiffies
+ HZ
*10;
5946 pCfg
->timer
.expires
= jiffies
+ HZ
*pCfg
->timeout
;
5948 /* Add to end of Q, set timer and then issue this command */
5949 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
5950 list_add_tail(&pCfg
->linkage
, &ioc
->configQ
);
5951 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
5953 add_timer(&pCfg
->timer
);
5954 mpt_put_msg_frame(mpt_base_index
, ioc
, mf
);
5955 wait_event(mpt_waitq
, pCfg
->wait_done
);
5957 /* mf has been freed - do not access */
5964 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5966 * mpt_timer_expired - Callback for timer process.
5967 * Used only internal config functionality.
5968 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5971 mpt_timer_expired(unsigned long data
)
5973 MPT_ADAPTER
*ioc
= (MPT_ADAPTER
*) data
;
5975 dcprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mpt_timer_expired! \n", ioc
->name
));
5977 /* Perform a FW reload */
5978 if (mpt_HardResetHandler(ioc
, NO_SLEEP
) < 0)
5979 printk(MYIOC_s_WARN_FMT
"Firmware Reload FAILED!\n", ioc
->name
);
5981 /* No more processing.
5982 * Hard reset clean-up will wake up
5983 * process and free all resources.
5985 dcprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"mpt_timer_expired complete!\n", ioc
->name
));
5990 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5992 * mpt_ioc_reset - Base cleanup for hard reset
5993 * @ioc: Pointer to the adapter structure
5994 * @reset_phase: Indicates pre- or post-reset functionality
5996 * Remark: Frees resources with internally generated commands.
5999 mpt_ioc_reset(MPT_ADAPTER
*ioc
, int reset_phase
)
6002 unsigned long flags
;
6004 dprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
6005 ": IOC %s_reset routed to MPT base driver!\n",
6006 ioc
->name
, reset_phase
==MPT_IOC_SETUP_RESET
? "setup" : (
6007 reset_phase
==MPT_IOC_PRE_RESET
? "pre" : "post")));
6009 if (reset_phase
== MPT_IOC_SETUP_RESET
) {
6011 } else if (reset_phase
== MPT_IOC_PRE_RESET
) {
6012 /* If the internal config Q is not empty -
6013 * delete timer. MF resources will be freed when
6014 * the FIFO's are primed.
6016 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
6017 list_for_each_entry(pCfg
, &ioc
->configQ
, linkage
)
6018 del_timer(&pCfg
->timer
);
6019 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
6024 /* Search the configQ for internal commands.
6025 * Flush the Q, and wake up all suspended threads.
6027 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
6028 list_for_each_entry_safe(pCfg
, pNext
, &ioc
->configQ
, linkage
) {
6029 list_del(&pCfg
->linkage
);
6031 pCfg
->status
= MPT_CONFIG_ERROR
;
6032 pCfg
->wait_done
= 1;
6033 wake_up(&mpt_waitq
);
6035 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
6038 return 1; /* currently means nothing really */
6042 #ifdef CONFIG_PROC_FS /* { */
6043 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6045 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
6047 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6049 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
6051 * Returns 0 for success, non-zero for failure.
6054 procmpt_create(void)
6056 struct proc_dir_entry
*ent
;
6058 mpt_proc_root_dir
= proc_mkdir(MPT_PROCFS_MPTBASEDIR
, NULL
);
6059 if (mpt_proc_root_dir
== NULL
)
6062 ent
= create_proc_entry("summary", S_IFREG
|S_IRUGO
, mpt_proc_root_dir
);
6064 ent
->read_proc
= procmpt_summary_read
;
6066 ent
= create_proc_entry("version", S_IFREG
|S_IRUGO
, mpt_proc_root_dir
);
6068 ent
->read_proc
= procmpt_version_read
;
6073 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6075 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
6077 * Returns 0 for success, non-zero for failure.
6080 procmpt_destroy(void)
6082 remove_proc_entry("version", mpt_proc_root_dir
);
6083 remove_proc_entry("summary", mpt_proc_root_dir
);
6084 remove_proc_entry(MPT_PROCFS_MPTBASEDIR
, NULL
);
6087 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6089 * procmpt_summary_read - Handle read request of a summary file
6090 * @buf: Pointer to area to write information
6091 * @start: Pointer to start pointer
6092 * @offset: Offset to start writing
6093 * @request: Amount of read data requested
6094 * @eof: Pointer to EOF integer
6097 * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
6098 * Returns number of characters written to process performing the read.
6101 procmpt_summary_read(char *buf
, char **start
, off_t offset
, int request
, int *eof
, void *data
)
6111 mpt_print_ioc_summary(ioc
, out
, &more
, 0, 1);
6115 list_for_each_entry(ioc
, &ioc_list
, list
) {
6118 mpt_print_ioc_summary(ioc
, out
, &more
, 0, 1);
6121 if ((out
-buf
) >= request
)
6128 MPT_PROC_READ_RETURN(buf
,start
,offset
,request
,eof
,len
);
6131 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6133 * procmpt_version_read - Handle read request from /proc/mpt/version.
6134 * @buf: Pointer to area to write information
6135 * @start: Pointer to start pointer
6136 * @offset: Offset to start writing
6137 * @request: Amount of read data requested
6138 * @eof: Pointer to EOF integer
6141 * Returns number of characters written to process performing the read.
6144 procmpt_version_read(char *buf
, char **start
, off_t offset
, int request
, int *eof
, void *data
)
6147 int scsi
, fc
, sas
, lan
, ctl
, targ
, dmp
;
6151 len
= sprintf(buf
, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON
);
6152 len
+= sprintf(buf
+len
, " Fusion MPT base driver\n");
6154 scsi
= fc
= sas
= lan
= ctl
= targ
= dmp
= 0;
6155 for (cb_idx
= MPT_MAX_PROTOCOL_DRIVERS
-1; cb_idx
; cb_idx
--) {
6157 if (MptCallbacks
[cb_idx
]) {
6158 switch (MptDriverClass
[cb_idx
]) {
6160 if (!scsi
++) drvname
= "SPI host";
6163 if (!fc
++) drvname
= "FC host";
6166 if (!sas
++) drvname
= "SAS host";
6169 if (!lan
++) drvname
= "LAN";
6172 if (!targ
++) drvname
= "SCSI target";
6175 if (!ctl
++) drvname
= "ioctl";
6180 len
+= sprintf(buf
+len
, " Fusion MPT %s driver\n", drvname
);
6184 MPT_PROC_READ_RETURN(buf
,start
,offset
,request
,eof
,len
);
6187 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6189 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
6190 * @buf: Pointer to area to write information
6191 * @start: Pointer to start pointer
6192 * @offset: Offset to start writing
6193 * @request: Amount of read data requested
6194 * @eof: Pointer to EOF integer
6197 * Returns number of characters written to process performing the read.
6200 procmpt_iocinfo_read(char *buf
, char **start
, off_t offset
, int request
, int *eof
, void *data
)
6202 MPT_ADAPTER
*ioc
= data
;
6208 mpt_get_fw_exp_ver(expVer
, ioc
);
6210 len
= sprintf(buf
, "%s:", ioc
->name
);
6211 if (ioc
->facts
.Flags
& MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT
)
6212 len
+= sprintf(buf
+len
, " (f/w download boot flag set)");
6213 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6214 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
6216 len
+= sprintf(buf
+len
, "\n ProductID = 0x%04x (%s)\n",
6217 ioc
->facts
.ProductID
,
6219 len
+= sprintf(buf
+len
, " FWVersion = 0x%08x%s", ioc
->facts
.FWVersion
.Word
, expVer
);
6220 if (ioc
->facts
.FWImageSize
)
6221 len
+= sprintf(buf
+len
, " (fw_size=%d)", ioc
->facts
.FWImageSize
);
6222 len
+= sprintf(buf
+len
, "\n MsgVersion = 0x%04x\n", ioc
->facts
.MsgVersion
);
6223 len
+= sprintf(buf
+len
, " FirstWhoInit = 0x%02x\n", ioc
->FirstWhoInit
);
6224 len
+= sprintf(buf
+len
, " EventState = 0x%02x\n", ioc
->facts
.EventState
);
6226 len
+= sprintf(buf
+len
, " CurrentHostMfaHighAddr = 0x%08x\n",
6227 ioc
->facts
.CurrentHostMfaHighAddr
);
6228 len
+= sprintf(buf
+len
, " CurrentSenseBufferHighAddr = 0x%08x\n",
6229 ioc
->facts
.CurrentSenseBufferHighAddr
);
6231 len
+= sprintf(buf
+len
, " MaxChainDepth = 0x%02x frames\n", ioc
->facts
.MaxChainDepth
);
6232 len
+= sprintf(buf
+len
, " MinBlockSize = 0x%02x bytes\n", 4*ioc
->facts
.BlockSize
);
6234 len
+= sprintf(buf
+len
, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6235 (void *)ioc
->req_frames
, (void *)(ulong
)ioc
->req_frames_dma
);
6237 * Rounding UP to nearest 4-kB boundary here...
6239 sz
= (ioc
->req_sz
* ioc
->req_depth
) + 128;
6240 sz
= ((sz
+ 0x1000UL
- 1UL) / 0x1000) * 0x1000;
6241 len
+= sprintf(buf
+len
, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6242 ioc
->req_sz
, ioc
->req_depth
, ioc
->req_sz
*ioc
->req_depth
, sz
);
6243 len
+= sprintf(buf
+len
, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
6244 4*ioc
->facts
.RequestFrameSize
,
6245 ioc
->facts
.GlobalCredits
);
6247 len
+= sprintf(buf
+len
, " Frames @ 0x%p (Dma @ 0x%p)\n",
6248 (void *)ioc
->alloc
, (void *)(ulong
)ioc
->alloc_dma
);
6249 sz
= (ioc
->reply_sz
* ioc
->reply_depth
) + 128;
6250 len
+= sprintf(buf
+len
, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6251 ioc
->reply_sz
, ioc
->reply_depth
, ioc
->reply_sz
*ioc
->reply_depth
, sz
);
6252 len
+= sprintf(buf
+len
, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
6253 ioc
->facts
.CurReplyFrameSize
,
6254 ioc
->facts
.ReplyQueueDepth
);
6256 len
+= sprintf(buf
+len
, " MaxDevices = %d\n",
6257 (ioc
->facts
.MaxDevices
==0) ? 255 : ioc
->facts
.MaxDevices
);
6258 len
+= sprintf(buf
+len
, " MaxBuses = %d\n", ioc
->facts
.MaxBuses
);
6261 for (p
=0; p
< ioc
->facts
.NumberOfPorts
; p
++) {
6262 len
+= sprintf(buf
+len
, " PortNumber = %d (of %d)\n",
6264 ioc
->facts
.NumberOfPorts
);
6265 if (ioc
->bus_type
== FC
) {
6266 if (ioc
->pfacts
[p
].ProtocolFlags
& MPI_PORTFACTS_PROTOCOL_LAN
) {
6267 u8
*a
= (u8
*)&ioc
->lan_cnfg_page1
.HardwareAddressLow
;
6268 len
+= sprintf(buf
+len
, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6269 a
[5], a
[4], a
[3], a
[2], a
[1], a
[0]);
6271 len
+= sprintf(buf
+len
, " WWN = %08X%08X:%08X%08X\n",
6272 ioc
->fc_port_page0
[p
].WWNN
.High
,
6273 ioc
->fc_port_page0
[p
].WWNN
.Low
,
6274 ioc
->fc_port_page0
[p
].WWPN
.High
,
6275 ioc
->fc_port_page0
[p
].WWPN
.Low
);
6279 MPT_PROC_READ_RETURN(buf
,start
,offset
,request
,eof
,len
);
6282 #endif /* CONFIG_PROC_FS } */
6284 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6286 mpt_get_fw_exp_ver(char *buf
, MPT_ADAPTER
*ioc
)
6289 if ((ioc
->facts
.FWVersion
.Word
>> 24) == 0x0E) {
6290 sprintf(buf
, " (Exp %02d%02d)",
6291 (ioc
->facts
.FWVersion
.Word
>> 16) & 0x00FF, /* Month */
6292 (ioc
->facts
.FWVersion
.Word
>> 8) & 0x1F); /* Day */
6295 if ((ioc
->facts
.FWVersion
.Word
>> 8) & 0x80)
6296 strcat(buf
, " [MDBG]");
6300 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6302 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6303 * @ioc: Pointer to MPT_ADAPTER structure
6304 * @buffer: Pointer to buffer where IOC summary info should be written
6305 * @size: Pointer to number of bytes we wrote (set by this routine)
6306 * @len: Offset at which to start writing in buffer
6307 * @showlan: Display LAN stuff?
6309 * This routine writes (english readable) ASCII text, which represents
6310 * a summary of IOC information, to a buffer.
6313 mpt_print_ioc_summary(MPT_ADAPTER
*ioc
, char *buffer
, int *size
, int len
, int showlan
)
6318 mpt_get_fw_exp_ver(expVer
, ioc
);
6321 * Shorter summary of attached ioc's...
6323 y
= sprintf(buffer
+len
, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6326 MPT_FW_REV_MAGIC_ID_STRING
, /* "FwRev=" or somesuch */
6327 ioc
->facts
.FWVersion
.Word
,
6329 ioc
->facts
.NumberOfPorts
,
6332 if (showlan
&& (ioc
->pfacts
[0].ProtocolFlags
& MPI_PORTFACTS_PROTOCOL_LAN
)) {
6333 u8
*a
= (u8
*)&ioc
->lan_cnfg_page1
.HardwareAddressLow
;
6334 y
+= sprintf(buffer
+len
+y
, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6335 a
[5], a
[4], a
[3], a
[2], a
[1], a
[0]);
6338 y
+= sprintf(buffer
+len
+y
, ", IRQ=%d", ioc
->pci_irq
);
6341 y
+= sprintf(buffer
+len
+y
, " (disabled)");
6343 y
+= sprintf(buffer
+len
+y
, "\n");
6350 * mpt_halt_firmware - Halts the firmware if it is operational and panic
6352 * @ioc: Pointer to MPT_ADAPTER structure
6356 mpt_halt_firmware(MPT_ADAPTER
*ioc
)
6360 ioc_raw_state
= mpt_GetIocState(ioc
, 0);
6362 if ((ioc_raw_state
& MPI_IOC_STATE_MASK
) == MPI_IOC_STATE_FAULT
) {
6363 printk(MYIOC_s_ERR_FMT
"IOC is in FAULT state (%04xh)!!!\n",
6364 ioc
->name
, ioc_raw_state
& MPI_DOORBELL_DATA_MASK
);
6365 panic("%s: IOC Fault (%04xh)!!!\n", ioc
->name
,
6366 ioc_raw_state
& MPI_DOORBELL_DATA_MASK
);
6368 CHIPREG_WRITE32(&ioc
->chip
->Doorbell
, 0xC0FFEE00);
6369 panic("%s: Firmware is halted due to command timeout\n",
6373 EXPORT_SYMBOL(mpt_halt_firmware
);
6375 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6379 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6381 * mpt_HardResetHandler - Generic reset handler
6382 * @ioc: Pointer to MPT_ADAPTER structure
6383 * @sleepFlag: Indicates if sleep or schedule must be called.
6385 * Issues SCSI Task Management call based on input arg values.
6386 * If TaskMgmt fails, returns associated SCSI request.
6388 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
6389 * or a non-interrupt thread. In the former, must not call schedule().
6391 * Note: A return of -1 is a FATAL error case, as it means a
6392 * FW reload/initialization failed.
6394 * Returns 0 for SUCCESS or -1 if FAILED.
6397 mpt_HardResetHandler(MPT_ADAPTER
*ioc
, int sleepFlag
)
6400 unsigned long flags
;
6402 dtmprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"HardResetHandler Entered!\n", ioc
->name
));
6404 printk(MYIOC_s_INFO_FMT
"HardResetHandler Entered!\n", ioc
->name
);
6405 printk("MF count 0x%x !\n", ioc
->mfcnt
);
6407 if (mpt_fwfault_debug
)
6408 mpt_halt_firmware(ioc
);
6410 /* Reset the adapter. Prevent more than 1 call to
6411 * mpt_do_ioc_recovery at any instant in time.
6413 spin_lock_irqsave(&ioc
->diagLock
, flags
);
6414 if ((ioc
->diagPending
) || (ioc
->alt_ioc
&& ioc
->alt_ioc
->diagPending
)){
6415 spin_unlock_irqrestore(&ioc
->diagLock
, flags
);
6418 ioc
->diagPending
= 1;
6420 spin_unlock_irqrestore(&ioc
->diagLock
, flags
);
6422 /* FIXME: If do_ioc_recovery fails, repeat....
6425 /* The SCSI driver needs to adjust timeouts on all current
6426 * commands prior to the diagnostic reset being issued.
6427 * Prevents timeouts occurring during a diagnostic reset...very bad.
6428 * For all other protocol drivers, this is a no-op.
6434 for (cb_idx
= MPT_MAX_PROTOCOL_DRIVERS
-1; cb_idx
; cb_idx
--) {
6435 if (MptResetHandlers
[cb_idx
]) {
6436 dtmprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Calling IOC reset_setup handler #%d\n",
6437 ioc
->name
, cb_idx
));
6438 r
+= mpt_signal_reset(cb_idx
, ioc
, MPT_IOC_SETUP_RESET
);
6440 dtmprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Calling alt-%s setup reset handler #%d\n",
6441 ioc
->name
, ioc
->alt_ioc
->name
, cb_idx
));
6442 r
+= mpt_signal_reset(cb_idx
, ioc
->alt_ioc
, MPT_IOC_SETUP_RESET
);
6448 if ((rc
= mpt_do_ioc_recovery(ioc
, MPT_HOSTEVENT_IOC_RECOVER
, sleepFlag
)) != 0) {
6449 printk(MYIOC_s_WARN_FMT
"Cannot recover rc = %d!\n", ioc
->name
, rc
);
6453 ioc
->alt_ioc
->reload_fw
= 0;
6455 spin_lock_irqsave(&ioc
->diagLock
, flags
);
6456 ioc
->diagPending
= 0;
6458 ioc
->alt_ioc
->diagPending
= 0;
6459 spin_unlock_irqrestore(&ioc
->diagLock
, flags
);
6461 dtmprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"HardResetHandler rc = %d!\n", ioc
->name
, rc
));
6466 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6468 EventDescriptionStr(u8 event
, u32 evData0
, char *evStr
)
6473 case MPI_EVENT_NONE
:
6476 case MPI_EVENT_LOG_DATA
:
6479 case MPI_EVENT_STATE_CHANGE
:
6480 ds
= "State Change";
6482 case MPI_EVENT_UNIT_ATTENTION
:
6483 ds
= "Unit Attention";
6485 case MPI_EVENT_IOC_BUS_RESET
:
6486 ds
= "IOC Bus Reset";
6488 case MPI_EVENT_EXT_BUS_RESET
:
6489 ds
= "External Bus Reset";
6491 case MPI_EVENT_RESCAN
:
6492 ds
= "Bus Rescan Event";
6494 case MPI_EVENT_LINK_STATUS_CHANGE
:
6495 if (evData0
== MPI_EVENT_LINK_STATUS_FAILURE
)
6496 ds
= "Link Status(FAILURE) Change";
6498 ds
= "Link Status(ACTIVE) Change";
6500 case MPI_EVENT_LOOP_STATE_CHANGE
:
6501 if (evData0
== MPI_EVENT_LOOP_STATE_CHANGE_LIP
)
6502 ds
= "Loop State(LIP) Change";
6503 else if (evData0
== MPI_EVENT_LOOP_STATE_CHANGE_LPE
)
6504 ds
= "Loop State(LPE) Change"; /* ??? */
6506 ds
= "Loop State(LPB) Change"; /* ??? */
6508 case MPI_EVENT_LOGOUT
:
6511 case MPI_EVENT_EVENT_CHANGE
:
6517 case MPI_EVENT_INTEGRATED_RAID
:
6519 u8 ReasonCode
= (u8
)(evData0
>> 16);
6520 switch (ReasonCode
) {
6521 case MPI_EVENT_RAID_RC_VOLUME_CREATED
:
6522 ds
= "Integrated Raid: Volume Created";
6524 case MPI_EVENT_RAID_RC_VOLUME_DELETED
:
6525 ds
= "Integrated Raid: Volume Deleted";
6527 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED
:
6528 ds
= "Integrated Raid: Volume Settings Changed";
6530 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED
:
6531 ds
= "Integrated Raid: Volume Status Changed";
6533 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED
:
6534 ds
= "Integrated Raid: Volume Physdisk Changed";
6536 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED
:
6537 ds
= "Integrated Raid: Physdisk Created";
6539 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED
:
6540 ds
= "Integrated Raid: Physdisk Deleted";
6542 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED
:
6543 ds
= "Integrated Raid: Physdisk Settings Changed";
6545 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED
:
6546 ds
= "Integrated Raid: Physdisk Status Changed";
6548 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED
:
6549 ds
= "Integrated Raid: Domain Validation Needed";
6551 case MPI_EVENT_RAID_RC_SMART_DATA
:
6552 ds
= "Integrated Raid; Smart Data";
6554 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED
:
6555 ds
= "Integrated Raid: Replace Action Started";
6558 ds
= "Integrated Raid";
6563 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE
:
6564 ds
= "SCSI Device Status Change";
6566 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE
:
6568 u8 id
= (u8
)(evData0
);
6569 u8 channel
= (u8
)(evData0
>> 8);
6570 u8 ReasonCode
= (u8
)(evData0
>> 16);
6571 switch (ReasonCode
) {
6572 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED
:
6573 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6574 "SAS Device Status Change: Added: "
6575 "id=%d channel=%d", id
, channel
);
6577 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING
:
6578 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6579 "SAS Device Status Change: Deleted: "
6580 "id=%d channel=%d", id
, channel
);
6582 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA
:
6583 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6584 "SAS Device Status Change: SMART Data: "
6585 "id=%d channel=%d", id
, channel
);
6587 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED
:
6588 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6589 "SAS Device Status Change: No Persistancy: "
6590 "id=%d channel=%d", id
, channel
);
6592 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED
:
6593 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6594 "SAS Device Status Change: Unsupported Device "
6595 "Discovered : id=%d channel=%d", id
, channel
);
6597 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET
:
6598 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6599 "SAS Device Status Change: Internal Device "
6600 "Reset : id=%d channel=%d", id
, channel
);
6602 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL
:
6603 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6604 "SAS Device Status Change: Internal Task "
6605 "Abort : id=%d channel=%d", id
, channel
);
6607 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL
:
6608 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6609 "SAS Device Status Change: Internal Abort "
6610 "Task Set : id=%d channel=%d", id
, channel
);
6612 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL
:
6613 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6614 "SAS Device Status Change: Internal Clear "
6615 "Task Set : id=%d channel=%d", id
, channel
);
6617 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL
:
6618 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6619 "SAS Device Status Change: Internal Query "
6620 "Task : id=%d channel=%d", id
, channel
);
6623 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6624 "SAS Device Status Change: Unknown: "
6625 "id=%d channel=%d", id
, channel
);
6630 case MPI_EVENT_ON_BUS_TIMER_EXPIRED
:
6631 ds
= "Bus Timer Expired";
6633 case MPI_EVENT_QUEUE_FULL
:
6635 u16 curr_depth
= (u16
)(evData0
>> 16);
6636 u8 channel
= (u8
)(evData0
>> 8);
6637 u8 id
= (u8
)(evData0
);
6639 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6640 "Queue Full: channel=%d id=%d depth=%d",
6641 channel
, id
, curr_depth
);
6644 case MPI_EVENT_SAS_SES
:
6645 ds
= "SAS SES Event";
6647 case MPI_EVENT_PERSISTENT_TABLE_FULL
:
6648 ds
= "Persistent Table Full";
6650 case MPI_EVENT_SAS_PHY_LINK_STATUS
:
6652 u8 LinkRates
= (u8
)(evData0
>> 8);
6653 u8 PhyNumber
= (u8
)(evData0
);
6654 LinkRates
= (LinkRates
& MPI_EVENT_SAS_PLS_LR_CURRENT_MASK
) >>
6655 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT
;
6656 switch (LinkRates
) {
6657 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN
:
6658 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6659 "SAS PHY Link Status: Phy=%d:"
6660 " Rate Unknown",PhyNumber
);
6662 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED
:
6663 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6664 "SAS PHY Link Status: Phy=%d:"
6665 " Phy Disabled",PhyNumber
);
6667 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION
:
6668 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6669 "SAS PHY Link Status: Phy=%d:"
6670 " Failed Speed Nego",PhyNumber
);
6672 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE
:
6673 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6674 "SAS PHY Link Status: Phy=%d:"
6675 " Sata OOB Completed",PhyNumber
);
6677 case MPI_EVENT_SAS_PLS_LR_RATE_1_5
:
6678 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6679 "SAS PHY Link Status: Phy=%d:"
6680 " Rate 1.5 Gbps",PhyNumber
);
6682 case MPI_EVENT_SAS_PLS_LR_RATE_3_0
:
6683 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6684 "SAS PHY Link Status: Phy=%d:"
6685 " Rate 3.0 Gpbs",PhyNumber
);
6688 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6689 "SAS PHY Link Status: Phy=%d", PhyNumber
);
6694 case MPI_EVENT_SAS_DISCOVERY_ERROR
:
6695 ds
= "SAS Discovery Error";
6697 case MPI_EVENT_IR_RESYNC_UPDATE
:
6699 u8 resync_complete
= (u8
)(evData0
>> 16);
6700 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6701 "IR Resync Update: Complete = %d:",resync_complete
);
6706 u8 ReasonCode
= (u8
)(evData0
>> 16);
6707 switch (ReasonCode
) {
6708 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED
:
6709 ds
= "IR2: LD State Changed";
6711 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED
:
6712 ds
= "IR2: PD State Changed";
6714 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL
:
6715 ds
= "IR2: Bad Block Table Full";
6717 case MPI_EVENT_IR2_RC_PD_INSERTED
:
6718 ds
= "IR2: PD Inserted";
6720 case MPI_EVENT_IR2_RC_PD_REMOVED
:
6721 ds
= "IR2: PD Removed";
6723 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED
:
6724 ds
= "IR2: Foreign CFG Detected";
6726 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR
:
6727 ds
= "IR2: Rebuild Medium Error";
6735 case MPI_EVENT_SAS_DISCOVERY
:
6738 ds
= "SAS Discovery: Start";
6740 ds
= "SAS Discovery: Stop";
6743 case MPI_EVENT_LOG_ENTRY_ADDED
:
6744 ds
= "SAS Log Entry Added";
6747 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE
:
6749 u8 phy_num
= (u8
)(evData0
);
6750 u8 port_num
= (u8
)(evData0
>> 8);
6751 u8 port_width
= (u8
)(evData0
>> 16);
6752 u8 primative
= (u8
)(evData0
>> 24);
6753 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6754 "SAS Broadcase Primative: phy=%d port=%d "
6755 "width=%d primative=0x%02x",
6756 phy_num
, port_num
, port_width
, primative
);
6760 case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE
:
6762 u8 reason
= (u8
)(evData0
);
6763 u8 port_num
= (u8
)(evData0
>> 8);
6764 u16 handle
= le16_to_cpu(evData0
>> 16);
6766 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6767 "SAS Initiator Device Status Change: reason=0x%02x "
6768 "port=%d handle=0x%04x",
6769 reason
, port_num
, handle
);
6773 case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW
:
6775 u8 max_init
= (u8
)(evData0
);
6776 u8 current_init
= (u8
)(evData0
>> 8);
6778 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6779 "SAS Initiator Device Table Overflow: max initiators=%02d "
6780 "current initators=%02d",
6781 max_init
, current_init
);
6784 case MPI_EVENT_SAS_SMP_ERROR
:
6786 u8 status
= (u8
)(evData0
);
6787 u8 port_num
= (u8
)(evData0
>> 8);
6788 u8 result
= (u8
)(evData0
>> 16);
6790 if (status
== MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID
)
6791 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6792 "SAS SMP Error: port=%d result=0x%02x",
6794 else if (status
== MPI_EVENT_SAS_SMP_CRC_ERROR
)
6795 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6796 "SAS SMP Error: port=%d : CRC Error",
6798 else if (status
== MPI_EVENT_SAS_SMP_TIMEOUT
)
6799 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6800 "SAS SMP Error: port=%d : Timeout",
6802 else if (status
== MPI_EVENT_SAS_SMP_NO_DESTINATION
)
6803 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6804 "SAS SMP Error: port=%d : No Destination",
6806 else if (status
== MPI_EVENT_SAS_SMP_BAD_DESTINATION
)
6807 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6808 "SAS SMP Error: port=%d : Bad Destination",
6811 snprintf(evStr
, EVENT_DESCR_STR_SZ
,
6812 "SAS SMP Error: port=%d : status=0x%02x",
6818 * MPT base "custom" events may be added here...
6825 strncpy(evStr
, ds
, EVENT_DESCR_STR_SZ
);
6828 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6830 * ProcessEventNotification - Route EventNotificationReply to all event handlers
6831 * @ioc: Pointer to MPT_ADAPTER structure
6832 * @pEventReply: Pointer to EventNotification reply frame
6833 * @evHandlers: Pointer to integer, number of event handlers
6835 * Routes a received EventNotificationReply to all currently registered
6837 * Returns sum of event handlers return values.
6840 ProcessEventNotification(MPT_ADAPTER
*ioc
, EventNotificationReply_t
*pEventReply
, int *evHandlers
)
6849 char evStr
[EVENT_DESCR_STR_SZ
];
6853 * Do platform normalization of values
6855 event
= le32_to_cpu(pEventReply
->Event
) & 0xFF;
6856 // evCtx = le32_to_cpu(pEventReply->EventContext);
6857 evDataLen
= le16_to_cpu(pEventReply
->EventDataLength
);
6859 evData0
= le32_to_cpu(pEventReply
->Data
[0]);
6862 EventDescriptionStr(event
, evData0
, evStr
);
6863 devtprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"MPT event:(%02Xh) : %s\n",
6868 #ifdef CONFIG_FUSION_LOGGING
6869 devtverboseprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
6870 ": Event data:\n", ioc
->name
));
6871 for (ii
= 0; ii
< evDataLen
; ii
++)
6872 devtverboseprintk(ioc
, printk(" %08x",
6873 le32_to_cpu(pEventReply
->Data
[ii
])));
6874 devtverboseprintk(ioc
, printk("\n"));
6878 * Do general / base driver event processing
6881 case MPI_EVENT_EVENT_CHANGE
: /* 0A */
6883 u8 evState
= evData0
& 0xFF;
6885 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6887 /* Update EventState field in cached IocFacts */
6888 if (ioc
->facts
.Function
) {
6889 ioc
->facts
.EventState
= evState
;
6893 case MPI_EVENT_INTEGRATED_RAID
:
6894 mptbase_raid_process_event_data(ioc
,
6895 (MpiEventDataRaid_t
*)pEventReply
->Data
);
6902 * Should this event be logged? Events are written sequentially.
6903 * When buffer is full, start again at the top.
6905 if (ioc
->events
&& (ioc
->eventTypes
& ( 1 << event
))) {
6908 idx
= ioc
->eventContext
% MPTCTL_EVENT_LOG_SIZE
;
6910 ioc
->events
[idx
].event
= event
;
6911 ioc
->events
[idx
].eventContext
= ioc
->eventContext
;
6913 for (ii
= 0; ii
< 2; ii
++) {
6915 ioc
->events
[idx
].data
[ii
] = le32_to_cpu(pEventReply
->Data
[ii
]);
6917 ioc
->events
[idx
].data
[ii
] = 0;
6920 ioc
->eventContext
++;
6925 * Call each currently registered protocol event handler.
6927 for (cb_idx
= MPT_MAX_PROTOCOL_DRIVERS
-1; cb_idx
; cb_idx
--) {
6928 if (MptEvHandlers
[cb_idx
]) {
6929 devtverboseprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"Routing Event to event handler #%d\n",
6930 ioc
->name
, cb_idx
));
6931 r
+= (*(MptEvHandlers
[cb_idx
]))(ioc
, pEventReply
);
6935 /* FIXME? Examine results here? */
6938 * If needed, send (a single) EventAck.
6940 if (pEventReply
->AckRequired
== MPI_EVENT_NOTIFICATION_ACK_REQUIRED
) {
6941 devtverboseprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
6942 "EventAck required\n",ioc
->name
));
6943 if ((ii
= SendEventAck(ioc
, pEventReply
)) != 0) {
6944 devtverboseprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"SendEventAck returned %d\n",
6949 *evHandlers
= handlers
;
6953 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6955 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6956 * @ioc: Pointer to MPT_ADAPTER structure
6957 * @log_info: U32 LogInfo reply word from the IOC
6959 * Refer to lsi/mpi_log_fc.h.
6962 mpt_fc_log_info(MPT_ADAPTER
*ioc
, u32 log_info
)
6964 char *desc
= "unknown";
6966 switch (log_info
& 0xFF000000) {
6967 case MPI_IOCLOGINFO_FC_INIT_BASE
:
6968 desc
= "FCP Initiator";
6970 case MPI_IOCLOGINFO_FC_TARGET_BASE
:
6971 desc
= "FCP Target";
6973 case MPI_IOCLOGINFO_FC_LAN_BASE
:
6976 case MPI_IOCLOGINFO_FC_MSG_BASE
:
6977 desc
= "MPI Message Layer";
6979 case MPI_IOCLOGINFO_FC_LINK_BASE
:
6982 case MPI_IOCLOGINFO_FC_CTX_BASE
:
6983 desc
= "Context Manager";
6985 case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET
:
6986 desc
= "Invalid Field Offset";
6988 case MPI_IOCLOGINFO_FC_STATE_CHANGE
:
6989 desc
= "State Change Info";
6993 printk(MYIOC_s_INFO_FMT
"LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
6994 ioc
->name
, log_info
, desc
, (log_info
& 0xFFFFFF));
6997 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6999 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
7000 * @ioc: Pointer to MPT_ADAPTER structure
7001 * @log_info: U32 LogInfo word from the IOC
7003 * Refer to lsi/sp_log.h.
7006 mpt_spi_log_info(MPT_ADAPTER
*ioc
, u32 log_info
)
7008 u32 info
= log_info
& 0x00FF0000;
7009 char *desc
= "unknown";
7013 desc
= "bug! MID not found";
7014 if (ioc
->reload_fw
== 0)
7019 desc
= "Parity Error";
7023 desc
= "ASYNC Outbound Overrun";
7027 desc
= "SYNC Offset Error";
7035 desc
= "Msg In Overflow";
7043 desc
= "Outbound DMA Overrun";
7047 desc
= "Task Management";
7051 desc
= "Device Problem";
7055 desc
= "Invalid Phase Change";
7059 desc
= "Untagged Table Size";
7064 printk(MYIOC_s_INFO_FMT
"LogInfo(0x%08x): F/W: %s\n", ioc
->name
, log_info
, desc
);
7067 /* strings for sas loginfo */
7068 static char *originator_str
[] = {
7073 static char *iop_code_str
[] = {
7075 "Invalid SAS Address", /* 01h */
7077 "Invalid Page", /* 03h */
7078 "Diag Message Error", /* 04h */
7079 "Task Terminated", /* 05h */
7080 "Enclosure Management", /* 06h */
7081 "Target Mode" /* 07h */
7083 static char *pl_code_str
[] = {
7085 "Open Failure", /* 01h */
7086 "Invalid Scatter Gather List", /* 02h */
7087 "Wrong Relative Offset or Frame Length", /* 03h */
7088 "Frame Transfer Error", /* 04h */
7089 "Transmit Frame Connected Low", /* 05h */
7090 "SATA Non-NCQ RW Error Bit Set", /* 06h */
7091 "SATA Read Log Receive Data Error", /* 07h */
7092 "SATA NCQ Fail All Commands After Error", /* 08h */
7093 "SATA Error in Receive Set Device Bit FIS", /* 09h */
7094 "Receive Frame Invalid Message", /* 0Ah */
7095 "Receive Context Message Valid Error", /* 0Bh */
7096 "Receive Frame Current Frame Error", /* 0Ch */
7097 "SATA Link Down", /* 0Dh */
7098 "Discovery SATA Init W IOS", /* 0Eh */
7099 "Config Invalid Page", /* 0Fh */
7100 "Discovery SATA Init Timeout", /* 10h */
7103 "IO Not Yet Executed", /* 13h */
7104 "IO Executed", /* 14h */
7105 "Persistent Reservation Out Not Affiliation "
7107 "Open Transmit DMA Abort", /* 16h */
7108 "IO Device Missing Delay Retry", /* 17h */
7109 "IO Cancelled Due to Recieve Error", /* 18h */
7117 "Enclosure Management" /* 20h */
7119 static char *ir_code_str
[] = {
7120 "Raid Action Error", /* 00h */
7130 static char *raid_sub_code_str
[] = {
7132 "Volume Creation Failed: Data Passed too "
7134 "Volume Creation Failed: Duplicate Volumes "
7135 "Attempted", /* 02h */
7136 "Volume Creation Failed: Max Number "
7137 "Supported Volumes Exceeded", /* 03h */
7138 "Volume Creation Failed: DMA Error", /* 04h */
7139 "Volume Creation Failed: Invalid Volume Type", /* 05h */
7140 "Volume Creation Failed: Error Reading "
7141 "MFG Page 4", /* 06h */
7142 "Volume Creation Failed: Creating Internal "
7143 "Structures", /* 07h */
7152 "Activation failed: Already Active Volume", /* 10h */
7153 "Activation failed: Unsupported Volume Type", /* 11h */
7154 "Activation failed: Too Many Active Volumes", /* 12h */
7155 "Activation failed: Volume ID in Use", /* 13h */
7156 "Activation failed: Reported Failure", /* 14h */
7157 "Activation failed: Importing a Volume", /* 15h */
7168 "Phys Disk failed: Too Many Phys Disks", /* 20h */
7169 "Phys Disk failed: Data Passed too Large", /* 21h */
7170 "Phys Disk failed: DMA Error", /* 22h */
7171 "Phys Disk failed: Invalid <channel:id>", /* 23h */
7172 "Phys Disk failed: Creating Phys Disk Config "
7185 "Compatibility Error: IR Disabled", /* 30h */
7186 "Compatibility Error: Inquiry Comand Failed", /* 31h */
7187 "Compatibility Error: Device not Direct Access "
7188 "Device ", /* 32h */
7189 "Compatibility Error: Removable Device Found", /* 33h */
7190 "Compatibility Error: Device SCSI Version not "
7191 "2 or Higher", /* 34h */
7192 "Compatibility Error: SATA Device, 48 BIT LBA "
7193 "not Supported", /* 35h */
7194 "Compatibility Error: Device doesn't have "
7195 "512 Byte Block Sizes", /* 36h */
7196 "Compatibility Error: Volume Type Check Failed", /* 37h */
7197 "Compatibility Error: Volume Type is "
7198 "Unsupported by FW", /* 38h */
7199 "Compatibility Error: Disk Drive too Small for "
7200 "use in Volume", /* 39h */
7201 "Compatibility Error: Phys Disk for Create "
7202 "Volume not Found", /* 3Ah */
7203 "Compatibility Error: Too Many or too Few "
7204 "Disks for Volume Type", /* 3Bh */
7205 "Compatibility Error: Disk stripe Sizes "
7206 "Must be 64KB", /* 3Ch */
7207 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
7210 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7212 * mpt_sas_log_info - Log information returned from SAS IOC.
7213 * @ioc: Pointer to MPT_ADAPTER structure
7214 * @log_info: U32 LogInfo reply word from the IOC
7216 * Refer to lsi/mpi_log_sas.h.
7219 mpt_sas_log_info(MPT_ADAPTER
*ioc
, u32 log_info
)
7221 union loginfo_type
{
7230 union loginfo_type sas_loginfo
;
7231 char *originator_desc
= NULL
;
7232 char *code_desc
= NULL
;
7233 char *sub_code_desc
= NULL
;
7235 sas_loginfo
.loginfo
= log_info
;
7236 if ((sas_loginfo
.dw
.bus_type
!= 3 /*SAS*/) &&
7237 (sas_loginfo
.dw
.originator
< ARRAY_SIZE(originator_str
)))
7240 originator_desc
= originator_str
[sas_loginfo
.dw
.originator
];
7242 switch (sas_loginfo
.dw
.originator
) {
7245 if (sas_loginfo
.dw
.code
<
7246 ARRAY_SIZE(iop_code_str
))
7247 code_desc
= iop_code_str
[sas_loginfo
.dw
.code
];
7250 if (sas_loginfo
.dw
.code
<
7251 ARRAY_SIZE(pl_code_str
))
7252 code_desc
= pl_code_str
[sas_loginfo
.dw
.code
];
7255 if (sas_loginfo
.dw
.code
>=
7256 ARRAY_SIZE(ir_code_str
))
7258 code_desc
= ir_code_str
[sas_loginfo
.dw
.code
];
7259 if (sas_loginfo
.dw
.subcode
>=
7260 ARRAY_SIZE(raid_sub_code_str
))
7262 if (sas_loginfo
.dw
.code
== 0)
7264 raid_sub_code_str
[sas_loginfo
.dw
.subcode
];
7270 if (sub_code_desc
!= NULL
)
7271 printk(MYIOC_s_INFO_FMT
7272 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7274 ioc
->name
, log_info
, originator_desc
, code_desc
,
7276 else if (code_desc
!= NULL
)
7277 printk(MYIOC_s_INFO_FMT
7278 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7279 " SubCode(0x%04x)\n",
7280 ioc
->name
, log_info
, originator_desc
, code_desc
,
7281 sas_loginfo
.dw
.subcode
);
7283 printk(MYIOC_s_INFO_FMT
7284 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
7285 " SubCode(0x%04x)\n",
7286 ioc
->name
, log_info
, originator_desc
,
7287 sas_loginfo
.dw
.code
, sas_loginfo
.dw
.subcode
);
7290 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7292 * mpt_iocstatus_info_config - IOCSTATUS information for config pages
7293 * @ioc: Pointer to MPT_ADAPTER structure
7294 * @ioc_status: U32 IOCStatus word from IOC
7295 * @mf: Pointer to MPT request frame
7297 * Refer to lsi/mpi.h.
7300 mpt_iocstatus_info_config(MPT_ADAPTER
*ioc
, u32 ioc_status
, MPT_FRAME_HDR
*mf
)
7302 Config_t
*pReq
= (Config_t
*)mf
;
7303 char extend_desc
[EVENT_DESCR_STR_SZ
];
7308 if (pReq
->Header
.PageType
== MPI_CONFIG_PAGETYPE_EXTENDED
)
7309 page_type
= pReq
->ExtPageType
;
7311 page_type
= pReq
->Header
.PageType
;
7314 * ignore invalid page messages for GET_NEXT_HANDLE
7316 form
= le32_to_cpu(pReq
->PageAddress
);
7317 if (ioc_status
== MPI_IOCSTATUS_CONFIG_INVALID_PAGE
) {
7318 if (page_type
== MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE
||
7319 page_type
== MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER
||
7320 page_type
== MPI_CONFIG_EXTPAGETYPE_ENCLOSURE
) {
7321 if ((form
>> MPI_SAS_DEVICE_PGAD_FORM_SHIFT
) ==
7322 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE
)
7325 if (page_type
== MPI_CONFIG_PAGETYPE_FC_DEVICE
)
7326 if ((form
& MPI_FC_DEVICE_PGAD_FORM_MASK
) ==
7327 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID
)
7331 snprintf(extend_desc
, EVENT_DESCR_STR_SZ
,
7332 "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
7333 page_type
, pReq
->Header
.PageNumber
, pReq
->Action
, form
);
7335 switch (ioc_status
) {
7337 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION
: /* 0x0020 */
7338 desc
= "Config Page Invalid Action";
7341 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE
: /* 0x0021 */
7342 desc
= "Config Page Invalid Type";
7345 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE
: /* 0x0022 */
7346 desc
= "Config Page Invalid Page";
7349 case MPI_IOCSTATUS_CONFIG_INVALID_DATA
: /* 0x0023 */
7350 desc
= "Config Page Invalid Data";
7353 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS
: /* 0x0024 */
7354 desc
= "Config Page No Defaults";
7357 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT
: /* 0x0025 */
7358 desc
= "Config Page Can't Commit";
7365 dreplyprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"IOCStatus(0x%04X): %s: %s\n",
7366 ioc
->name
, ioc_status
, desc
, extend_desc
));
7370 * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
7371 * @ioc: Pointer to MPT_ADAPTER structure
7372 * @ioc_status: U32 IOCStatus word from IOC
7373 * @mf: Pointer to MPT request frame
7375 * Refer to lsi/mpi.h.
7378 mpt_iocstatus_info(MPT_ADAPTER
*ioc
, u32 ioc_status
, MPT_FRAME_HDR
*mf
)
7380 u32 status
= ioc_status
& MPI_IOCSTATUS_MASK
;
7385 /****************************************************************************/
7386 /* Common IOCStatus values for all replies */
7387 /****************************************************************************/
7389 case MPI_IOCSTATUS_INVALID_FUNCTION
: /* 0x0001 */
7390 desc
= "Invalid Function";
7393 case MPI_IOCSTATUS_BUSY
: /* 0x0002 */
7397 case MPI_IOCSTATUS_INVALID_SGL
: /* 0x0003 */
7398 desc
= "Invalid SGL";
7401 case MPI_IOCSTATUS_INTERNAL_ERROR
: /* 0x0004 */
7402 desc
= "Internal Error";
7405 case MPI_IOCSTATUS_RESERVED
: /* 0x0005 */
7409 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES
: /* 0x0006 */
7410 desc
= "Insufficient Resources";
7413 case MPI_IOCSTATUS_INVALID_FIELD
: /* 0x0007 */
7414 desc
= "Invalid Field";
7417 case MPI_IOCSTATUS_INVALID_STATE
: /* 0x0008 */
7418 desc
= "Invalid State";
7421 /****************************************************************************/
7422 /* Config IOCStatus values */
7423 /****************************************************************************/
7425 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION
: /* 0x0020 */
7426 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE
: /* 0x0021 */
7427 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE
: /* 0x0022 */
7428 case MPI_IOCSTATUS_CONFIG_INVALID_DATA
: /* 0x0023 */
7429 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS
: /* 0x0024 */
7430 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT
: /* 0x0025 */
7431 mpt_iocstatus_info_config(ioc
, status
, mf
);
7434 /****************************************************************************/
7435 /* SCSIIO Reply (SPI, FCP, SAS) initiator values */
7437 /* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
7439 /****************************************************************************/
7441 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR
: /* 0x0040 */
7442 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN
: /* 0x0045 */
7443 case MPI_IOCSTATUS_SCSI_INVALID_BUS
: /* 0x0041 */
7444 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID
: /* 0x0042 */
7445 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE
: /* 0x0043 */
7446 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN
: /* 0x0044 */
7447 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR
: /* 0x0046 */
7448 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR
: /* 0x0047 */
7449 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED
: /* 0x0048 */
7450 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH
: /* 0x0049 */
7451 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED
: /* 0x004A */
7452 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED
: /* 0x004B */
7453 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED
: /* 0x004C */
7456 /****************************************************************************/
7457 /* SCSI Target values */
7458 /****************************************************************************/
7460 case MPI_IOCSTATUS_TARGET_PRIORITY_IO
: /* 0x0060 */
7461 desc
= "Target: Priority IO";
7464 case MPI_IOCSTATUS_TARGET_INVALID_PORT
: /* 0x0061 */
7465 desc
= "Target: Invalid Port";
7468 case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX
: /* 0x0062 */
7469 desc
= "Target Invalid IO Index:";
7472 case MPI_IOCSTATUS_TARGET_ABORTED
: /* 0x0063 */
7473 desc
= "Target: Aborted";
7476 case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE
: /* 0x0064 */
7477 desc
= "Target: No Conn Retryable";
7480 case MPI_IOCSTATUS_TARGET_NO_CONNECTION
: /* 0x0065 */
7481 desc
= "Target: No Connection";
7484 case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH
: /* 0x006A */
7485 desc
= "Target: Transfer Count Mismatch";
7488 case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT
: /* 0x006B */
7489 desc
= "Target: STS Data not Sent";
7492 case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR
: /* 0x006D */
7493 desc
= "Target: Data Offset Error";
7496 case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA
: /* 0x006E */
7497 desc
= "Target: Too Much Write Data";
7500 case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT
: /* 0x006F */
7501 desc
= "Target: IU Too Short";
7504 case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT
: /* 0x0070 */
7505 desc
= "Target: ACK NAK Timeout";
7508 case MPI_IOCSTATUS_TARGET_NAK_RECEIVED
: /* 0x0071 */
7509 desc
= "Target: Nak Received";
7512 /****************************************************************************/
7513 /* Fibre Channel Direct Access values */
7514 /****************************************************************************/
7516 case MPI_IOCSTATUS_FC_ABORTED
: /* 0x0066 */
7517 desc
= "FC: Aborted";
7520 case MPI_IOCSTATUS_FC_RX_ID_INVALID
: /* 0x0067 */
7521 desc
= "FC: RX ID Invalid";
7524 case MPI_IOCSTATUS_FC_DID_INVALID
: /* 0x0068 */
7525 desc
= "FC: DID Invalid";
7528 case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT
: /* 0x0069 */
7529 desc
= "FC: Node Logged Out";
7532 case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED
: /* 0x006C */
7533 desc
= "FC: Exchange Canceled";
7536 /****************************************************************************/
7538 /****************************************************************************/
7540 case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND
: /* 0x0080 */
7541 desc
= "LAN: Device not Found";
7544 case MPI_IOCSTATUS_LAN_DEVICE_FAILURE
: /* 0x0081 */
7545 desc
= "LAN: Device Failure";
7548 case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR
: /* 0x0082 */
7549 desc
= "LAN: Transmit Error";
7552 case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED
: /* 0x0083 */
7553 desc
= "LAN: Transmit Aborted";
7556 case MPI_IOCSTATUS_LAN_RECEIVE_ERROR
: /* 0x0084 */
7557 desc
= "LAN: Receive Error";
7560 case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED
: /* 0x0085 */
7561 desc
= "LAN: Receive Aborted";
7564 case MPI_IOCSTATUS_LAN_PARTIAL_PACKET
: /* 0x0086 */
7565 desc
= "LAN: Partial Packet";
7568 case MPI_IOCSTATUS_LAN_CANCELED
: /* 0x0087 */
7569 desc
= "LAN: Canceled";
7572 /****************************************************************************/
7573 /* Serial Attached SCSI values */
7574 /****************************************************************************/
7576 case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED
: /* 0x0090 */
7577 desc
= "SAS: SMP Request Failed";
7580 case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN
: /* 0x0090 */
7581 desc
= "SAS: SMP Data Overrun";
7592 dreplyprintk(ioc
, printk(MYIOC_s_DEBUG_FMT
"IOCStatus(0x%04X): %s\n",
7593 ioc
->name
, status
, desc
));
7596 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7597 EXPORT_SYMBOL(mpt_attach
);
7598 EXPORT_SYMBOL(mpt_detach
);
7600 EXPORT_SYMBOL(mpt_resume
);
7601 EXPORT_SYMBOL(mpt_suspend
);
7603 EXPORT_SYMBOL(ioc_list
);
7604 EXPORT_SYMBOL(mpt_register
);
7605 EXPORT_SYMBOL(mpt_deregister
);
7606 EXPORT_SYMBOL(mpt_event_register
);
7607 EXPORT_SYMBOL(mpt_event_deregister
);
7608 EXPORT_SYMBOL(mpt_reset_register
);
7609 EXPORT_SYMBOL(mpt_reset_deregister
);
7610 EXPORT_SYMBOL(mpt_device_driver_register
);
7611 EXPORT_SYMBOL(mpt_device_driver_deregister
);
7612 EXPORT_SYMBOL(mpt_get_msg_frame
);
7613 EXPORT_SYMBOL(mpt_put_msg_frame
);
7614 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri
);
7615 EXPORT_SYMBOL(mpt_free_msg_frame
);
7616 EXPORT_SYMBOL(mpt_add_sge
);
7617 EXPORT_SYMBOL(mpt_send_handshake_request
);
7618 EXPORT_SYMBOL(mpt_verify_adapter
);
7619 EXPORT_SYMBOL(mpt_GetIocState
);
7620 EXPORT_SYMBOL(mpt_print_ioc_summary
);
7621 EXPORT_SYMBOL(mpt_HardResetHandler
);
7622 EXPORT_SYMBOL(mpt_config
);
7623 EXPORT_SYMBOL(mpt_findImVolumes
);
7624 EXPORT_SYMBOL(mpt_alloc_fw_memory
);
7625 EXPORT_SYMBOL(mpt_free_fw_memory
);
7626 EXPORT_SYMBOL(mptbase_sas_persist_operation
);
7627 EXPORT_SYMBOL(mpt_raid_phys_disk_pg0
);
7629 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7631 * fusion_init - Fusion MPT base driver initialization routine.
7633 * Returns 0 for success, non-zero for failure.
7640 show_mptmod_ver(my_NAME
, my_VERSION
);
7641 printk(KERN_INFO COPYRIGHT
"\n");
7643 for (cb_idx
= 0; cb_idx
< MPT_MAX_PROTOCOL_DRIVERS
; cb_idx
++) {
7644 MptCallbacks
[cb_idx
] = NULL
;
7645 MptDriverClass
[cb_idx
] = MPTUNKNOWN_DRIVER
;
7646 MptEvHandlers
[cb_idx
] = NULL
;
7647 MptResetHandlers
[cb_idx
] = NULL
;
7650 /* Register ourselves (mptbase) in order to facilitate
7651 * EventNotification handling.
7653 mpt_base_index
= mpt_register(mpt_base_reply
, MPTBASE_DRIVER
);
7655 /* Register for hard reset handling callbacks.
7657 mpt_reset_register(mpt_base_index
, mpt_ioc_reset
);
7659 #ifdef CONFIG_PROC_FS
7660 (void) procmpt_create();
7665 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7667 * fusion_exit - Perform driver unload cleanup.
7669 * This routine frees all resources associated with each MPT adapter
7670 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
7676 mpt_reset_deregister(mpt_base_index
);
7678 #ifdef CONFIG_PROC_FS
7683 module_init(fusion_init
);
7684 module_exit(fusion_exit
);