Merge ../scsi-misc-2.6
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / message / fusion / mptbase.c
blob43308df64623ace8b1d261f9b28858643306fc8c
1 /*
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 Logic PCI chip/adapter(s)
6 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
8 * Copyright (c) 1999-2005 LSI Logic Corporation
9 * (mailto:mpt_linux_developer@lsil.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.
23 NO WARRANTY
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>
61 #include <asm/io.h>
62 #ifdef CONFIG_MTRR
63 #include <asm/mtrr.h>
64 #endif
66 #include "mptbase.h"
68 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69 #define my_NAME "Fusion MPT base driver"
70 #define my_VERSION MPT_LINUX_VERSION_COMMON
71 #define MYNAM "mptbase"
73 MODULE_AUTHOR(MODULEAUTHOR);
74 MODULE_DESCRIPTION(my_NAME);
75 MODULE_LICENSE("GPL");
78 * cmd line parameters
80 static int mpt_msi_enable;
81 module_param(mpt_msi_enable, int, 0);
82 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
84 #ifdef MFCNT
85 static int mfcounter = 0;
86 #define PRINT_MF_COUNT 20000
87 #endif
89 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
91 * Public data...
93 int mpt_lan_index = -1;
94 int mpt_stm_index = -1;
96 struct proc_dir_entry *mpt_proc_root_dir;
98 #define WHOINIT_UNKNOWN 0xAA
100 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
102 * Private data...
104 /* Adapter link list */
105 LIST_HEAD(ioc_list);
106 /* Callback lookup table */
107 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
108 /* Protocol driver class lookup table */
109 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
110 /* Event handler lookup table */
111 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
112 /* Reset handler lookup table */
113 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
114 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
116 static int mpt_base_index = -1;
117 static int last_drv_idx = -1;
119 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
121 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
123 * Forward protos...
125 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
126 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
127 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
128 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
129 int sleepFlag);
130 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
131 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
132 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
133 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
135 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
136 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
137 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
138 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
139 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
140 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
141 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
142 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
143 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
144 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
145 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
146 static int PrimeIocFifos(MPT_ADAPTER *ioc);
147 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
148 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
149 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
150 static int GetLanConfigPages(MPT_ADAPTER *ioc);
151 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
152 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
153 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
154 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
155 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
156 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
157 static void mpt_timer_expired(unsigned long data);
158 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
159 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
160 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
161 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
163 #ifdef CONFIG_PROC_FS
164 static int procmpt_summary_read(char *buf, char **start, off_t offset,
165 int request, int *eof, void *data);
166 static int procmpt_version_read(char *buf, char **start, off_t offset,
167 int request, int *eof, void *data);
168 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
169 int request, int *eof, void *data);
170 #endif
171 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
173 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
174 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
175 static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
176 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
177 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
178 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
179 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
181 /* module entry point */
182 static int __init fusion_init (void);
183 static void __exit fusion_exit (void);
185 #define CHIPREG_READ32(addr) readl_relaxed(addr)
186 #define CHIPREG_READ32_dmasync(addr) readl(addr)
187 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
188 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
189 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
191 static void
192 pci_disable_io_access(struct pci_dev *pdev)
194 u16 command_reg;
196 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
197 command_reg &= ~1;
198 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
201 static void
202 pci_enable_io_access(struct pci_dev *pdev)
204 u16 command_reg;
206 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
207 command_reg |= 1;
208 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
212 * Process turbo (context) reply...
214 static void
215 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
217 MPT_FRAME_HDR *mf = NULL;
218 MPT_FRAME_HDR *mr = NULL;
219 int req_idx = 0;
220 int cb_idx;
222 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
223 ioc->name, pa));
225 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
226 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
227 req_idx = pa & 0x0000FFFF;
228 cb_idx = (pa & 0x00FF0000) >> 16;
229 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
230 break;
231 case MPI_CONTEXT_REPLY_TYPE_LAN:
232 cb_idx = mpt_lan_index;
234 * Blind set of mf to NULL here was fatal
235 * after lan_reply says "freeme"
236 * Fix sort of combined with an optimization here;
237 * added explicit check for case where lan_reply
238 * was just returning 1 and doing nothing else.
239 * For this case skip the callback, but set up
240 * proper mf value first here:-)
242 if ((pa & 0x58000000) == 0x58000000) {
243 req_idx = pa & 0x0000FFFF;
244 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
245 mpt_free_msg_frame(ioc, mf);
246 mb();
247 return;
248 break;
250 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
251 break;
252 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
253 cb_idx = mpt_stm_index;
254 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
255 break;
256 default:
257 cb_idx = 0;
258 BUG();
261 /* Check for (valid) IO callback! */
262 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
263 MptCallbacks[cb_idx] == NULL) {
264 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
265 __FUNCTION__, ioc->name, cb_idx);
266 goto out;
269 if (MptCallbacks[cb_idx](ioc, mf, mr))
270 mpt_free_msg_frame(ioc, mf);
271 out:
272 mb();
275 static void
276 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
278 MPT_FRAME_HDR *mf;
279 MPT_FRAME_HDR *mr;
280 int req_idx;
281 int cb_idx;
282 int freeme;
284 u32 reply_dma_low;
285 u16 ioc_stat;
287 /* non-TURBO reply! Hmmm, something may be up...
288 * Newest turbo reply mechanism; get address
289 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
292 /* Map DMA address of reply header to cpu address.
293 * pa is 32 bits - but the dma address may be 32 or 64 bits
294 * get offset based only only the low addresses
297 reply_dma_low = (pa <<= 1);
298 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
299 (reply_dma_low - ioc->reply_frames_low_dma));
301 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
302 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
303 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
305 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
306 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
307 DBG_DUMP_REPLY_FRAME(mr)
309 /* Check/log IOC log info
311 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
312 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
313 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
314 if (ioc->bus_type == FC)
315 mpt_fc_log_info(ioc, log_info);
316 else if (ioc->bus_type == SPI)
317 mpt_spi_log_info(ioc, log_info);
318 else if (ioc->bus_type == SAS)
319 mpt_sas_log_info(ioc, log_info);
321 if (ioc_stat & MPI_IOCSTATUS_MASK) {
322 if (ioc->bus_type == SPI &&
323 cb_idx != mpt_stm_index &&
324 cb_idx != mpt_lan_index)
325 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
329 /* Check for (valid) IO callback! */
330 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
331 MptCallbacks[cb_idx] == NULL) {
332 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
333 __FUNCTION__, ioc->name, cb_idx);
334 freeme = 0;
335 goto out;
338 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
340 out:
341 /* Flush (non-TURBO) reply with a WRITE! */
342 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
344 if (freeme)
345 mpt_free_msg_frame(ioc, mf);
346 mb();
349 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
351 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
352 * @irq: irq number (not used)
353 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
354 * @r: pt_regs pointer (not used)
356 * This routine is registered via the request_irq() kernel API call,
357 * and handles all interrupts generated from a specific MPT adapter
358 * (also referred to as a IO Controller or IOC).
359 * This routine must clear the interrupt from the adapter and does
360 * so by reading the reply FIFO. Multiple replies may be processed
361 * per single call to this routine.
363 * This routine handles register-level access of the adapter but
364 * dispatches (calls) a protocol-specific callback routine to handle
365 * the protocol-specific details of the MPT request completion.
367 static irqreturn_t
368 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
370 MPT_ADAPTER *ioc = bus_id;
371 u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
373 if (pa == 0xFFFFFFFF)
374 return IRQ_NONE;
377 * Drain the reply FIFO!
379 do {
380 if (pa & MPI_ADDRESS_REPLY_A_BIT)
381 mpt_reply(ioc, pa);
382 else
383 mpt_turbo_reply(ioc, pa);
384 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
385 } while (pa != 0xFFFFFFFF);
387 return IRQ_HANDLED;
390 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
392 * mpt_base_reply - MPT base driver's callback routine; all base driver
393 * "internal" request/reply processing is routed here.
394 * Currently used for EventNotification and EventAck handling.
395 * @ioc: Pointer to MPT_ADAPTER structure
396 * @mf: Pointer to original MPT request frame
397 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
399 * Returns 1 indicating original alloc'd request frame ptr
400 * should be freed, or 0 if it shouldn't.
402 static int
403 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
405 int freereq = 1;
406 u8 func;
408 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
410 #if defined(MPT_DEBUG_MSG_FRAME)
411 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
412 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
413 DBG_DUMP_REQUEST_FRAME_HDR(mf)
415 #endif
417 func = reply->u.hdr.Function;
418 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
419 ioc->name, func));
421 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
422 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
423 int evHandlers = 0;
424 int results;
426 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
427 if (results != evHandlers) {
428 /* CHECKME! Any special handling needed here? */
429 devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
430 ioc->name, evHandlers, results));
434 * Hmmm... It seems that EventNotificationReply is an exception
435 * to the rule of one reply per request.
437 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
438 freereq = 0;
439 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
440 ioc->name, pEvReply));
441 } else {
442 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
443 ioc->name, pEvReply));
446 #ifdef CONFIG_PROC_FS
447 // LogEvent(ioc, pEvReply);
448 #endif
450 } else if (func == MPI_FUNCTION_EVENT_ACK) {
451 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
452 ioc->name));
453 } else if (func == MPI_FUNCTION_CONFIG) {
454 CONFIGPARMS *pCfg;
455 unsigned long flags;
457 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
458 ioc->name, mf, reply));
460 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
462 if (pCfg) {
463 /* disable timer and remove from linked list */
464 del_timer(&pCfg->timer);
466 spin_lock_irqsave(&ioc->FreeQlock, flags);
467 list_del(&pCfg->linkage);
468 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
471 * If IOC Status is SUCCESS, save the header
472 * and set the status code to GOOD.
474 pCfg->status = MPT_CONFIG_ERROR;
475 if (reply) {
476 ConfigReply_t *pReply = (ConfigReply_t *)reply;
477 u16 status;
479 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
480 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
481 status, le32_to_cpu(pReply->IOCLogInfo)));
483 pCfg->status = status;
484 if (status == MPI_IOCSTATUS_SUCCESS) {
485 if ((pReply->Header.PageType &
486 MPI_CONFIG_PAGETYPE_MASK) ==
487 MPI_CONFIG_PAGETYPE_EXTENDED) {
488 pCfg->cfghdr.ehdr->ExtPageLength =
489 le16_to_cpu(pReply->ExtPageLength);
490 pCfg->cfghdr.ehdr->ExtPageType =
491 pReply->ExtPageType;
493 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
495 /* If this is a regular header, save PageLength. */
496 /* LMP Do this better so not using a reserved field! */
497 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
498 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
499 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
504 * Wake up the original calling thread
506 pCfg->wait_done = 1;
507 wake_up(&mpt_waitq);
509 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
510 /* we should be always getting a reply frame */
511 memcpy(ioc->persist_reply_frame, reply,
512 min(MPT_DEFAULT_FRAME_SIZE,
513 4*reply->u.reply.MsgLength));
514 del_timer(&ioc->persist_timer);
515 ioc->persist_wait_done = 1;
516 wake_up(&mpt_waitq);
517 } else {
518 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
519 ioc->name, func);
523 * Conditionally tell caller to free the original
524 * EventNotification/EventAck/unexpected request frame!
526 return freereq;
529 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
531 * mpt_register - Register protocol-specific main callback handler.
532 * @cbfunc: callback function pointer
533 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
535 * This routine is called by a protocol-specific driver (SCSI host,
536 * LAN, SCSI target) to register it's reply callback routine. Each
537 * protocol-specific driver must do this before it will be able to
538 * use any IOC resources, such as obtaining request frames.
540 * NOTES: The SCSI protocol driver currently calls this routine thrice
541 * in order to register separate callbacks; one for "normal" SCSI IO;
542 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
544 * Returns a positive integer valued "handle" in the
545 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
546 * Any non-positive return value (including zero!) should be considered
547 * an error by the caller.
550 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
552 int i;
554 last_drv_idx = -1;
557 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
558 * (slot/handle 0 is reserved!)
560 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
561 if (MptCallbacks[i] == NULL) {
562 MptCallbacks[i] = cbfunc;
563 MptDriverClass[i] = dclass;
564 MptEvHandlers[i] = NULL;
565 last_drv_idx = i;
566 break;
570 return last_drv_idx;
573 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
575 * mpt_deregister - Deregister a protocol drivers resources.
576 * @cb_idx: previously registered callback handle
578 * Each protocol-specific driver should call this routine when it's
579 * module is unloaded.
581 void
582 mpt_deregister(int cb_idx)
584 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
585 MptCallbacks[cb_idx] = NULL;
586 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
587 MptEvHandlers[cb_idx] = NULL;
589 last_drv_idx++;
593 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
595 * mpt_event_register - Register protocol-specific event callback
596 * handler.
597 * @cb_idx: previously registered (via mpt_register) callback handle
598 * @ev_cbfunc: callback function
600 * This routine can be called by one or more protocol-specific drivers
601 * if/when they choose to be notified of MPT events.
603 * Returns 0 for success.
606 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
608 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
609 return -1;
611 MptEvHandlers[cb_idx] = ev_cbfunc;
612 return 0;
615 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
617 * mpt_event_deregister - Deregister protocol-specific event callback
618 * handler.
619 * @cb_idx: previously registered callback handle
621 * Each protocol-specific driver should call this routine
622 * when it does not (or can no longer) handle events,
623 * or when it's module is unloaded.
625 void
626 mpt_event_deregister(int cb_idx)
628 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
629 return;
631 MptEvHandlers[cb_idx] = NULL;
634 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
636 * mpt_reset_register - Register protocol-specific IOC reset handler.
637 * @cb_idx: previously registered (via mpt_register) callback handle
638 * @reset_func: reset function
640 * This routine can be called by one or more protocol-specific drivers
641 * if/when they choose to be notified of IOC resets.
643 * Returns 0 for success.
646 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
648 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
649 return -1;
651 MptResetHandlers[cb_idx] = reset_func;
652 return 0;
655 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
657 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
658 * @cb_idx: previously registered callback handle
660 * Each protocol-specific driver should call this routine
661 * when it does not (or can no longer) handle IOC reset handling,
662 * or when it's module is unloaded.
664 void
665 mpt_reset_deregister(int cb_idx)
667 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
668 return;
670 MptResetHandlers[cb_idx] = NULL;
673 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
675 * mpt_device_driver_register - Register device driver hooks
678 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
680 MPT_ADAPTER *ioc;
682 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
683 return -EINVAL;
686 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
688 /* call per pci device probe entry point */
689 list_for_each_entry(ioc, &ioc_list, list) {
690 if(dd_cbfunc->probe) {
691 dd_cbfunc->probe(ioc->pcidev,
692 ioc->pcidev->driver->id_table);
696 return 0;
699 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
701 * mpt_device_driver_deregister - DeRegister device driver hooks
703 void
704 mpt_device_driver_deregister(int cb_idx)
706 struct mpt_pci_driver *dd_cbfunc;
707 MPT_ADAPTER *ioc;
709 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
710 return;
712 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
714 list_for_each_entry(ioc, &ioc_list, list) {
715 if (dd_cbfunc->remove)
716 dd_cbfunc->remove(ioc->pcidev);
719 MptDeviceDriverHandlers[cb_idx] = NULL;
723 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
725 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
726 * allocated per MPT adapter.
727 * @handle: Handle of registered MPT protocol driver
728 * @ioc: Pointer to MPT adapter structure
730 * Returns pointer to a MPT request frame or %NULL if none are available
731 * or IOC is not active.
733 MPT_FRAME_HDR*
734 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
736 MPT_FRAME_HDR *mf;
737 unsigned long flags;
738 u16 req_idx; /* Request index */
740 /* validate handle and ioc identifier */
742 #ifdef MFCNT
743 if (!ioc->active)
744 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
745 #endif
747 /* If interrupts are not attached, do not return a request frame */
748 if (!ioc->active)
749 return NULL;
751 spin_lock_irqsave(&ioc->FreeQlock, flags);
752 if (!list_empty(&ioc->FreeQ)) {
753 int req_offset;
755 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
756 u.frame.linkage.list);
757 list_del(&mf->u.frame.linkage.list);
758 mf->u.frame.linkage.arg1 = 0;
759 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
760 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
761 /* u16! */
762 req_idx = req_offset / ioc->req_sz;
763 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
764 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
765 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
766 #ifdef MFCNT
767 ioc->mfcnt++;
768 #endif
770 else
771 mf = NULL;
772 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
774 #ifdef MFCNT
775 if (mf == NULL)
776 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
777 mfcounter++;
778 if (mfcounter == PRINT_MF_COUNT)
779 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
780 #endif
782 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
783 ioc->name, handle, ioc->id, mf));
784 return mf;
787 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
789 * mpt_put_msg_frame - Send a protocol specific MPT request frame
790 * to a IOC.
791 * @handle: Handle of registered MPT protocol driver
792 * @ioc: Pointer to MPT adapter structure
793 * @mf: Pointer to MPT request frame
795 * This routine posts a MPT request frame to the request post FIFO of a
796 * specific MPT adapter.
798 void
799 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
801 u32 mf_dma_addr;
802 int req_offset;
803 u16 req_idx; /* Request index */
805 /* ensure values are reset properly! */
806 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
807 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
808 /* u16! */
809 req_idx = req_offset / ioc->req_sz;
810 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
811 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
813 #ifdef MPT_DEBUG_MSG_FRAME
815 u32 *m = mf->u.frame.hwhdr.__hdr;
816 int ii, n;
818 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
819 ioc->name, m);
820 n = ioc->req_sz/4 - 1;
821 while (m[n] == 0)
822 n--;
823 for (ii=0; ii<=n; ii++) {
824 if (ii && ((ii%8)==0))
825 printk("\n" KERN_INFO " ");
826 printk(" %08x", le32_to_cpu(m[ii]));
828 printk("\n");
830 #endif
832 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
833 dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
834 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
837 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
839 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
840 * @handle: Handle of registered MPT protocol driver
841 * @ioc: Pointer to MPT adapter structure
842 * @mf: Pointer to MPT request frame
844 * This routine places a MPT request frame back on the MPT adapter's
845 * FreeQ.
847 void
848 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
850 unsigned long flags;
852 /* Put Request back on FreeQ! */
853 spin_lock_irqsave(&ioc->FreeQlock, flags);
854 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
855 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
856 #ifdef MFCNT
857 ioc->mfcnt--;
858 #endif
859 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
862 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
864 * mpt_add_sge - Place a simple SGE at address pAddr.
865 * @pAddr: virtual address for SGE
866 * @flagslength: SGE flags and data transfer length
867 * @dma_addr: Physical address
869 * This routine places a MPT request frame back on the MPT adapter's
870 * FreeQ.
872 void
873 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
875 if (sizeof(dma_addr_t) == sizeof(u64)) {
876 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
877 u32 tmp = dma_addr & 0xFFFFFFFF;
879 pSge->FlagsLength = cpu_to_le32(flagslength);
880 pSge->Address.Low = cpu_to_le32(tmp);
881 tmp = (u32) ((u64)dma_addr >> 32);
882 pSge->Address.High = cpu_to_le32(tmp);
884 } else {
885 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
886 pSge->FlagsLength = cpu_to_le32(flagslength);
887 pSge->Address = cpu_to_le32(dma_addr);
891 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
893 * mpt_send_handshake_request - Send MPT request via doorbell
894 * handshake method.
895 * @handle: Handle of registered MPT protocol driver
896 * @ioc: Pointer to MPT adapter structure
897 * @reqBytes: Size of the request in bytes
898 * @req: Pointer to MPT request frame
899 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
901 * This routine is used exclusively to send MptScsiTaskMgmt
902 * requests since they are required to be sent via doorbell handshake.
904 * NOTE: It is the callers responsibility to byte-swap fields in the
905 * request which are greater than 1 byte in size.
907 * Returns 0 for success, non-zero for failure.
910 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
912 int r = 0;
913 u8 *req_as_bytes;
914 int ii;
916 /* State is known to be good upon entering
917 * this function so issue the bus reset
918 * request.
922 * Emulate what mpt_put_msg_frame() does /wrt to sanity
923 * setting cb_idx/req_idx. But ONLY if this request
924 * is in proper (pre-alloc'd) request buffer range...
926 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
927 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
928 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
929 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
930 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
933 /* Make sure there are no doorbells */
934 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
936 CHIPREG_WRITE32(&ioc->chip->Doorbell,
937 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
938 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
940 /* Wait for IOC doorbell int */
941 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
942 return ii;
945 /* Read doorbell and check for active bit */
946 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
947 return -5;
949 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
950 ioc->name, ii));
952 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
954 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
955 return -2;
958 /* Send request via doorbell handshake */
959 req_as_bytes = (u8 *) req;
960 for (ii = 0; ii < reqBytes/4; ii++) {
961 u32 word;
963 word = ((req_as_bytes[(ii*4) + 0] << 0) |
964 (req_as_bytes[(ii*4) + 1] << 8) |
965 (req_as_bytes[(ii*4) + 2] << 16) |
966 (req_as_bytes[(ii*4) + 3] << 24));
967 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
968 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
969 r = -3;
970 break;
974 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
975 r = 0;
976 else
977 r = -4;
979 /* Make sure there are no doorbells */
980 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
982 return r;
985 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
987 * mpt_host_page_access_control - provides mechanism for the host
988 * driver to control the IOC's Host Page Buffer access.
989 * @ioc: Pointer to MPT adapter structure
990 * @access_control_value: define bits below
992 * Access Control Value - bits[15:12]
993 * 0h Reserved
994 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
995 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
996 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
998 * Returns 0 for success, non-zero for failure.
1001 static int
1002 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1004 int r = 0;
1006 /* return if in use */
1007 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1008 & MPI_DOORBELL_ACTIVE)
1009 return -1;
1011 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1013 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1014 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1015 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1016 (access_control_value<<12)));
1018 /* Wait for IOC to clear Doorbell Status bit */
1019 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1020 return -2;
1021 }else
1022 return 0;
1025 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1027 * mpt_host_page_alloc - allocate system memory for the fw
1028 * If we already allocated memory in past, then resend the same pointer.
1029 * ioc@: Pointer to pointer to IOC adapter
1030 * ioc_init@: Pointer to ioc init config page
1032 * Returns 0 for success, non-zero for failure.
1034 static int
1035 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1037 char *psge;
1038 int flags_length;
1039 u32 host_page_buffer_sz=0;
1041 if(!ioc->HostPageBuffer) {
1043 host_page_buffer_sz =
1044 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1046 if(!host_page_buffer_sz)
1047 return 0; /* fw doesn't need any host buffers */
1049 /* spin till we get enough memory */
1050 while(host_page_buffer_sz > 0) {
1052 if((ioc->HostPageBuffer = pci_alloc_consistent(
1053 ioc->pcidev,
1054 host_page_buffer_sz,
1055 &ioc->HostPageBuffer_dma)) != NULL) {
1057 dinitprintk((MYIOC_s_INFO_FMT
1058 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1059 ioc->name,
1060 ioc->HostPageBuffer,
1061 ioc->HostPageBuffer_dma,
1062 host_page_buffer_sz));
1063 ioc->alloc_total += host_page_buffer_sz;
1064 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1065 break;
1068 host_page_buffer_sz -= (4*1024);
1072 if(!ioc->HostPageBuffer) {
1073 printk(MYIOC_s_ERR_FMT
1074 "Failed to alloc memory for host_page_buffer!\n",
1075 ioc->name);
1076 return -999;
1079 psge = (char *)&ioc_init->HostPageBufferSGE;
1080 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1081 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1082 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1083 MPI_SGE_FLAGS_HOST_TO_IOC |
1084 MPI_SGE_FLAGS_END_OF_BUFFER;
1085 if (sizeof(dma_addr_t) == sizeof(u64)) {
1086 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1088 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1089 flags_length |= ioc->HostPageBuffer_sz;
1090 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1091 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1093 return 0;
1096 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1098 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1099 * the associated MPT adapter structure.
1100 * @iocid: IOC unique identifier (integer)
1101 * @iocpp: Pointer to pointer to IOC adapter
1103 * Returns iocid and sets iocpp.
1106 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1108 MPT_ADAPTER *ioc;
1110 list_for_each_entry(ioc,&ioc_list,list) {
1111 if (ioc->id == iocid) {
1112 *iocpp =ioc;
1113 return iocid;
1117 *iocpp = NULL;
1118 return -1;
1121 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1123 * mpt_attach - Install a PCI intelligent MPT adapter.
1124 * @pdev: Pointer to pci_dev structure
1126 * This routine performs all the steps necessary to bring the IOC of
1127 * a MPT adapter to a OPERATIONAL state. This includes registering
1128 * memory regions, registering the interrupt, and allocating request
1129 * and reply memory pools.
1131 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1132 * MPT adapter.
1134 * Returns 0 for success, non-zero for failure.
1136 * TODO: Add support for polled controllers
1139 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1141 MPT_ADAPTER *ioc;
1142 u8 __iomem *mem;
1143 unsigned long mem_phys;
1144 unsigned long port;
1145 u32 msize;
1146 u32 psize;
1147 int ii;
1148 int r = -ENODEV;
1149 u8 revision;
1150 u8 pcixcmd;
1151 static int mpt_ids = 0;
1152 #ifdef CONFIG_PROC_FS
1153 struct proc_dir_entry *dent, *ent;
1154 #endif
1156 if (pci_enable_device(pdev))
1157 return r;
1159 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1161 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1162 dprintk((KERN_INFO MYNAM
1163 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1164 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1165 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1166 return r;
1169 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1170 dprintk((KERN_INFO MYNAM
1171 ": Using 64 bit consistent mask\n"));
1172 else
1173 dprintk((KERN_INFO MYNAM
1174 ": Not using 64 bit consistent mask\n"));
1176 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1177 if (ioc == NULL) {
1178 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1179 return -ENOMEM;
1181 ioc->alloc_total = sizeof(MPT_ADAPTER);
1182 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1183 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1185 ioc->pcidev = pdev;
1186 ioc->diagPending = 0;
1187 spin_lock_init(&ioc->diagLock);
1188 spin_lock_init(&ioc->initializing_hba_lock);
1190 /* Initialize the event logging.
1192 ioc->eventTypes = 0; /* None */
1193 ioc->eventContext = 0;
1194 ioc->eventLogSize = 0;
1195 ioc->events = NULL;
1197 #ifdef MFCNT
1198 ioc->mfcnt = 0;
1199 #endif
1201 ioc->cached_fw = NULL;
1203 /* Initilize SCSI Config Data structure
1205 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1207 /* Initialize the running configQ head.
1209 INIT_LIST_HEAD(&ioc->configQ);
1211 /* Initialize the fc rport list head.
1213 INIT_LIST_HEAD(&ioc->fc_rports);
1215 /* Find lookup slot. */
1216 INIT_LIST_HEAD(&ioc->list);
1217 ioc->id = mpt_ids++;
1219 mem_phys = msize = 0;
1220 port = psize = 0;
1221 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1222 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1223 if (psize)
1224 continue;
1225 /* Get I/O space! */
1226 port = pci_resource_start(pdev, ii);
1227 psize = pci_resource_len(pdev,ii);
1228 } else {
1229 if (msize)
1230 continue;
1231 /* Get memmap */
1232 mem_phys = pci_resource_start(pdev, ii);
1233 msize = pci_resource_len(pdev,ii);
1236 ioc->mem_size = msize;
1238 mem = NULL;
1239 /* Get logical ptr for PciMem0 space */
1240 /*mem = ioremap(mem_phys, msize);*/
1241 mem = ioremap(mem_phys, msize);
1242 if (mem == NULL) {
1243 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1244 kfree(ioc);
1245 return -EINVAL;
1247 ioc->memmap = mem;
1248 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1250 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1251 &ioc->facts, &ioc->pfacts[0]));
1253 ioc->mem_phys = mem_phys;
1254 ioc->chip = (SYSIF_REGS __iomem *)mem;
1256 /* Save Port IO values in case we need to do downloadboot */
1258 u8 *pmem = (u8*)port;
1259 ioc->pio_mem_phys = port;
1260 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1263 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1264 ioc->prod_name = "LSIFC909";
1265 ioc->bus_type = FC;
1267 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1268 ioc->prod_name = "LSIFC929";
1269 ioc->bus_type = FC;
1271 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1272 ioc->prod_name = "LSIFC919";
1273 ioc->bus_type = FC;
1275 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1276 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1277 ioc->bus_type = FC;
1278 if (revision < XL_929) {
1279 ioc->prod_name = "LSIFC929X";
1280 /* 929X Chip Fix. Set Split transactions level
1281 * for PCIX. Set MOST bits to zero.
1283 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1284 pcixcmd &= 0x8F;
1285 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1286 } else {
1287 ioc->prod_name = "LSIFC929XL";
1288 /* 929XL Chip Fix. Set MMRBC to 0x08.
1290 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1291 pcixcmd |= 0x08;
1292 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1295 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1296 ioc->prod_name = "LSIFC919X";
1297 ioc->bus_type = FC;
1298 /* 919X Chip Fix. Set Split transactions level
1299 * for PCIX. Set MOST bits to zero.
1301 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1302 pcixcmd &= 0x8F;
1303 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1305 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1306 ioc->prod_name = "LSIFC939X";
1307 ioc->bus_type = FC;
1308 ioc->errata_flag_1064 = 1;
1310 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1311 ioc->prod_name = "LSIFC949X";
1312 ioc->bus_type = FC;
1313 ioc->errata_flag_1064 = 1;
1315 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1316 ioc->prod_name = "LSIFC949E";
1317 ioc->bus_type = FC;
1319 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1320 ioc->prod_name = "LSI53C1030";
1321 ioc->bus_type = SPI;
1322 /* 1030 Chip Fix. Disable Split transactions
1323 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1325 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1326 if (revision < C0_1030) {
1327 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1328 pcixcmd &= 0x8F;
1329 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1332 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1333 ioc->prod_name = "LSI53C1035";
1334 ioc->bus_type = SPI;
1336 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1337 ioc->prod_name = "LSISAS1064";
1338 ioc->bus_type = SAS;
1339 ioc->errata_flag_1064 = 1;
1341 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1342 ioc->prod_name = "LSISAS1068";
1343 ioc->bus_type = SAS;
1344 ioc->errata_flag_1064 = 1;
1346 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1347 ioc->prod_name = "LSISAS1064E";
1348 ioc->bus_type = SAS;
1350 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1351 ioc->prod_name = "LSISAS1068E";
1352 ioc->bus_type = SAS;
1354 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
1355 ioc->prod_name = "LSISAS1078";
1356 ioc->bus_type = SAS;
1359 if (ioc->errata_flag_1064)
1360 pci_disable_io_access(pdev);
1362 sprintf(ioc->name, "ioc%d", ioc->id);
1364 spin_lock_init(&ioc->FreeQlock);
1366 /* Disable all! */
1367 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1368 ioc->active = 0;
1369 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1371 /* Set lookup ptr. */
1372 list_add_tail(&ioc->list, &ioc_list);
1374 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1376 mpt_detect_bound_ports(ioc, pdev);
1378 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1379 CAN_SLEEP)) != 0){
1380 printk(KERN_WARNING MYNAM
1381 ": WARNING - %s did not initialize properly! (%d)\n",
1382 ioc->name, r);
1383 list_del(&ioc->list);
1384 if (ioc->alt_ioc)
1385 ioc->alt_ioc->alt_ioc = NULL;
1386 iounmap(mem);
1387 kfree(ioc);
1388 pci_set_drvdata(pdev, NULL);
1389 return r;
1392 /* call per device driver probe entry point */
1393 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1394 if(MptDeviceDriverHandlers[ii] &&
1395 MptDeviceDriverHandlers[ii]->probe) {
1396 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1400 #ifdef CONFIG_PROC_FS
1402 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1404 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1405 if (dent) {
1406 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1407 if (ent) {
1408 ent->read_proc = procmpt_iocinfo_read;
1409 ent->data = ioc;
1411 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1412 if (ent) {
1413 ent->read_proc = procmpt_summary_read;
1414 ent->data = ioc;
1417 #endif
1419 return 0;
1422 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1424 * mpt_detach - Remove a PCI intelligent MPT adapter.
1425 * @pdev: Pointer to pci_dev structure
1429 void
1430 mpt_detach(struct pci_dev *pdev)
1432 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1433 char pname[32];
1434 int ii;
1436 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1437 remove_proc_entry(pname, NULL);
1438 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1439 remove_proc_entry(pname, NULL);
1440 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1441 remove_proc_entry(pname, NULL);
1443 /* call per device driver remove entry point */
1444 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1445 if(MptDeviceDriverHandlers[ii] &&
1446 MptDeviceDriverHandlers[ii]->remove) {
1447 MptDeviceDriverHandlers[ii]->remove(pdev);
1451 /* Disable interrupts! */
1452 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1454 ioc->active = 0;
1455 synchronize_irq(pdev->irq);
1457 /* Clear any lingering interrupt */
1458 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1460 CHIPREG_READ32(&ioc->chip->IntStatus);
1462 mpt_adapter_dispose(ioc);
1464 pci_set_drvdata(pdev, NULL);
1467 /**************************************************************************
1468 * Power Management
1470 #ifdef CONFIG_PM
1471 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1473 * mpt_suspend - Fusion MPT base driver suspend routine.
1478 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1480 u32 device_state;
1481 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1483 device_state=pci_choose_state(pdev, state);
1485 printk(MYIOC_s_INFO_FMT
1486 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1487 ioc->name, pdev, pci_name(pdev), device_state);
1489 pci_save_state(pdev);
1491 /* put ioc into READY_STATE */
1492 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1493 printk(MYIOC_s_ERR_FMT
1494 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1497 /* disable interrupts */
1498 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1499 ioc->active = 0;
1501 /* Clear any lingering interrupt */
1502 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1504 pci_disable_device(pdev);
1505 pci_set_power_state(pdev, device_state);
1507 return 0;
1510 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1512 * mpt_resume - Fusion MPT base driver resume routine.
1517 mpt_resume(struct pci_dev *pdev)
1519 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1520 u32 device_state = pdev->current_state;
1521 int recovery_state;
1523 printk(MYIOC_s_INFO_FMT
1524 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1525 ioc->name, pdev, pci_name(pdev), device_state);
1527 pci_set_power_state(pdev, 0);
1528 pci_restore_state(pdev);
1529 pci_enable_device(pdev);
1531 /* enable interrupts */
1532 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1533 ioc->active = 1;
1535 printk(MYIOC_s_INFO_FMT
1536 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1537 ioc->name,
1538 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1539 CHIPREG_READ32(&ioc->chip->Doorbell));
1541 /* bring ioc to operational state */
1542 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1543 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1544 printk(MYIOC_s_INFO_FMT
1545 "pci-resume: Cannot recover, error:[%x]\n",
1546 ioc->name, recovery_state);
1547 } else {
1548 printk(MYIOC_s_INFO_FMT
1549 "pci-resume: success\n", ioc->name);
1552 return 0;
1554 #endif
1556 static int
1557 mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
1559 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1560 ioc->bus_type != SPI) ||
1561 (MptDriverClass[index] == MPTFC_DRIVER &&
1562 ioc->bus_type != FC) ||
1563 (MptDriverClass[index] == MPTSAS_DRIVER &&
1564 ioc->bus_type != SAS))
1565 /* make sure we only call the relevant reset handler
1566 * for the bus */
1567 return 0;
1568 return (MptResetHandlers[index])(ioc, reset_phase);
1571 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1573 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1574 * @ioc: Pointer to MPT adapter structure
1575 * @reason: Event word / reason
1576 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1578 * This routine performs all the steps necessary to bring the IOC
1579 * to a OPERATIONAL state.
1581 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1582 * MPT adapter.
1584 * Returns:
1585 * 0 for success
1586 * -1 if failed to get board READY
1587 * -2 if READY but IOCFacts Failed
1588 * -3 if READY but PrimeIOCFifos Failed
1589 * -4 if READY but IOCInit Failed
1591 static int
1592 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1594 int hard_reset_done = 0;
1595 int alt_ioc_ready = 0;
1596 int hard;
1597 int rc=0;
1598 int ii;
1599 int handlers;
1600 int ret = 0;
1601 int reset_alt_ioc_active = 0;
1602 int irq_allocated = 0;
1604 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1605 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1607 /* Disable reply interrupts (also blocks FreeQ) */
1608 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1609 ioc->active = 0;
1611 if (ioc->alt_ioc) {
1612 if (ioc->alt_ioc->active)
1613 reset_alt_ioc_active = 1;
1615 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1616 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1617 ioc->alt_ioc->active = 0;
1620 hard = 1;
1621 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1622 hard = 0;
1624 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1625 if (hard_reset_done == -4) {
1626 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1627 ioc->name);
1629 if (reset_alt_ioc_active && ioc->alt_ioc) {
1630 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1631 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1632 ioc->alt_ioc->name));
1633 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1634 ioc->alt_ioc->active = 1;
1637 } else {
1638 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1639 ioc->name);
1641 return -1;
1644 /* hard_reset_done = 0 if a soft reset was performed
1645 * and 1 if a hard reset was performed.
1647 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1648 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1649 alt_ioc_ready = 1;
1650 else
1651 printk(KERN_WARNING MYNAM
1652 ": alt-%s: Not ready WARNING!\n",
1653 ioc->alt_ioc->name);
1656 for (ii=0; ii<5; ii++) {
1657 /* Get IOC facts! Allow 5 retries */
1658 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1659 break;
1663 if (ii == 5) {
1664 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1665 ret = -2;
1666 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1667 MptDisplayIocCapabilities(ioc);
1670 if (alt_ioc_ready) {
1671 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1672 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1673 /* Retry - alt IOC was initialized once
1675 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1677 if (rc) {
1678 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1679 alt_ioc_ready = 0;
1680 reset_alt_ioc_active = 0;
1681 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1682 MptDisplayIocCapabilities(ioc->alt_ioc);
1687 * Device is reset now. It must have de-asserted the interrupt line
1688 * (if it was asserted) and it should be safe to register for the
1689 * interrupt now.
1691 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1692 ioc->pci_irq = -1;
1693 if (ioc->pcidev->irq) {
1694 if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
1695 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
1696 ioc->name);
1697 rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
1698 IRQF_SHARED, ioc->name, ioc);
1699 if (rc < 0) {
1700 printk(MYIOC_s_ERR_FMT "Unable to allocate "
1701 "interrupt %d!\n", ioc->name,
1702 ioc->pcidev->irq);
1703 if (mpt_msi_enable)
1704 pci_disable_msi(ioc->pcidev);
1705 return -EBUSY;
1707 irq_allocated = 1;
1708 ioc->pci_irq = ioc->pcidev->irq;
1709 pci_set_master(ioc->pcidev); /* ?? */
1710 pci_set_drvdata(ioc->pcidev, ioc);
1711 dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
1712 "%d\n", ioc->name, ioc->pcidev->irq));
1716 /* Prime reply & request queues!
1717 * (mucho alloc's) Must be done prior to
1718 * init as upper addresses are needed for init.
1719 * If fails, continue with alt-ioc processing
1721 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1722 ret = -3;
1724 /* May need to check/upload firmware & data here!
1725 * If fails, continue with alt-ioc processing
1727 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1728 ret = -4;
1729 // NEW!
1730 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1731 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1732 ioc->alt_ioc->name, rc);
1733 alt_ioc_ready = 0;
1734 reset_alt_ioc_active = 0;
1737 if (alt_ioc_ready) {
1738 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1739 alt_ioc_ready = 0;
1740 reset_alt_ioc_active = 0;
1741 printk(KERN_WARNING MYNAM
1742 ": alt-%s: (%d) init failure WARNING!\n",
1743 ioc->alt_ioc->name, rc);
1747 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1748 if (ioc->upload_fw) {
1749 ddlprintk((MYIOC_s_INFO_FMT
1750 "firmware upload required!\n", ioc->name));
1752 /* Controller is not operational, cannot do upload
1754 if (ret == 0) {
1755 rc = mpt_do_upload(ioc, sleepFlag);
1756 if (rc == 0) {
1757 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1759 * Maintain only one pointer to FW memory
1760 * so there will not be two attempt to
1761 * downloadboot onboard dual function
1762 * chips (mpt_adapter_disable,
1763 * mpt_diag_reset)
1765 ioc->cached_fw = NULL;
1766 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1767 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1769 } else {
1770 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1771 ret = -5;
1777 if (ret == 0) {
1778 /* Enable! (reply interrupt) */
1779 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1780 ioc->active = 1;
1783 if (reset_alt_ioc_active && ioc->alt_ioc) {
1784 /* (re)Enable alt-IOC! (reply interrupt) */
1785 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1786 ioc->alt_ioc->name));
1787 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1788 ioc->alt_ioc->active = 1;
1791 /* Enable MPT base driver management of EventNotification
1792 * and EventAck handling.
1794 if ((ret == 0) && (!ioc->facts.EventState))
1795 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1797 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1798 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1800 /* Add additional "reason" check before call to GetLanConfigPages
1801 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1802 * recursive scenario; GetLanConfigPages times out, timer expired
1803 * routine calls HardResetHandler, which calls into here again,
1804 * and we try GetLanConfigPages again...
1806 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1807 if (ioc->bus_type == SAS) {
1809 /* clear persistency table */
1810 if(ioc->facts.IOCExceptions &
1811 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1812 ret = mptbase_sas_persist_operation(ioc,
1813 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1814 if(ret != 0)
1815 goto out;
1818 /* Find IM volumes
1820 mpt_findImVolumes(ioc);
1822 } else if (ioc->bus_type == FC) {
1823 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1824 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1826 * Pre-fetch the ports LAN MAC address!
1827 * (LANPage1_t stuff)
1829 (void) GetLanConfigPages(ioc);
1830 #ifdef MPT_DEBUG
1832 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1833 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1834 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1836 #endif
1838 } else {
1839 /* Get NVRAM and adapter maximums from SPP 0 and 2
1841 mpt_GetScsiPortSettings(ioc, 0);
1843 /* Get version and length of SDP 1
1845 mpt_readScsiDevicePageHeaders(ioc, 0);
1847 /* Find IM volumes
1849 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1850 mpt_findImVolumes(ioc);
1852 /* Check, and possibly reset, the coalescing value
1854 mpt_read_ioc_pg_1(ioc);
1856 mpt_read_ioc_pg_4(ioc);
1859 GetIoUnitPage2(ioc);
1863 * Call each currently registered protocol IOC reset handler
1864 * with post-reset indication.
1865 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1866 * MptResetHandlers[] registered yet.
1868 if (hard_reset_done) {
1869 rc = handlers = 0;
1870 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1871 if ((ret == 0) && MptResetHandlers[ii]) {
1872 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1873 ioc->name, ii));
1874 rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
1875 handlers++;
1878 if (alt_ioc_ready && MptResetHandlers[ii]) {
1879 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1880 ioc->name, ioc->alt_ioc->name, ii));
1881 rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
1882 handlers++;
1885 /* FIXME? Examine results here? */
1888 out:
1889 if ((ret != 0) && irq_allocated) {
1890 free_irq(ioc->pci_irq, ioc);
1891 if (mpt_msi_enable)
1892 pci_disable_msi(ioc->pcidev);
1894 return ret;
1897 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1899 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1900 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1901 * 929X, 1030 or 1035.
1902 * @ioc: Pointer to MPT adapter structure
1903 * @pdev: Pointer to (struct pci_dev) structure
1905 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1906 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1908 static void
1909 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1911 struct pci_dev *peer=NULL;
1912 unsigned int slot = PCI_SLOT(pdev->devfn);
1913 unsigned int func = PCI_FUNC(pdev->devfn);
1914 MPT_ADAPTER *ioc_srch;
1916 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1917 " searching for devfn match on %x or %x\n",
1918 ioc->name, pci_name(pdev), pdev->bus->number,
1919 pdev->devfn, func-1, func+1));
1921 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1922 if (!peer) {
1923 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1924 if (!peer)
1925 return;
1928 list_for_each_entry(ioc_srch, &ioc_list, list) {
1929 struct pci_dev *_pcidev = ioc_srch->pcidev;
1930 if (_pcidev == peer) {
1931 /* Paranoia checks */
1932 if (ioc->alt_ioc != NULL) {
1933 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1934 ioc->name, ioc->alt_ioc->name);
1935 break;
1936 } else if (ioc_srch->alt_ioc != NULL) {
1937 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1938 ioc_srch->name, ioc_srch->alt_ioc->name);
1939 break;
1941 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1942 ioc->name, ioc_srch->name));
1943 ioc_srch->alt_ioc = ioc;
1944 ioc->alt_ioc = ioc_srch;
1947 pci_dev_put(peer);
1950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1952 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1953 * @this: Pointer to MPT adapter structure
1955 static void
1956 mpt_adapter_disable(MPT_ADAPTER *ioc)
1958 int sz;
1959 int ret;
1961 if (ioc->cached_fw != NULL) {
1962 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1963 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1964 printk(KERN_WARNING MYNAM
1965 ": firmware downloadboot failure (%d)!\n", ret);
1969 /* Disable adapter interrupts! */
1970 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1971 ioc->active = 0;
1972 /* Clear any lingering interrupt */
1973 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1975 if (ioc->alloc != NULL) {
1976 sz = ioc->alloc_sz;
1977 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
1978 ioc->name, ioc->alloc, ioc->alloc_sz));
1979 pci_free_consistent(ioc->pcidev, sz,
1980 ioc->alloc, ioc->alloc_dma);
1981 ioc->reply_frames = NULL;
1982 ioc->req_frames = NULL;
1983 ioc->alloc = NULL;
1984 ioc->alloc_total -= sz;
1987 if (ioc->sense_buf_pool != NULL) {
1988 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
1989 pci_free_consistent(ioc->pcidev, sz,
1990 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
1991 ioc->sense_buf_pool = NULL;
1992 ioc->alloc_total -= sz;
1995 if (ioc->events != NULL){
1996 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
1997 kfree(ioc->events);
1998 ioc->events = NULL;
1999 ioc->alloc_total -= sz;
2002 if (ioc->cached_fw != NULL) {
2003 sz = ioc->facts.FWImageSize;
2004 pci_free_consistent(ioc->pcidev, sz,
2005 ioc->cached_fw, ioc->cached_fw_dma);
2006 ioc->cached_fw = NULL;
2007 ioc->alloc_total -= sz;
2010 kfree(ioc->spi_data.nvram);
2011 kfree(ioc->raid_data.pIocPg3);
2012 ioc->spi_data.nvram = NULL;
2013 ioc->raid_data.pIocPg3 = NULL;
2015 if (ioc->spi_data.pIocPg4 != NULL) {
2016 sz = ioc->spi_data.IocPg4Sz;
2017 pci_free_consistent(ioc->pcidev, sz,
2018 ioc->spi_data.pIocPg4,
2019 ioc->spi_data.IocPg4_dma);
2020 ioc->spi_data.pIocPg4 = NULL;
2021 ioc->alloc_total -= sz;
2024 if (ioc->ReqToChain != NULL) {
2025 kfree(ioc->ReqToChain);
2026 kfree(ioc->RequestNB);
2027 ioc->ReqToChain = NULL;
2030 kfree(ioc->ChainToChain);
2031 ioc->ChainToChain = NULL;
2033 if (ioc->HostPageBuffer != NULL) {
2034 if((ret = mpt_host_page_access_control(ioc,
2035 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2036 printk(KERN_ERR MYNAM
2037 ": %s: host page buffers free failed (%d)!\n",
2038 __FUNCTION__, ret);
2040 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2041 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2042 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2043 ioc->HostPageBuffer,
2044 ioc->HostPageBuffer_dma);
2045 ioc->HostPageBuffer = NULL;
2046 ioc->HostPageBuffer_sz = 0;
2047 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2051 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2053 * mpt_adapter_dispose - Free all resources associated with a MPT
2054 * adapter.
2055 * @ioc: Pointer to MPT adapter structure
2057 * This routine unregisters h/w resources and frees all alloc'd memory
2058 * associated with a MPT adapter structure.
2060 static void
2061 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2063 int sz_first, sz_last;
2065 if (ioc == NULL)
2066 return;
2068 sz_first = ioc->alloc_total;
2070 mpt_adapter_disable(ioc);
2072 if (ioc->pci_irq != -1) {
2073 free_irq(ioc->pci_irq, ioc);
2074 if (mpt_msi_enable)
2075 pci_disable_msi(ioc->pcidev);
2076 ioc->pci_irq = -1;
2079 if (ioc->memmap != NULL) {
2080 iounmap(ioc->memmap);
2081 ioc->memmap = NULL;
2084 #if defined(CONFIG_MTRR) && 0
2085 if (ioc->mtrr_reg > 0) {
2086 mtrr_del(ioc->mtrr_reg, 0, 0);
2087 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2089 #endif
2091 /* Zap the adapter lookup ptr! */
2092 list_del(&ioc->list);
2094 sz_last = ioc->alloc_total;
2095 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2096 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2098 if (ioc->alt_ioc)
2099 ioc->alt_ioc->alt_ioc = NULL;
2101 kfree(ioc);
2104 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2106 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2107 * @ioc: Pointer to MPT adapter structure
2109 static void
2110 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2112 int i = 0;
2114 printk(KERN_INFO "%s: ", ioc->name);
2115 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2116 printk("%s: ", ioc->prod_name+3);
2117 printk("Capabilities={");
2119 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2120 printk("Initiator");
2121 i++;
2124 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2125 printk("%sTarget", i ? "," : "");
2126 i++;
2129 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2130 printk("%sLAN", i ? "," : "");
2131 i++;
2134 #if 0
2136 * This would probably evoke more questions than it's worth
2138 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2139 printk("%sLogBusAddr", i ? "," : "");
2140 i++;
2142 #endif
2144 printk("}\n");
2147 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2149 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2150 * @ioc: Pointer to MPT_ADAPTER structure
2151 * @force: Force hard KickStart of IOC
2152 * @sleepFlag: Specifies whether the process can sleep
2154 * Returns:
2155 * 1 - DIAG reset and READY
2156 * 0 - READY initially OR soft reset and READY
2157 * -1 - Any failure on KickStart
2158 * -2 - Msg Unit Reset Failed
2159 * -3 - IO Unit Reset Failed
2160 * -4 - IOC owned by a PEER
2162 static int
2163 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2165 u32 ioc_state;
2166 int statefault = 0;
2167 int cntdn;
2168 int hard_reset_done = 0;
2169 int r;
2170 int ii;
2171 int whoinit;
2173 /* Get current [raw] IOC state */
2174 ioc_state = mpt_GetIocState(ioc, 0);
2175 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2178 * Check to see if IOC got left/stuck in doorbell handshake
2179 * grip of death. If so, hard reset the IOC.
2181 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2182 statefault = 1;
2183 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2184 ioc->name);
2187 /* Is it already READY? */
2188 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2189 return 0;
2192 * Check to see if IOC is in FAULT state.
2194 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2195 statefault = 2;
2196 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2197 ioc->name);
2198 printk(KERN_WARNING " FAULT code = %04xh\n",
2199 ioc_state & MPI_DOORBELL_DATA_MASK);
2203 * Hmmm... Did it get left operational?
2205 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2206 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2207 ioc->name));
2209 /* Check WhoInit.
2210 * If PCI Peer, exit.
2211 * Else, if no fault conditions are present, issue a MessageUnitReset
2212 * Else, fall through to KickStart case
2214 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2215 dinitprintk((KERN_INFO MYNAM
2216 ": whoinit 0x%x statefault %d force %d\n",
2217 whoinit, statefault, force));
2218 if (whoinit == MPI_WHOINIT_PCI_PEER)
2219 return -4;
2220 else {
2221 if ((statefault == 0 ) && (force == 0)) {
2222 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2223 return 0;
2225 statefault = 3;
2229 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2230 if (hard_reset_done < 0)
2231 return -1;
2234 * Loop here waiting for IOC to come READY.
2236 ii = 0;
2237 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2239 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2240 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2242 * BIOS or previous driver load left IOC in OP state.
2243 * Reset messaging FIFOs.
2245 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2246 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2247 return -2;
2249 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2251 * Something is wrong. Try to get IOC back
2252 * to a known state.
2254 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2255 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2256 return -3;
2260 ii++; cntdn--;
2261 if (!cntdn) {
2262 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2263 ioc->name, (int)((ii+5)/HZ));
2264 return -ETIME;
2267 if (sleepFlag == CAN_SLEEP) {
2268 msleep(1);
2269 } else {
2270 mdelay (1); /* 1 msec delay */
2275 if (statefault < 3) {
2276 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2277 ioc->name,
2278 statefault==1 ? "stuck handshake" : "IOC FAULT");
2281 return hard_reset_done;
2284 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2286 * mpt_GetIocState - Get the current state of a MPT adapter.
2287 * @ioc: Pointer to MPT_ADAPTER structure
2288 * @cooked: Request raw or cooked IOC state
2290 * Returns all IOC Doorbell register bits if cooked==0, else just the
2291 * Doorbell bits in MPI_IOC_STATE_MASK.
2294 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2296 u32 s, sc;
2298 /* Get! */
2299 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2300 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2301 sc = s & MPI_IOC_STATE_MASK;
2303 /* Save! */
2304 ioc->last_state = sc;
2306 return cooked ? sc : s;
2309 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2311 * GetIocFacts - Send IOCFacts request to MPT adapter.
2312 * @ioc: Pointer to MPT_ADAPTER structure
2313 * @sleepFlag: Specifies whether the process can sleep
2314 * @reason: If recovery, only update facts.
2316 * Returns 0 for success, non-zero for failure.
2318 static int
2319 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2321 IOCFacts_t get_facts;
2322 IOCFactsReply_t *facts;
2323 int r;
2324 int req_sz;
2325 int reply_sz;
2326 int sz;
2327 u32 status, vv;
2328 u8 shiftFactor=1;
2330 /* IOC *must* NOT be in RESET state! */
2331 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2332 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2333 ioc->name,
2334 ioc->last_state );
2335 return -44;
2338 facts = &ioc->facts;
2340 /* Destination (reply area)... */
2341 reply_sz = sizeof(*facts);
2342 memset(facts, 0, reply_sz);
2344 /* Request area (get_facts on the stack right now!) */
2345 req_sz = sizeof(get_facts);
2346 memset(&get_facts, 0, req_sz);
2348 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2349 /* Assert: All other get_facts fields are zero! */
2351 dinitprintk((MYIOC_s_INFO_FMT
2352 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2353 ioc->name, req_sz, reply_sz));
2355 /* No non-zero fields in the get_facts request are greater than
2356 * 1 byte in size, so we can just fire it off as is.
2358 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2359 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2360 if (r != 0)
2361 return r;
2364 * Now byte swap (GRRR) the necessary fields before any further
2365 * inspection of reply contents.
2367 * But need to do some sanity checks on MsgLength (byte) field
2368 * to make sure we don't zero IOC's req_sz!
2370 /* Did we get a valid reply? */
2371 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2372 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2374 * If not been here, done that, save off first WhoInit value
2376 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2377 ioc->FirstWhoInit = facts->WhoInit;
2380 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2381 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2382 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2383 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2384 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2385 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2386 /* CHECKME! IOCStatus, IOCLogInfo */
2388 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2389 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2392 * FC f/w version changed between 1.1 and 1.2
2393 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2394 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2396 if (facts->MsgVersion < 0x0102) {
2398 * Handle old FC f/w style, convert to new...
2400 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2401 facts->FWVersion.Word =
2402 ((oldv<<12) & 0xFF000000) |
2403 ((oldv<<8) & 0x000FFF00);
2404 } else
2405 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2407 facts->ProductID = le16_to_cpu(facts->ProductID);
2408 facts->CurrentHostMfaHighAddr =
2409 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2410 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2411 facts->CurrentSenseBufferHighAddr =
2412 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2413 facts->CurReplyFrameSize =
2414 le16_to_cpu(facts->CurReplyFrameSize);
2415 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2418 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2419 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2420 * to 14 in MPI-1.01.0x.
2422 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2423 facts->MsgVersion > 0x0100) {
2424 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2427 sz = facts->FWImageSize;
2428 if ( sz & 0x01 )
2429 sz += 1;
2430 if ( sz & 0x02 )
2431 sz += 2;
2432 facts->FWImageSize = sz;
2434 if (!facts->RequestFrameSize) {
2435 /* Something is wrong! */
2436 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2437 ioc->name);
2438 return -55;
2441 r = sz = facts->BlockSize;
2442 vv = ((63 / (sz * 4)) + 1) & 0x03;
2443 ioc->NB_for_64_byte_frame = vv;
2444 while ( sz )
2446 shiftFactor++;
2447 sz = sz >> 1;
2449 ioc->NBShiftFactor = shiftFactor;
2450 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2451 ioc->name, vv, shiftFactor, r));
2453 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2455 * Set values for this IOC's request & reply frame sizes,
2456 * and request & reply queue depths...
2458 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2459 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2460 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2461 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2463 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2464 ioc->name, ioc->reply_sz, ioc->reply_depth));
2465 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2466 ioc->name, ioc->req_sz, ioc->req_depth));
2468 /* Get port facts! */
2469 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2470 return r;
2472 } else {
2473 printk(MYIOC_s_ERR_FMT
2474 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2475 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2476 RequestFrameSize)/sizeof(u32)));
2477 return -66;
2480 return 0;
2483 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2485 * GetPortFacts - Send PortFacts request to MPT adapter.
2486 * @ioc: Pointer to MPT_ADAPTER structure
2487 * @portnum: Port number
2488 * @sleepFlag: Specifies whether the process can sleep
2490 * Returns 0 for success, non-zero for failure.
2492 static int
2493 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2495 PortFacts_t get_pfacts;
2496 PortFactsReply_t *pfacts;
2497 int ii;
2498 int req_sz;
2499 int reply_sz;
2501 /* IOC *must* NOT be in RESET state! */
2502 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2503 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2504 ioc->name,
2505 ioc->last_state );
2506 return -4;
2509 pfacts = &ioc->pfacts[portnum];
2511 /* Destination (reply area)... */
2512 reply_sz = sizeof(*pfacts);
2513 memset(pfacts, 0, reply_sz);
2515 /* Request area (get_pfacts on the stack right now!) */
2516 req_sz = sizeof(get_pfacts);
2517 memset(&get_pfacts, 0, req_sz);
2519 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2520 get_pfacts.PortNumber = portnum;
2521 /* Assert: All other get_pfacts fields are zero! */
2523 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2524 ioc->name, portnum));
2526 /* No non-zero fields in the get_pfacts request are greater than
2527 * 1 byte in size, so we can just fire it off as is.
2529 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2530 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2531 if (ii != 0)
2532 return ii;
2534 /* Did we get a valid reply? */
2536 /* Now byte swap the necessary fields in the response. */
2537 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2538 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2539 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2540 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2541 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2542 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2543 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2544 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2545 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2547 return 0;
2550 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2552 * SendIocInit - Send IOCInit request to MPT adapter.
2553 * @ioc: Pointer to MPT_ADAPTER structure
2554 * @sleepFlag: Specifies whether the process can sleep
2556 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2558 * Returns 0 for success, non-zero for failure.
2560 static int
2561 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2563 IOCInit_t ioc_init;
2564 MPIDefaultReply_t init_reply;
2565 u32 state;
2566 int r;
2567 int count;
2568 int cntdn;
2570 memset(&ioc_init, 0, sizeof(ioc_init));
2571 memset(&init_reply, 0, sizeof(init_reply));
2573 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2574 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2576 /* If we are in a recovery mode and we uploaded the FW image,
2577 * then this pointer is not NULL. Skip the upload a second time.
2578 * Set this flag if cached_fw set for either IOC.
2580 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2581 ioc->upload_fw = 1;
2582 else
2583 ioc->upload_fw = 0;
2584 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2585 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2587 if(ioc->bus_type == SAS)
2588 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2589 else if(ioc->bus_type == FC)
2590 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2591 else
2592 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2593 ioc_init.MaxBuses = MPT_MAX_BUS;
2594 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2595 ioc->name, ioc->facts.MsgVersion));
2596 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2597 // set MsgVersion and HeaderVersion host driver was built with
2598 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2599 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2601 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2602 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2603 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2604 return -99;
2606 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2608 if (sizeof(dma_addr_t) == sizeof(u64)) {
2609 /* Save the upper 32-bits of the request
2610 * (reply) and sense buffers.
2612 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2613 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2614 } else {
2615 /* Force 32-bit addressing */
2616 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2617 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2620 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2621 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2622 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2623 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2625 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2626 ioc->name, &ioc_init));
2628 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2629 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2630 if (r != 0) {
2631 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2632 return r;
2635 /* No need to byte swap the multibyte fields in the reply
2636 * since we don't even look at it's contents.
2639 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2640 ioc->name, &ioc_init));
2642 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2643 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2644 return r;
2647 /* YIKES! SUPER IMPORTANT!!!
2648 * Poll IocState until _OPERATIONAL while IOC is doing
2649 * LoopInit and TargetDiscovery!
2651 count = 0;
2652 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2653 state = mpt_GetIocState(ioc, 1);
2654 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2655 if (sleepFlag == CAN_SLEEP) {
2656 msleep(1);
2657 } else {
2658 mdelay(1);
2661 if (!cntdn) {
2662 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2663 ioc->name, (int)((count+5)/HZ));
2664 return -9;
2667 state = mpt_GetIocState(ioc, 1);
2668 count++;
2670 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2671 ioc->name, count));
2673 return r;
2676 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2678 * SendPortEnable - Send PortEnable request to MPT adapter port.
2679 * @ioc: Pointer to MPT_ADAPTER structure
2680 * @portnum: Port number to enable
2681 * @sleepFlag: Specifies whether the process can sleep
2683 * Send PortEnable to bring IOC to OPERATIONAL state.
2685 * Returns 0 for success, non-zero for failure.
2687 static int
2688 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2690 PortEnable_t port_enable;
2691 MPIDefaultReply_t reply_buf;
2692 int rc;
2693 int req_sz;
2694 int reply_sz;
2696 /* Destination... */
2697 reply_sz = sizeof(MPIDefaultReply_t);
2698 memset(&reply_buf, 0, reply_sz);
2700 req_sz = sizeof(PortEnable_t);
2701 memset(&port_enable, 0, req_sz);
2703 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2704 port_enable.PortNumber = portnum;
2705 /* port_enable.ChainOffset = 0; */
2706 /* port_enable.MsgFlags = 0; */
2707 /* port_enable.MsgContext = 0; */
2709 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2710 ioc->name, portnum, &port_enable));
2712 /* RAID FW may take a long time to enable
2714 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2715 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2716 (ioc->bus_type == SAS)) {
2717 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2718 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2719 300 /*seconds*/, sleepFlag);
2720 } else {
2721 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2722 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2723 30 /*seconds*/, sleepFlag);
2725 return rc;
2729 * ioc: Pointer to MPT_ADAPTER structure
2730 * size - total FW bytes
2732 void
2733 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2735 if (ioc->cached_fw)
2736 return; /* use already allocated memory */
2737 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2738 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2739 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2740 } else {
2741 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2742 ioc->alloc_total += size;
2746 * If alt_img is NULL, delete from ioc structure.
2747 * Else, delete a secondary image in same format.
2749 void
2750 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2752 int sz;
2754 sz = ioc->facts.FWImageSize;
2755 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2756 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2757 pci_free_consistent(ioc->pcidev, sz,
2758 ioc->cached_fw, ioc->cached_fw_dma);
2759 ioc->cached_fw = NULL;
2761 return;
2765 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2767 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2768 * @ioc: Pointer to MPT_ADAPTER structure
2769 * @sleepFlag: Specifies whether the process can sleep
2771 * Returns 0 for success, >0 for handshake failure
2772 * <0 for fw upload failure.
2774 * Remark: If bound IOC and a successful FWUpload was performed
2775 * on the bound IOC, the second image is discarded
2776 * and memory is free'd. Both channels must upload to prevent
2777 * IOC from running in degraded mode.
2779 static int
2780 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2782 u8 request[ioc->req_sz];
2783 u8 reply[sizeof(FWUploadReply_t)];
2784 FWUpload_t *prequest;
2785 FWUploadReply_t *preply;
2786 FWUploadTCSGE_t *ptcsge;
2787 int sgeoffset;
2788 u32 flagsLength;
2789 int ii, sz, reply_sz;
2790 int cmdStatus;
2792 /* If the image size is 0, we are done.
2794 if ((sz = ioc->facts.FWImageSize) == 0)
2795 return 0;
2797 mpt_alloc_fw_memory(ioc, sz);
2799 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2800 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2802 if (ioc->cached_fw == NULL) {
2803 /* Major Failure.
2805 return -ENOMEM;
2808 prequest = (FWUpload_t *)&request;
2809 preply = (FWUploadReply_t *)&reply;
2811 /* Destination... */
2812 memset(prequest, 0, ioc->req_sz);
2814 reply_sz = sizeof(reply);
2815 memset(preply, 0, reply_sz);
2817 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2818 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2820 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2821 ptcsge->DetailsLength = 12;
2822 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2823 ptcsge->ImageSize = cpu_to_le32(sz);
2825 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2827 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2828 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2830 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2831 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2832 prequest, sgeoffset));
2833 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2835 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2836 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2838 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2840 cmdStatus = -EFAULT;
2841 if (ii == 0) {
2842 /* Handshake transfer was complete and successful.
2843 * Check the Reply Frame.
2845 int status, transfer_sz;
2846 status = le16_to_cpu(preply->IOCStatus);
2847 if (status == MPI_IOCSTATUS_SUCCESS) {
2848 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2849 if (transfer_sz == sz)
2850 cmdStatus = 0;
2853 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2854 ioc->name, cmdStatus));
2857 if (cmdStatus) {
2859 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2860 ioc->name));
2861 mpt_free_fw_memory(ioc);
2864 return cmdStatus;
2867 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2869 * mpt_downloadboot - DownloadBoot code
2870 * @ioc: Pointer to MPT_ADAPTER structure
2871 * @flag: Specify which part of IOC memory is to be uploaded.
2872 * @sleepFlag: Specifies whether the process can sleep
2874 * FwDownloadBoot requires Programmed IO access.
2876 * Returns 0 for success
2877 * -1 FW Image size is 0
2878 * -2 No valid cached_fw Pointer
2879 * <0 for fw upload failure.
2881 static int
2882 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2884 MpiExtImageHeader_t *pExtImage;
2885 u32 fwSize;
2886 u32 diag0val;
2887 int count;
2888 u32 *ptrFw;
2889 u32 diagRwData;
2890 u32 nextImage;
2891 u32 load_addr;
2892 u32 ioc_state=0;
2894 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2895 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2897 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2898 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2899 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2900 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2901 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2902 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2904 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2906 /* wait 1 msec */
2907 if (sleepFlag == CAN_SLEEP) {
2908 msleep(1);
2909 } else {
2910 mdelay (1);
2913 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2914 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2916 for (count = 0; count < 30; count ++) {
2917 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2918 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2919 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2920 ioc->name, count));
2921 break;
2923 /* wait .1 sec */
2924 if (sleepFlag == CAN_SLEEP) {
2925 msleep (100);
2926 } else {
2927 mdelay (100);
2931 if ( count == 30 ) {
2932 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2933 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2934 ioc->name, diag0val));
2935 return -3;
2938 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2939 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2940 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2941 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2942 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2943 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2945 /* Set the DiagRwEn and Disable ARM bits */
2946 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2948 fwSize = (pFwHeader->ImageSize + 3)/4;
2949 ptrFw = (u32 *) pFwHeader;
2951 /* Write the LoadStartAddress to the DiagRw Address Register
2952 * using Programmed IO
2954 if (ioc->errata_flag_1064)
2955 pci_enable_io_access(ioc->pcidev);
2957 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2958 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2959 ioc->name, pFwHeader->LoadStartAddress));
2961 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2962 ioc->name, fwSize*4, ptrFw));
2963 while (fwSize--) {
2964 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2967 nextImage = pFwHeader->NextImageHeaderOffset;
2968 while (nextImage) {
2969 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2971 load_addr = pExtImage->LoadStartAddress;
2973 fwSize = (pExtImage->ImageSize + 3) >> 2;
2974 ptrFw = (u32 *)pExtImage;
2976 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
2977 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
2978 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
2980 while (fwSize--) {
2981 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2983 nextImage = pExtImage->NextImageHeaderOffset;
2986 /* Write the IopResetVectorRegAddr */
2987 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
2988 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
2990 /* Write the IopResetVectorValue */
2991 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
2992 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
2994 /* Clear the internal flash bad bit - autoincrementing register,
2995 * so must do two writes.
2997 if (ioc->bus_type == SPI) {
2999 * 1030 and 1035 H/W errata, workaround to access
3000 * the ClearFlashBadSignatureBit
3002 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3003 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3004 diagRwData |= 0x40000000;
3005 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3006 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3008 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3009 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3010 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3011 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3013 /* wait 1 msec */
3014 if (sleepFlag == CAN_SLEEP) {
3015 msleep (1);
3016 } else {
3017 mdelay (1);
3021 if (ioc->errata_flag_1064)
3022 pci_disable_io_access(ioc->pcidev);
3024 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3025 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3026 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3027 ioc->name, diag0val));
3028 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3029 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3030 ioc->name, diag0val));
3031 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3033 /* Write 0xFF to reset the sequencer */
3034 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3036 if (ioc->bus_type == SAS) {
3037 ioc_state = mpt_GetIocState(ioc, 0);
3038 if ( (GetIocFacts(ioc, sleepFlag,
3039 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3040 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3041 ioc->name, ioc_state));
3042 return -EFAULT;
3046 for (count=0; count<HZ*20; count++) {
3047 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3048 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3049 ioc->name, count, ioc_state));
3050 if (ioc->bus_type == SAS) {
3051 return 0;
3053 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3054 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3055 ioc->name));
3056 return -EFAULT;
3058 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3059 ioc->name));
3060 return 0;
3062 if (sleepFlag == CAN_SLEEP) {
3063 msleep (10);
3064 } else {
3065 mdelay (10);
3068 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3069 ioc->name, ioc_state));
3070 return -EFAULT;
3073 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3075 * KickStart - Perform hard reset of MPT adapter.
3076 * @ioc: Pointer to MPT_ADAPTER structure
3077 * @force: Force hard reset
3078 * @sleepFlag: Specifies whether the process can sleep
3080 * This routine places MPT adapter in diagnostic mode via the
3081 * WriteSequence register, and then performs a hard reset of adapter
3082 * via the Diagnostic register.
3084 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3085 * or NO_SLEEP (interrupt thread, use mdelay)
3086 * force - 1 if doorbell active, board fault state
3087 * board operational, IOC_RECOVERY or
3088 * IOC_BRINGUP and there is an alt_ioc.
3089 * 0 else
3091 * Returns:
3092 * 1 - hard reset, READY
3093 * 0 - no reset due to History bit, READY
3094 * -1 - no reset due to History bit but not READY
3095 * OR reset but failed to come READY
3096 * -2 - no reset, could not enter DIAG mode
3097 * -3 - reset but bad FW bit
3099 static int
3100 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3102 int hard_reset_done = 0;
3103 u32 ioc_state=0;
3104 int cnt,cntdn;
3106 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3107 if (ioc->bus_type == SPI) {
3108 /* Always issue a Msg Unit Reset first. This will clear some
3109 * SCSI bus hang conditions.
3111 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3113 if (sleepFlag == CAN_SLEEP) {
3114 msleep (1000);
3115 } else {
3116 mdelay (1000);
3120 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3121 if (hard_reset_done < 0)
3122 return hard_reset_done;
3124 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3125 ioc->name));
3127 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3128 for (cnt=0; cnt<cntdn; cnt++) {
3129 ioc_state = mpt_GetIocState(ioc, 1);
3130 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3131 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3132 ioc->name, cnt));
3133 return hard_reset_done;
3135 if (sleepFlag == CAN_SLEEP) {
3136 msleep (10);
3137 } else {
3138 mdelay (10);
3142 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3143 ioc->name, ioc_state);
3144 return -1;
3147 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3149 * mpt_diag_reset - Perform hard reset of the adapter.
3150 * @ioc: Pointer to MPT_ADAPTER structure
3151 * @ignore: Set if to honor and clear to ignore
3152 * the reset history bit
3153 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3154 * else set to NO_SLEEP (use mdelay instead)
3156 * This routine places the adapter in diagnostic mode via the
3157 * WriteSequence register and then performs a hard reset of adapter
3158 * via the Diagnostic register. Adapter should be in ready state
3159 * upon successful completion.
3161 * Returns: 1 hard reset successful
3162 * 0 no reset performed because reset history bit set
3163 * -2 enabling diagnostic mode failed
3164 * -3 diagnostic reset failed
3166 static int
3167 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3169 u32 diag0val;
3170 u32 doorbell;
3171 int hard_reset_done = 0;
3172 int count = 0;
3173 #ifdef MPT_DEBUG
3174 u32 diag1val = 0;
3175 #endif
3177 if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3178 drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3179 "address=%p\n", ioc->name, __FUNCTION__,
3180 &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3181 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3182 if (sleepFlag == CAN_SLEEP)
3183 msleep(1);
3184 else
3185 mdelay(1);
3187 for (count = 0; count < 60; count ++) {
3188 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3189 doorbell &= MPI_IOC_STATE_MASK;
3191 drsprintk((MYIOC_s_INFO_FMT
3192 "looking for READY STATE: doorbell=%x"
3193 " count=%d\n",
3194 ioc->name, doorbell, count));
3195 if (doorbell == MPI_IOC_STATE_READY) {
3196 return 0;
3199 /* wait 1 sec */
3200 if (sleepFlag == CAN_SLEEP)
3201 msleep(1000);
3202 else
3203 mdelay(1000);
3205 return -1;
3208 /* Clear any existing interrupts */
3209 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3211 /* Use "Diagnostic reset" method! (only thing available!) */
3212 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3214 #ifdef MPT_DEBUG
3215 if (ioc->alt_ioc)
3216 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3217 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3218 ioc->name, diag0val, diag1val));
3219 #endif
3221 /* Do the reset if we are told to ignore the reset history
3222 * or if the reset history is 0
3224 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3225 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3226 /* Write magic sequence to WriteSequence register
3227 * Loop until in diagnostic mode
3229 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3230 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3231 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3232 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3233 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3234 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3236 /* wait 100 msec */
3237 if (sleepFlag == CAN_SLEEP) {
3238 msleep (100);
3239 } else {
3240 mdelay (100);
3243 count++;
3244 if (count > 20) {
3245 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3246 ioc->name, diag0val);
3247 return -2;
3251 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3253 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3254 ioc->name, diag0val));
3257 #ifdef MPT_DEBUG
3258 if (ioc->alt_ioc)
3259 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3260 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3261 ioc->name, diag0val, diag1val));
3262 #endif
3264 * Disable the ARM (Bug fix)
3267 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3268 mdelay(1);
3271 * Now hit the reset bit in the Diagnostic register
3272 * (THE BIG HAMMER!) (Clears DRWE bit).
3274 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3275 hard_reset_done = 1;
3276 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3277 ioc->name));
3280 * Call each currently registered protocol IOC reset handler
3281 * with pre-reset indication.
3282 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3283 * MptResetHandlers[] registered yet.
3286 int ii;
3287 int r = 0;
3289 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3290 if (MptResetHandlers[ii]) {
3291 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3292 ioc->name, ii));
3293 r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
3294 if (ioc->alt_ioc) {
3295 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3296 ioc->name, ioc->alt_ioc->name, ii));
3297 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3301 /* FIXME? Examine results here? */
3304 if (ioc->cached_fw) {
3305 /* If the DownloadBoot operation fails, the
3306 * IOC will be left unusable. This is a fatal error
3307 * case. _diag_reset will return < 0
3309 for (count = 0; count < 30; count ++) {
3310 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3311 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3312 break;
3315 /* wait 1 sec */
3316 if (sleepFlag == CAN_SLEEP) {
3317 msleep (1000);
3318 } else {
3319 mdelay (1000);
3322 if ((count = mpt_downloadboot(ioc,
3323 (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
3324 printk(KERN_WARNING MYNAM
3325 ": firmware downloadboot failure (%d)!\n", count);
3328 } else {
3329 /* Wait for FW to reload and for board
3330 * to go to the READY state.
3331 * Maximum wait is 60 seconds.
3332 * If fail, no error will check again
3333 * with calling program.
3335 for (count = 0; count < 60; count ++) {
3336 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3337 doorbell &= MPI_IOC_STATE_MASK;
3339 if (doorbell == MPI_IOC_STATE_READY) {
3340 break;
3343 /* wait 1 sec */
3344 if (sleepFlag == CAN_SLEEP) {
3345 msleep (1000);
3346 } else {
3347 mdelay (1000);
3353 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3354 #ifdef MPT_DEBUG
3355 if (ioc->alt_ioc)
3356 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3357 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3358 ioc->name, diag0val, diag1val));
3359 #endif
3361 /* Clear RESET_HISTORY bit! Place board in the
3362 * diagnostic mode to update the diag register.
3364 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3365 count = 0;
3366 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3367 /* Write magic sequence to WriteSequence register
3368 * Loop until in diagnostic mode
3370 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3371 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3372 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3373 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3374 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3375 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3377 /* wait 100 msec */
3378 if (sleepFlag == CAN_SLEEP) {
3379 msleep (100);
3380 } else {
3381 mdelay (100);
3384 count++;
3385 if (count > 20) {
3386 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3387 ioc->name, diag0val);
3388 break;
3390 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3392 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3393 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3394 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3395 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3396 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3397 ioc->name);
3400 /* Disable Diagnostic Mode
3402 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3404 /* Check FW reload status flags.
3406 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3407 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3408 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3409 ioc->name, diag0val);
3410 return -3;
3413 #ifdef MPT_DEBUG
3414 if (ioc->alt_ioc)
3415 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3416 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3417 ioc->name, diag0val, diag1val));
3418 #endif
3421 * Reset flag that says we've enabled event notification
3423 ioc->facts.EventState = 0;
3425 if (ioc->alt_ioc)
3426 ioc->alt_ioc->facts.EventState = 0;
3428 return hard_reset_done;
3431 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3433 * SendIocReset - Send IOCReset request to MPT adapter.
3434 * @ioc: Pointer to MPT_ADAPTER structure
3435 * @reset_type: reset type, expected values are
3436 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3438 * Send IOCReset request to the MPT adapter.
3440 * Returns 0 for success, non-zero for failure.
3442 static int
3443 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3445 int r;
3446 u32 state;
3447 int cntdn, count;
3449 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3450 ioc->name, reset_type));
3451 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3452 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3453 return r;
3455 /* FW ACK'd request, wait for READY state
3457 count = 0;
3458 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3460 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3461 cntdn--;
3462 count++;
3463 if (!cntdn) {
3464 if (sleepFlag != CAN_SLEEP)
3465 count *= 10;
3467 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3468 ioc->name, (int)((count+5)/HZ));
3469 return -ETIME;
3472 if (sleepFlag == CAN_SLEEP) {
3473 msleep(1);
3474 } else {
3475 mdelay (1); /* 1 msec delay */
3479 /* TODO!
3480 * Cleanup all event stuff for this IOC; re-issue EventNotification
3481 * request if needed.
3483 if (ioc->facts.Function)
3484 ioc->facts.EventState = 0;
3486 return 0;
3489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3491 * initChainBuffers - Allocate memory for and initialize
3492 * chain buffers, chain buffer control arrays and spinlock.
3493 * @hd: Pointer to MPT_SCSI_HOST structure
3494 * @init: If set, initialize the spin lock.
3496 static int
3497 initChainBuffers(MPT_ADAPTER *ioc)
3499 u8 *mem;
3500 int sz, ii, num_chain;
3501 int scale, num_sge, numSGE;
3503 /* ReqToChain size must equal the req_depth
3504 * index = req_idx
3506 if (ioc->ReqToChain == NULL) {
3507 sz = ioc->req_depth * sizeof(int);
3508 mem = kmalloc(sz, GFP_ATOMIC);
3509 if (mem == NULL)
3510 return -1;
3512 ioc->ReqToChain = (int *) mem;
3513 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3514 ioc->name, mem, sz));
3515 mem = kmalloc(sz, GFP_ATOMIC);
3516 if (mem == NULL)
3517 return -1;
3519 ioc->RequestNB = (int *) mem;
3520 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3521 ioc->name, mem, sz));
3523 for (ii = 0; ii < ioc->req_depth; ii++) {
3524 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3527 /* ChainToChain size must equal the total number
3528 * of chain buffers to be allocated.
3529 * index = chain_idx
3531 * Calculate the number of chain buffers needed(plus 1) per I/O
3532 * then multiply the the maximum number of simultaneous cmds
3534 * num_sge = num sge in request frame + last chain buffer
3535 * scale = num sge per chain buffer if no chain element
3537 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3538 if (sizeof(dma_addr_t) == sizeof(u64))
3539 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3540 else
3541 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3543 if (sizeof(dma_addr_t) == sizeof(u64)) {
3544 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3545 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3546 } else {
3547 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3548 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3550 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3551 ioc->name, num_sge, numSGE));
3553 if ( numSGE > MPT_SCSI_SG_DEPTH )
3554 numSGE = MPT_SCSI_SG_DEPTH;
3556 num_chain = 1;
3557 while (numSGE - num_sge > 0) {
3558 num_chain++;
3559 num_sge += (scale - 1);
3561 num_chain++;
3563 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3564 ioc->name, numSGE, num_sge, num_chain));
3566 if (ioc->bus_type == SPI)
3567 num_chain *= MPT_SCSI_CAN_QUEUE;
3568 else
3569 num_chain *= MPT_FC_CAN_QUEUE;
3571 ioc->num_chain = num_chain;
3573 sz = num_chain * sizeof(int);
3574 if (ioc->ChainToChain == NULL) {
3575 mem = kmalloc(sz, GFP_ATOMIC);
3576 if (mem == NULL)
3577 return -1;
3579 ioc->ChainToChain = (int *) mem;
3580 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3581 ioc->name, mem, sz));
3582 } else {
3583 mem = (u8 *) ioc->ChainToChain;
3585 memset(mem, 0xFF, sz);
3586 return num_chain;
3589 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3591 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3592 * @ioc: Pointer to MPT_ADAPTER structure
3594 * This routine allocates memory for the MPT reply and request frame
3595 * pools (if necessary), and primes the IOC reply FIFO with
3596 * reply frames.
3598 * Returns 0 for success, non-zero for failure.
3600 static int
3601 PrimeIocFifos(MPT_ADAPTER *ioc)
3603 MPT_FRAME_HDR *mf;
3604 unsigned long flags;
3605 dma_addr_t alloc_dma;
3606 u8 *mem;
3607 int i, reply_sz, sz, total_size, num_chain;
3609 /* Prime reply FIFO... */
3611 if (ioc->reply_frames == NULL) {
3612 if ( (num_chain = initChainBuffers(ioc)) < 0)
3613 return -1;
3615 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3616 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3617 ioc->name, ioc->reply_sz, ioc->reply_depth));
3618 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3619 ioc->name, reply_sz, reply_sz));
3621 sz = (ioc->req_sz * ioc->req_depth);
3622 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3623 ioc->name, ioc->req_sz, ioc->req_depth));
3624 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3625 ioc->name, sz, sz));
3626 total_size += sz;
3628 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3629 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3630 ioc->name, ioc->req_sz, num_chain));
3631 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3632 ioc->name, sz, sz, num_chain));
3634 total_size += sz;
3635 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3636 if (mem == NULL) {
3637 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3638 ioc->name);
3639 goto out_fail;
3642 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3643 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3645 memset(mem, 0, total_size);
3646 ioc->alloc_total += total_size;
3647 ioc->alloc = mem;
3648 ioc->alloc_dma = alloc_dma;
3649 ioc->alloc_sz = total_size;
3650 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3651 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3653 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3654 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3656 alloc_dma += reply_sz;
3657 mem += reply_sz;
3659 /* Request FIFO - WE manage this! */
3661 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3662 ioc->req_frames_dma = alloc_dma;
3664 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3665 ioc->name, mem, (void *)(ulong)alloc_dma));
3667 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3669 #if defined(CONFIG_MTRR) && 0
3671 * Enable Write Combining MTRR for IOC's memory region.
3672 * (at least as much as we can; "size and base must be
3673 * multiples of 4 kiB"
3675 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3677 MTRR_TYPE_WRCOMB, 1);
3678 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3679 ioc->name, ioc->req_frames_dma, sz));
3680 #endif
3682 for (i = 0; i < ioc->req_depth; i++) {
3683 alloc_dma += ioc->req_sz;
3684 mem += ioc->req_sz;
3687 ioc->ChainBuffer = mem;
3688 ioc->ChainBufferDMA = alloc_dma;
3690 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3691 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3693 /* Initialize the free chain Q.
3696 INIT_LIST_HEAD(&ioc->FreeChainQ);
3698 /* Post the chain buffers to the FreeChainQ.
3700 mem = (u8 *)ioc->ChainBuffer;
3701 for (i=0; i < num_chain; i++) {
3702 mf = (MPT_FRAME_HDR *) mem;
3703 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3704 mem += ioc->req_sz;
3707 /* Initialize Request frames linked list
3709 alloc_dma = ioc->req_frames_dma;
3710 mem = (u8 *) ioc->req_frames;
3712 spin_lock_irqsave(&ioc->FreeQlock, flags);
3713 INIT_LIST_HEAD(&ioc->FreeQ);
3714 for (i = 0; i < ioc->req_depth; i++) {
3715 mf = (MPT_FRAME_HDR *) mem;
3717 /* Queue REQUESTs *internally*! */
3718 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3720 mem += ioc->req_sz;
3722 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3724 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3725 ioc->sense_buf_pool =
3726 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3727 if (ioc->sense_buf_pool == NULL) {
3728 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3729 ioc->name);
3730 goto out_fail;
3733 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3734 ioc->alloc_total += sz;
3735 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3736 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3740 /* Post Reply frames to FIFO
3742 alloc_dma = ioc->alloc_dma;
3743 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3744 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3746 for (i = 0; i < ioc->reply_depth; i++) {
3747 /* Write each address to the IOC! */
3748 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3749 alloc_dma += ioc->reply_sz;
3752 return 0;
3754 out_fail:
3755 if (ioc->alloc != NULL) {
3756 sz = ioc->alloc_sz;
3757 pci_free_consistent(ioc->pcidev,
3759 ioc->alloc, ioc->alloc_dma);
3760 ioc->reply_frames = NULL;
3761 ioc->req_frames = NULL;
3762 ioc->alloc_total -= sz;
3764 if (ioc->sense_buf_pool != NULL) {
3765 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3766 pci_free_consistent(ioc->pcidev,
3768 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3769 ioc->sense_buf_pool = NULL;
3771 return -1;
3774 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3776 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3777 * from IOC via doorbell handshake method.
3778 * @ioc: Pointer to MPT_ADAPTER structure
3779 * @reqBytes: Size of the request in bytes
3780 * @req: Pointer to MPT request frame
3781 * @replyBytes: Expected size of the reply in bytes
3782 * @u16reply: Pointer to area where reply should be written
3783 * @maxwait: Max wait time for a reply (in seconds)
3784 * @sleepFlag: Specifies whether the process can sleep
3786 * NOTES: It is the callers responsibility to byte-swap fields in the
3787 * request which are greater than 1 byte in size. It is also the
3788 * callers responsibility to byte-swap response fields which are
3789 * greater than 1 byte in size.
3791 * Returns 0 for success, non-zero for failure.
3793 static int
3794 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3795 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3797 MPIDefaultReply_t *mptReply;
3798 int failcnt = 0;
3799 int t;
3802 * Get ready to cache a handshake reply
3804 ioc->hs_reply_idx = 0;
3805 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3806 mptReply->MsgLength = 0;
3809 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3810 * then tell IOC that we want to handshake a request of N words.
3811 * (WRITE u32val to Doorbell reg).
3813 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3814 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3815 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3816 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3819 * Wait for IOC's doorbell handshake int
3821 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3822 failcnt++;
3824 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3825 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3827 /* Read doorbell and check for active bit */
3828 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3829 return -1;
3832 * Clear doorbell int (WRITE 0 to IntStatus reg),
3833 * then wait for IOC to ACKnowledge that it's ready for
3834 * our handshake request.
3836 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3837 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3838 failcnt++;
3840 if (!failcnt) {
3841 int ii;
3842 u8 *req_as_bytes = (u8 *) req;
3845 * Stuff request words via doorbell handshake,
3846 * with ACK from IOC for each.
3848 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3849 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3850 (req_as_bytes[(ii*4) + 1] << 8) |
3851 (req_as_bytes[(ii*4) + 2] << 16) |
3852 (req_as_bytes[(ii*4) + 3] << 24));
3854 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3855 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3856 failcnt++;
3859 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3860 DBG_DUMP_REQUEST_FRAME_HDR(req)
3862 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3863 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3866 * Wait for completion of doorbell handshake reply from the IOC
3868 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3869 failcnt++;
3871 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3872 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3875 * Copy out the cached reply...
3877 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3878 u16reply[ii] = ioc->hs_reply[ii];
3879 } else {
3880 return -99;
3883 return -failcnt;
3886 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3888 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3889 * in it's IntStatus register.
3890 * @ioc: Pointer to MPT_ADAPTER structure
3891 * @howlong: How long to wait (in seconds)
3892 * @sleepFlag: Specifies whether the process can sleep
3894 * This routine waits (up to ~2 seconds max) for IOC doorbell
3895 * handshake ACKnowledge.
3897 * Returns a negative value on failure, else wait loop count.
3899 static int
3900 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3902 int cntdn;
3903 int count = 0;
3904 u32 intstat=0;
3906 cntdn = 1000 * howlong;
3908 if (sleepFlag == CAN_SLEEP) {
3909 while (--cntdn) {
3910 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3911 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3912 break;
3913 msleep (1);
3914 count++;
3916 } else {
3917 while (--cntdn) {
3918 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3919 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3920 break;
3921 mdelay (1);
3922 count++;
3926 if (cntdn) {
3927 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3928 ioc->name, count));
3929 return count;
3932 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3933 ioc->name, count, intstat);
3934 return -1;
3937 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3939 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3940 * in it's IntStatus register.
3941 * @ioc: Pointer to MPT_ADAPTER structure
3942 * @howlong: How long to wait (in seconds)
3943 * @sleepFlag: Specifies whether the process can sleep
3945 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3947 * Returns a negative value on failure, else wait loop count.
3949 static int
3950 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3952 int cntdn;
3953 int count = 0;
3954 u32 intstat=0;
3956 cntdn = 1000 * howlong;
3957 if (sleepFlag == CAN_SLEEP) {
3958 while (--cntdn) {
3959 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3960 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3961 break;
3962 msleep(1);
3963 count++;
3965 } else {
3966 while (--cntdn) {
3967 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3968 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3969 break;
3970 mdelay(1);
3971 count++;
3975 if (cntdn) {
3976 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3977 ioc->name, count, howlong));
3978 return count;
3981 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3982 ioc->name, count, intstat);
3983 return -1;
3986 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3988 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3989 * @ioc: Pointer to MPT_ADAPTER structure
3990 * @howlong: How long to wait (in seconds)
3991 * @sleepFlag: Specifies whether the process can sleep
3993 * This routine polls the IOC for a handshake reply, 16 bits at a time.
3994 * Reply is cached to IOC private area large enough to hold a maximum
3995 * of 128 bytes of reply data.
3997 * Returns a negative value on failure, else size of reply in WORDS.
3999 static int
4000 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4002 int u16cnt = 0;
4003 int failcnt = 0;
4004 int t;
4005 u16 *hs_reply = ioc->hs_reply;
4006 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4007 u16 hword;
4009 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4012 * Get first two u16's so we can look at IOC's intended reply MsgLength
4014 u16cnt=0;
4015 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4016 failcnt++;
4017 } else {
4018 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4019 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4020 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4021 failcnt++;
4022 else {
4023 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4024 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4028 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4029 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4030 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4033 * If no error (and IOC said MsgLength is > 0), piece together
4034 * reply 16 bits at a time.
4036 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4037 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4038 failcnt++;
4039 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4040 /* don't overflow our IOC hs_reply[] buffer! */
4041 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4042 hs_reply[u16cnt] = hword;
4043 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4046 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4047 failcnt++;
4048 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4050 if (failcnt) {
4051 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4052 ioc->name);
4053 return -failcnt;
4055 #if 0
4056 else if (u16cnt != (2 * mptReply->MsgLength)) {
4057 return -101;
4059 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4060 return -102;
4062 #endif
4064 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4065 DBG_DUMP_REPLY_FRAME(mptReply)
4067 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4068 ioc->name, t, u16cnt/2));
4069 return u16cnt/2;
4072 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4074 * GetLanConfigPages - Fetch LANConfig pages.
4075 * @ioc: Pointer to MPT_ADAPTER structure
4077 * Return: 0 for success
4078 * -ENOMEM if no memory available
4079 * -EPERM if not allowed due to ISR context
4080 * -EAGAIN if no msg frames currently available
4081 * -EFAULT for non-successful reply or no reply (timeout)
4083 static int
4084 GetLanConfigPages(MPT_ADAPTER *ioc)
4086 ConfigPageHeader_t hdr;
4087 CONFIGPARMS cfg;
4088 LANPage0_t *ppage0_alloc;
4089 dma_addr_t page0_dma;
4090 LANPage1_t *ppage1_alloc;
4091 dma_addr_t page1_dma;
4092 int rc = 0;
4093 int data_sz;
4094 int copy_sz;
4096 /* Get LAN Page 0 header */
4097 hdr.PageVersion = 0;
4098 hdr.PageLength = 0;
4099 hdr.PageNumber = 0;
4100 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4101 cfg.cfghdr.hdr = &hdr;
4102 cfg.physAddr = -1;
4103 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4104 cfg.dir = 0;
4105 cfg.pageAddr = 0;
4106 cfg.timeout = 0;
4108 if ((rc = mpt_config(ioc, &cfg)) != 0)
4109 return rc;
4111 if (hdr.PageLength > 0) {
4112 data_sz = hdr.PageLength * 4;
4113 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4114 rc = -ENOMEM;
4115 if (ppage0_alloc) {
4116 memset((u8 *)ppage0_alloc, 0, data_sz);
4117 cfg.physAddr = page0_dma;
4118 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4120 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4121 /* save the data */
4122 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4123 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4127 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4129 /* FIXME!
4130 * Normalize endianness of structure data,
4131 * by byte-swapping all > 1 byte fields!
4136 if (rc)
4137 return rc;
4140 /* Get LAN Page 1 header */
4141 hdr.PageVersion = 0;
4142 hdr.PageLength = 0;
4143 hdr.PageNumber = 1;
4144 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4145 cfg.cfghdr.hdr = &hdr;
4146 cfg.physAddr = -1;
4147 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4148 cfg.dir = 0;
4149 cfg.pageAddr = 0;
4151 if ((rc = mpt_config(ioc, &cfg)) != 0)
4152 return rc;
4154 if (hdr.PageLength == 0)
4155 return 0;
4157 data_sz = hdr.PageLength * 4;
4158 rc = -ENOMEM;
4159 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4160 if (ppage1_alloc) {
4161 memset((u8 *)ppage1_alloc, 0, data_sz);
4162 cfg.physAddr = page1_dma;
4163 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4165 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4166 /* save the data */
4167 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4168 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4171 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4173 /* FIXME!
4174 * Normalize endianness of structure data,
4175 * by byte-swapping all > 1 byte fields!
4180 return rc;
4183 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4185 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4186 * @ioc: Pointer to MPT_ADAPTER structure
4187 * @sas_address: 64bit SAS Address for operation.
4188 * @target_id: specified target for operation
4189 * @bus: specified bus for operation
4190 * @persist_opcode: see below
4192 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4193 * devices not currently present.
4194 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4196 * NOTE: Don't use not this function during interrupt time.
4198 * Returns: 0 for success, non-zero error
4201 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4203 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4205 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4206 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4207 MPT_FRAME_HDR *mf = NULL;
4208 MPIHeader_t *mpi_hdr;
4211 /* insure garbage is not sent to fw */
4212 switch(persist_opcode) {
4214 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4215 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4216 break;
4218 default:
4219 return -1;
4220 break;
4223 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4225 /* Get a MF for this command.
4227 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4228 printk("%s: no msg frames!\n",__FUNCTION__);
4229 return -1;
4232 mpi_hdr = (MPIHeader_t *) mf;
4233 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4234 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4235 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4236 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4237 sasIoUnitCntrReq->Operation = persist_opcode;
4239 init_timer(&ioc->persist_timer);
4240 ioc->persist_timer.data = (unsigned long) ioc;
4241 ioc->persist_timer.function = mpt_timer_expired;
4242 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4243 ioc->persist_wait_done=0;
4244 add_timer(&ioc->persist_timer);
4245 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4246 wait_event(mpt_waitq, ioc->persist_wait_done);
4248 sasIoUnitCntrReply =
4249 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4250 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4251 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4252 __FUNCTION__,
4253 sasIoUnitCntrReply->IOCStatus,
4254 sasIoUnitCntrReply->IOCLogInfo);
4255 return -1;
4258 printk("%s: success\n",__FUNCTION__);
4259 return 0;
4262 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4264 static void
4265 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4266 MpiEventDataRaid_t * pRaidEventData)
4268 int volume;
4269 int reason;
4270 int disk;
4271 int status;
4272 int flags;
4273 int state;
4275 volume = pRaidEventData->VolumeID;
4276 reason = pRaidEventData->ReasonCode;
4277 disk = pRaidEventData->PhysDiskNum;
4278 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4279 flags = (status >> 0) & 0xff;
4280 state = (status >> 8) & 0xff;
4282 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4283 return;
4286 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4287 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4288 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4289 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4290 ioc->name, disk);
4291 } else {
4292 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4293 ioc->name, volume);
4296 switch(reason) {
4297 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4298 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4299 ioc->name);
4300 break;
4302 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4304 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4305 ioc->name);
4306 break;
4308 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4309 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4310 ioc->name);
4311 break;
4313 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4314 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4315 ioc->name,
4316 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4317 ? "optimal"
4318 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4319 ? "degraded"
4320 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4321 ? "failed"
4322 : "state unknown",
4323 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4324 ? ", enabled" : "",
4325 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4326 ? ", quiesced" : "",
4327 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4328 ? ", resync in progress" : "" );
4329 break;
4331 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4332 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4333 ioc->name, disk);
4334 break;
4336 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4337 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4338 ioc->name);
4339 break;
4341 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4342 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4343 ioc->name);
4344 break;
4346 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4347 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4348 ioc->name);
4349 break;
4351 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4352 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4353 ioc->name,
4354 state == MPI_PHYSDISK0_STATUS_ONLINE
4355 ? "online"
4356 : state == MPI_PHYSDISK0_STATUS_MISSING
4357 ? "missing"
4358 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4359 ? "not compatible"
4360 : state == MPI_PHYSDISK0_STATUS_FAILED
4361 ? "failed"
4362 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4363 ? "initializing"
4364 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4365 ? "offline requested"
4366 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4367 ? "failed requested"
4368 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4369 ? "offline"
4370 : "state unknown",
4371 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4372 ? ", out of sync" : "",
4373 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4374 ? ", quiesced" : "" );
4375 break;
4377 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4378 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4379 ioc->name, disk);
4380 break;
4382 case MPI_EVENT_RAID_RC_SMART_DATA:
4383 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4384 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4385 break;
4387 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4388 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4389 ioc->name, disk);
4390 break;
4394 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4396 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4397 * @ioc: Pointer to MPT_ADAPTER structure
4399 * Returns: 0 for success
4400 * -ENOMEM if no memory available
4401 * -EPERM if not allowed due to ISR context
4402 * -EAGAIN if no msg frames currently available
4403 * -EFAULT for non-successful reply or no reply (timeout)
4405 static int
4406 GetIoUnitPage2(MPT_ADAPTER *ioc)
4408 ConfigPageHeader_t hdr;
4409 CONFIGPARMS cfg;
4410 IOUnitPage2_t *ppage_alloc;
4411 dma_addr_t page_dma;
4412 int data_sz;
4413 int rc;
4415 /* Get the page header */
4416 hdr.PageVersion = 0;
4417 hdr.PageLength = 0;
4418 hdr.PageNumber = 2;
4419 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4420 cfg.cfghdr.hdr = &hdr;
4421 cfg.physAddr = -1;
4422 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4423 cfg.dir = 0;
4424 cfg.pageAddr = 0;
4425 cfg.timeout = 0;
4427 if ((rc = mpt_config(ioc, &cfg)) != 0)
4428 return rc;
4430 if (hdr.PageLength == 0)
4431 return 0;
4433 /* Read the config page */
4434 data_sz = hdr.PageLength * 4;
4435 rc = -ENOMEM;
4436 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4437 if (ppage_alloc) {
4438 memset((u8 *)ppage_alloc, 0, data_sz);
4439 cfg.physAddr = page_dma;
4440 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4442 /* If Good, save data */
4443 if ((rc = mpt_config(ioc, &cfg)) == 0)
4444 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4446 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4449 return rc;
4452 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4453 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4454 * @ioc: Pointer to a Adapter Strucutre
4455 * @portnum: IOC port number
4457 * Return: -EFAULT if read of config page header fails
4458 * or if no nvram
4459 * If read of SCSI Port Page 0 fails,
4460 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4461 * Adapter settings: async, narrow
4462 * Return 1
4463 * If read of SCSI Port Page 2 fails,
4464 * Adapter settings valid
4465 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4466 * Return 1
4467 * Else
4468 * Both valid
4469 * Return 0
4470 * CHECK - what type of locking mechanisms should be used????
4472 static int
4473 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4475 u8 *pbuf;
4476 dma_addr_t buf_dma;
4477 CONFIGPARMS cfg;
4478 ConfigPageHeader_t header;
4479 int ii;
4480 int data, rc = 0;
4482 /* Allocate memory
4484 if (!ioc->spi_data.nvram) {
4485 int sz;
4486 u8 *mem;
4487 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4488 mem = kmalloc(sz, GFP_ATOMIC);
4489 if (mem == NULL)
4490 return -EFAULT;
4492 ioc->spi_data.nvram = (int *) mem;
4494 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4495 ioc->name, ioc->spi_data.nvram, sz));
4498 /* Invalidate NVRAM information
4500 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4501 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4504 /* Read SPP0 header, allocate memory, then read page.
4506 header.PageVersion = 0;
4507 header.PageLength = 0;
4508 header.PageNumber = 0;
4509 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4510 cfg.cfghdr.hdr = &header;
4511 cfg.physAddr = -1;
4512 cfg.pageAddr = portnum;
4513 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4514 cfg.dir = 0;
4515 cfg.timeout = 0; /* use default */
4516 if (mpt_config(ioc, &cfg) != 0)
4517 return -EFAULT;
4519 if (header.PageLength > 0) {
4520 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4521 if (pbuf) {
4522 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4523 cfg.physAddr = buf_dma;
4524 if (mpt_config(ioc, &cfg) != 0) {
4525 ioc->spi_data.maxBusWidth = MPT_NARROW;
4526 ioc->spi_data.maxSyncOffset = 0;
4527 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4528 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4529 rc = 1;
4530 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4531 ioc->name, ioc->spi_data.minSyncFactor));
4532 } else {
4533 /* Save the Port Page 0 data
4535 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4536 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4537 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4539 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4540 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4541 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4542 ioc->name, pPP0->Capabilities));
4544 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4545 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4546 if (data) {
4547 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4548 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4549 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4550 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4551 ioc->name, ioc->spi_data.minSyncFactor));
4552 } else {
4553 ioc->spi_data.maxSyncOffset = 0;
4554 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4557 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4559 /* Update the minSyncFactor based on bus type.
4561 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4562 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4564 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4565 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4566 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4567 ioc->name, ioc->spi_data.minSyncFactor));
4571 if (pbuf) {
4572 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4577 /* SCSI Port Page 2 - Read the header then the page.
4579 header.PageVersion = 0;
4580 header.PageLength = 0;
4581 header.PageNumber = 2;
4582 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4583 cfg.cfghdr.hdr = &header;
4584 cfg.physAddr = -1;
4585 cfg.pageAddr = portnum;
4586 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4587 cfg.dir = 0;
4588 if (mpt_config(ioc, &cfg) != 0)
4589 return -EFAULT;
4591 if (header.PageLength > 0) {
4592 /* Allocate memory and read SCSI Port Page 2
4594 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4595 if (pbuf) {
4596 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4597 cfg.physAddr = buf_dma;
4598 if (mpt_config(ioc, &cfg) != 0) {
4599 /* Nvram data is left with INVALID mark
4601 rc = 1;
4602 } else {
4603 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4604 MpiDeviceInfo_t *pdevice = NULL;
4607 * Save "Set to Avoid SCSI Bus Resets" flag
4609 ioc->spi_data.bus_reset =
4610 (le32_to_cpu(pPP2->PortFlags) &
4611 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4612 0 : 1 ;
4614 /* Save the Port Page 2 data
4615 * (reformat into a 32bit quantity)
4617 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4618 ioc->spi_data.PortFlags = data;
4619 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4620 pdevice = &pPP2->DeviceSettings[ii];
4621 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4622 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4623 ioc->spi_data.nvram[ii] = data;
4627 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4631 /* Update Adapter limits with those from NVRAM
4632 * Comment: Don't need to do this. Target performance
4633 * parameters will never exceed the adapters limits.
4636 return rc;
4639 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4640 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4641 * @ioc: Pointer to a Adapter Strucutre
4642 * @portnum: IOC port number
4644 * Return: -EFAULT if read of config page header fails
4645 * or 0 if success.
4647 static int
4648 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4650 CONFIGPARMS cfg;
4651 ConfigPageHeader_t header;
4653 /* Read the SCSI Device Page 1 header
4655 header.PageVersion = 0;
4656 header.PageLength = 0;
4657 header.PageNumber = 1;
4658 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4659 cfg.cfghdr.hdr = &header;
4660 cfg.physAddr = -1;
4661 cfg.pageAddr = portnum;
4662 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4663 cfg.dir = 0;
4664 cfg.timeout = 0;
4665 if (mpt_config(ioc, &cfg) != 0)
4666 return -EFAULT;
4668 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4669 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4671 header.PageVersion = 0;
4672 header.PageLength = 0;
4673 header.PageNumber = 0;
4674 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4675 if (mpt_config(ioc, &cfg) != 0)
4676 return -EFAULT;
4678 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4679 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4681 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4682 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4684 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4685 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4686 return 0;
4689 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4691 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4692 * @ioc: Pointer to a Adapter Strucutre
4693 * @portnum: IOC port number
4695 * Return:
4696 * 0 on success
4697 * -EFAULT if read of config page header fails or data pointer not NULL
4698 * -ENOMEM if pci_alloc failed
4701 mpt_findImVolumes(MPT_ADAPTER *ioc)
4703 IOCPage2_t *pIoc2;
4704 u8 *mem;
4705 ConfigPageIoc2RaidVol_t *pIocRv;
4706 dma_addr_t ioc2_dma;
4707 CONFIGPARMS cfg;
4708 ConfigPageHeader_t header;
4709 int jj;
4710 int rc = 0;
4711 int iocpage2sz;
4712 u8 nVols, nPhys;
4713 u8 vid, vbus, vioc;
4715 /* Read IOCP2 header then the page.
4717 header.PageVersion = 0;
4718 header.PageLength = 0;
4719 header.PageNumber = 2;
4720 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4721 cfg.cfghdr.hdr = &header;
4722 cfg.physAddr = -1;
4723 cfg.pageAddr = 0;
4724 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4725 cfg.dir = 0;
4726 cfg.timeout = 0;
4727 if (mpt_config(ioc, &cfg) != 0)
4728 return -EFAULT;
4730 if (header.PageLength == 0)
4731 return -EFAULT;
4733 iocpage2sz = header.PageLength * 4;
4734 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4735 if (!pIoc2)
4736 return -ENOMEM;
4738 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4739 cfg.physAddr = ioc2_dma;
4740 if (mpt_config(ioc, &cfg) != 0)
4741 goto done_and_free;
4743 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4744 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4745 if (mem) {
4746 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4747 } else {
4748 goto done_and_free;
4751 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4753 /* Identify RAID Volume Id's */
4754 nVols = pIoc2->NumActiveVolumes;
4755 if ( nVols == 0) {
4756 /* No RAID Volume.
4758 goto done_and_free;
4759 } else {
4760 /* At least 1 RAID Volume
4762 pIocRv = pIoc2->RaidVolume;
4763 ioc->raid_data.isRaid = 0;
4764 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4765 vid = pIocRv->VolumeID;
4766 vbus = pIocRv->VolumeBus;
4767 vioc = pIocRv->VolumeIOC;
4769 /* find the match
4771 if (vbus == 0) {
4772 ioc->raid_data.isRaid |= (1 << vid);
4773 } else {
4774 /* Error! Always bus 0
4780 /* Identify Hidden Physical Disk Id's */
4781 nPhys = pIoc2->NumActivePhysDisks;
4782 if (nPhys == 0) {
4783 /* No physical disks.
4785 } else {
4786 mpt_read_ioc_pg_3(ioc);
4789 done_and_free:
4790 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4792 return rc;
4795 static int
4796 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4798 IOCPage3_t *pIoc3;
4799 u8 *mem;
4800 CONFIGPARMS cfg;
4801 ConfigPageHeader_t header;
4802 dma_addr_t ioc3_dma;
4803 int iocpage3sz = 0;
4805 /* Free the old page
4807 kfree(ioc->raid_data.pIocPg3);
4808 ioc->raid_data.pIocPg3 = NULL;
4810 /* There is at least one physical disk.
4811 * Read and save IOC Page 3
4813 header.PageVersion = 0;
4814 header.PageLength = 0;
4815 header.PageNumber = 3;
4816 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4817 cfg.cfghdr.hdr = &header;
4818 cfg.physAddr = -1;
4819 cfg.pageAddr = 0;
4820 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4821 cfg.dir = 0;
4822 cfg.timeout = 0;
4823 if (mpt_config(ioc, &cfg) != 0)
4824 return 0;
4826 if (header.PageLength == 0)
4827 return 0;
4829 /* Read Header good, alloc memory
4831 iocpage3sz = header.PageLength * 4;
4832 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4833 if (!pIoc3)
4834 return 0;
4836 /* Read the Page and save the data
4837 * into malloc'd memory.
4839 cfg.physAddr = ioc3_dma;
4840 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4841 if (mpt_config(ioc, &cfg) == 0) {
4842 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4843 if (mem) {
4844 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4845 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4849 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4851 return 0;
4854 static void
4855 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4857 IOCPage4_t *pIoc4;
4858 CONFIGPARMS cfg;
4859 ConfigPageHeader_t header;
4860 dma_addr_t ioc4_dma;
4861 int iocpage4sz;
4863 /* Read and save IOC Page 4
4865 header.PageVersion = 0;
4866 header.PageLength = 0;
4867 header.PageNumber = 4;
4868 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4869 cfg.cfghdr.hdr = &header;
4870 cfg.physAddr = -1;
4871 cfg.pageAddr = 0;
4872 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4873 cfg.dir = 0;
4874 cfg.timeout = 0;
4875 if (mpt_config(ioc, &cfg) != 0)
4876 return;
4878 if (header.PageLength == 0)
4879 return;
4881 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4882 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4883 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4884 if (!pIoc4)
4885 return;
4886 } else {
4887 ioc4_dma = ioc->spi_data.IocPg4_dma;
4888 iocpage4sz = ioc->spi_data.IocPg4Sz;
4891 /* Read the Page into dma memory.
4893 cfg.physAddr = ioc4_dma;
4894 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4895 if (mpt_config(ioc, &cfg) == 0) {
4896 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4897 ioc->spi_data.IocPg4_dma = ioc4_dma;
4898 ioc->spi_data.IocPg4Sz = iocpage4sz;
4899 } else {
4900 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4901 ioc->spi_data.pIocPg4 = NULL;
4905 static void
4906 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4908 IOCPage1_t *pIoc1;
4909 CONFIGPARMS cfg;
4910 ConfigPageHeader_t header;
4911 dma_addr_t ioc1_dma;
4912 int iocpage1sz = 0;
4913 u32 tmp;
4915 /* Check the Coalescing Timeout in IOC Page 1
4917 header.PageVersion = 0;
4918 header.PageLength = 0;
4919 header.PageNumber = 1;
4920 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4921 cfg.cfghdr.hdr = &header;
4922 cfg.physAddr = -1;
4923 cfg.pageAddr = 0;
4924 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4925 cfg.dir = 0;
4926 cfg.timeout = 0;
4927 if (mpt_config(ioc, &cfg) != 0)
4928 return;
4930 if (header.PageLength == 0)
4931 return;
4933 /* Read Header good, alloc memory
4935 iocpage1sz = header.PageLength * 4;
4936 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4937 if (!pIoc1)
4938 return;
4940 /* Read the Page and check coalescing timeout
4942 cfg.physAddr = ioc1_dma;
4943 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4944 if (mpt_config(ioc, &cfg) == 0) {
4946 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4947 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4948 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4950 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4951 ioc->name, tmp));
4953 if (tmp > MPT_COALESCING_TIMEOUT) {
4954 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4956 /* Write NVRAM and current
4958 cfg.dir = 1;
4959 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4960 if (mpt_config(ioc, &cfg) == 0) {
4961 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4962 ioc->name, MPT_COALESCING_TIMEOUT));
4964 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4965 if (mpt_config(ioc, &cfg) == 0) {
4966 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4967 ioc->name, MPT_COALESCING_TIMEOUT));
4968 } else {
4969 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4970 ioc->name));
4973 } else {
4974 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4975 ioc->name));
4979 } else {
4980 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4984 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4986 return;
4989 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4991 * SendEventNotification - Send EventNotification (on or off) request
4992 * to MPT adapter.
4993 * @ioc: Pointer to MPT_ADAPTER structure
4994 * @EvSwitch: Event switch flags
4996 static int
4997 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4999 EventNotification_t *evnp;
5001 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5002 if (evnp == NULL) {
5003 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5004 ioc->name));
5005 return 0;
5007 memset(evnp, 0, sizeof(*evnp));
5009 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5011 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5012 evnp->ChainOffset = 0;
5013 evnp->MsgFlags = 0;
5014 evnp->Switch = EvSwitch;
5016 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5018 return 0;
5021 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5023 * SendEventAck - Send EventAck request to MPT adapter.
5024 * @ioc: Pointer to MPT_ADAPTER structure
5025 * @evnp: Pointer to original EventNotification request
5027 static int
5028 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5030 EventAck_t *pAck;
5032 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5033 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
5034 "request frame for Event=%x EventContext=%x EventData=%x!\n",
5035 ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
5036 le32_to_cpu(evnp->Data[0]));
5037 return -1;
5039 memset(pAck, 0, sizeof(*pAck));
5041 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5043 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5044 pAck->ChainOffset = 0;
5045 pAck->MsgFlags = 0;
5046 pAck->Event = evnp->Event;
5047 pAck->EventContext = evnp->EventContext;
5049 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5051 return 0;
5054 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5056 * mpt_config - Generic function to issue config message
5057 * @ioc - Pointer to an adapter structure
5058 * @cfg - Pointer to a configuration structure. Struct contains
5059 * action, page address, direction, physical address
5060 * and pointer to a configuration page header
5061 * Page header is updated.
5063 * Returns 0 for success
5064 * -EPERM if not allowed due to ISR context
5065 * -EAGAIN if no msg frames currently available
5066 * -EFAULT for non-successful reply or no reply (timeout)
5069 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5071 Config_t *pReq;
5072 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5073 MPT_FRAME_HDR *mf;
5074 unsigned long flags;
5075 int ii, rc;
5076 int flagsLength;
5077 int in_isr;
5079 /* Prevent calling wait_event() (below), if caller happens
5080 * to be in ISR context, because that is fatal!
5082 in_isr = in_interrupt();
5083 if (in_isr) {
5084 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5085 ioc->name));
5086 return -EPERM;
5089 /* Get and Populate a free Frame
5091 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5092 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5093 ioc->name));
5094 return -EAGAIN;
5096 pReq = (Config_t *)mf;
5097 pReq->Action = pCfg->action;
5098 pReq->Reserved = 0;
5099 pReq->ChainOffset = 0;
5100 pReq->Function = MPI_FUNCTION_CONFIG;
5102 /* Assume page type is not extended and clear "reserved" fields. */
5103 pReq->ExtPageLength = 0;
5104 pReq->ExtPageType = 0;
5105 pReq->MsgFlags = 0;
5107 for (ii=0; ii < 8; ii++)
5108 pReq->Reserved2[ii] = 0;
5110 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5111 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5112 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5113 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5115 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5116 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5117 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5118 pReq->ExtPageType = pExtHdr->ExtPageType;
5119 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5121 /* Page Length must be treated as a reserved field for the extended header. */
5122 pReq->Header.PageLength = 0;
5125 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5127 /* Add a SGE to the config request.
5129 if (pCfg->dir)
5130 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5131 else
5132 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5134 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5135 flagsLength |= pExtHdr->ExtPageLength * 4;
5137 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5138 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5140 else {
5141 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5143 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5144 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5147 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5149 /* Append pCfg pointer to end of mf
5151 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5153 /* Initalize the timer
5155 init_timer(&pCfg->timer);
5156 pCfg->timer.data = (unsigned long) ioc;
5157 pCfg->timer.function = mpt_timer_expired;
5158 pCfg->wait_done = 0;
5160 /* Set the timer; ensure 10 second minimum */
5161 if (pCfg->timeout < 10)
5162 pCfg->timer.expires = jiffies + HZ*10;
5163 else
5164 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5166 /* Add to end of Q, set timer and then issue this command */
5167 spin_lock_irqsave(&ioc->FreeQlock, flags);
5168 list_add_tail(&pCfg->linkage, &ioc->configQ);
5169 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5171 add_timer(&pCfg->timer);
5172 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5173 wait_event(mpt_waitq, pCfg->wait_done);
5175 /* mf has been freed - do not access */
5177 rc = pCfg->status;
5179 return rc;
5182 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5184 * mpt_timer_expired - Call back for timer process.
5185 * Used only internal config functionality.
5186 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5188 static void
5189 mpt_timer_expired(unsigned long data)
5191 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5193 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5195 /* Perform a FW reload */
5196 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5197 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5199 /* No more processing.
5200 * Hard reset clean-up will wake up
5201 * process and free all resources.
5203 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5205 return;
5208 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5210 * mpt_ioc_reset - Base cleanup for hard reset
5211 * @ioc: Pointer to the adapter structure
5212 * @reset_phase: Indicates pre- or post-reset functionality
5214 * Remark: Free's resources with internally generated commands.
5216 static int
5217 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5219 CONFIGPARMS *pCfg;
5220 unsigned long flags;
5222 dprintk((KERN_WARNING MYNAM
5223 ": IOC %s_reset routed to MPT base driver!\n",
5224 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5225 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5227 if (reset_phase == MPT_IOC_SETUP_RESET) {
5229 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5230 /* If the internal config Q is not empty -
5231 * delete timer. MF resources will be freed when
5232 * the FIFO's are primed.
5234 spin_lock_irqsave(&ioc->FreeQlock, flags);
5235 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5236 del_timer(&pCfg->timer);
5237 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5239 } else {
5240 CONFIGPARMS *pNext;
5242 /* Search the configQ for internal commands.
5243 * Flush the Q, and wake up all suspended threads.
5245 spin_lock_irqsave(&ioc->FreeQlock, flags);
5246 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5247 list_del(&pCfg->linkage);
5249 pCfg->status = MPT_CONFIG_ERROR;
5250 pCfg->wait_done = 1;
5251 wake_up(&mpt_waitq);
5253 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5256 return 1; /* currently means nothing really */
5260 #ifdef CONFIG_PROC_FS /* { */
5261 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5263 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5265 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5267 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5269 * Returns 0 for success, non-zero for failure.
5271 static int
5272 procmpt_create(void)
5274 struct proc_dir_entry *ent;
5276 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5277 if (mpt_proc_root_dir == NULL)
5278 return -ENOTDIR;
5280 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5281 if (ent)
5282 ent->read_proc = procmpt_summary_read;
5284 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5285 if (ent)
5286 ent->read_proc = procmpt_version_read;
5288 return 0;
5291 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5293 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5295 * Returns 0 for success, non-zero for failure.
5297 static void
5298 procmpt_destroy(void)
5300 remove_proc_entry("version", mpt_proc_root_dir);
5301 remove_proc_entry("summary", mpt_proc_root_dir);
5302 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5305 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5307 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5308 * or from /proc/mpt/iocN/summary.
5309 * @buf: Pointer to area to write information
5310 * @start: Pointer to start pointer
5311 * @offset: Offset to start writing
5312 * @request:
5313 * @eof: Pointer to EOF integer
5314 * @data: Pointer
5316 * Returns number of characters written to process performing the read.
5318 static int
5319 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5321 MPT_ADAPTER *ioc;
5322 char *out = buf;
5323 int len;
5325 if (data) {
5326 int more = 0;
5328 ioc = data;
5329 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5331 out += more;
5332 } else {
5333 list_for_each_entry(ioc, &ioc_list, list) {
5334 int more = 0;
5336 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5338 out += more;
5339 if ((out-buf) >= request)
5340 break;
5344 len = out - buf;
5346 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5349 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5351 * procmpt_version_read - Handle read request from /proc/mpt/version.
5352 * @buf: Pointer to area to write information
5353 * @start: Pointer to start pointer
5354 * @offset: Offset to start writing
5355 * @request:
5356 * @eof: Pointer to EOF integer
5357 * @data: Pointer
5359 * Returns number of characters written to process performing the read.
5361 static int
5362 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5364 int ii;
5365 int scsi, fc, sas, lan, ctl, targ, dmp;
5366 char *drvname;
5367 int len;
5369 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5370 len += sprintf(buf+len, " Fusion MPT base driver\n");
5372 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5373 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5374 drvname = NULL;
5375 if (MptCallbacks[ii]) {
5376 switch (MptDriverClass[ii]) {
5377 case MPTSPI_DRIVER:
5378 if (!scsi++) drvname = "SPI host";
5379 break;
5380 case MPTFC_DRIVER:
5381 if (!fc++) drvname = "FC host";
5382 break;
5383 case MPTSAS_DRIVER:
5384 if (!sas++) drvname = "SAS host";
5385 break;
5386 case MPTLAN_DRIVER:
5387 if (!lan++) drvname = "LAN";
5388 break;
5389 case MPTSTM_DRIVER:
5390 if (!targ++) drvname = "SCSI target";
5391 break;
5392 case MPTCTL_DRIVER:
5393 if (!ctl++) drvname = "ioctl";
5394 break;
5397 if (drvname)
5398 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5402 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5405 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5407 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5408 * @buf: Pointer to area to write information
5409 * @start: Pointer to start pointer
5410 * @offset: Offset to start writing
5411 * @request:
5412 * @eof: Pointer to EOF integer
5413 * @data: Pointer
5415 * Returns number of characters written to process performing the read.
5417 static int
5418 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5420 MPT_ADAPTER *ioc = data;
5421 int len;
5422 char expVer[32];
5423 int sz;
5424 int p;
5426 mpt_get_fw_exp_ver(expVer, ioc);
5428 len = sprintf(buf, "%s:", ioc->name);
5429 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5430 len += sprintf(buf+len, " (f/w download boot flag set)");
5431 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5432 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5434 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5435 ioc->facts.ProductID,
5436 ioc->prod_name);
5437 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5438 if (ioc->facts.FWImageSize)
5439 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5440 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5441 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5442 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5444 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5445 ioc->facts.CurrentHostMfaHighAddr);
5446 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5447 ioc->facts.CurrentSenseBufferHighAddr);
5449 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5450 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5452 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5453 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5455 * Rounding UP to nearest 4-kB boundary here...
5457 sz = (ioc->req_sz * ioc->req_depth) + 128;
5458 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5459 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5460 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5461 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5462 4*ioc->facts.RequestFrameSize,
5463 ioc->facts.GlobalCredits);
5465 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5466 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5467 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5468 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5469 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5470 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5471 ioc->facts.CurReplyFrameSize,
5472 ioc->facts.ReplyQueueDepth);
5474 len += sprintf(buf+len, " MaxDevices = %d\n",
5475 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5476 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5478 /* per-port info */
5479 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5480 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5481 p+1,
5482 ioc->facts.NumberOfPorts);
5483 if (ioc->bus_type == FC) {
5484 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5485 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5486 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5487 a[5], a[4], a[3], a[2], a[1], a[0]);
5489 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5490 ioc->fc_port_page0[p].WWNN.High,
5491 ioc->fc_port_page0[p].WWNN.Low,
5492 ioc->fc_port_page0[p].WWPN.High,
5493 ioc->fc_port_page0[p].WWPN.Low);
5497 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5500 #endif /* CONFIG_PROC_FS } */
5502 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5503 static void
5504 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5506 buf[0] ='\0';
5507 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5508 sprintf(buf, " (Exp %02d%02d)",
5509 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5510 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5512 /* insider hack! */
5513 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5514 strcat(buf, " [MDBG]");
5518 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5520 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5521 * @ioc: Pointer to MPT_ADAPTER structure
5522 * @buffer: Pointer to buffer where IOC summary info should be written
5523 * @size: Pointer to number of bytes we wrote (set by this routine)
5524 * @len: Offset at which to start writing in buffer
5525 * @showlan: Display LAN stuff?
5527 * This routine writes (english readable) ASCII text, which represents
5528 * a summary of IOC information, to a buffer.
5530 void
5531 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5533 char expVer[32];
5534 int y;
5536 mpt_get_fw_exp_ver(expVer, ioc);
5539 * Shorter summary of attached ioc's...
5541 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5542 ioc->name,
5543 ioc->prod_name,
5544 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5545 ioc->facts.FWVersion.Word,
5546 expVer,
5547 ioc->facts.NumberOfPorts,
5548 ioc->req_depth);
5550 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5551 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5552 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5553 a[5], a[4], a[3], a[2], a[1], a[0]);
5556 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5558 if (!ioc->active)
5559 y += sprintf(buffer+len+y, " (disabled)");
5561 y += sprintf(buffer+len+y, "\n");
5563 *size = y;
5566 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5568 * Reset Handling
5570 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5572 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5573 * Management call based on input arg values. If TaskMgmt fails,
5574 * return associated SCSI request.
5575 * @ioc: Pointer to MPT_ADAPTER structure
5576 * @sleepFlag: Indicates if sleep or schedule must be called.
5578 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5579 * or a non-interrupt thread. In the former, must not call schedule().
5581 * Remark: A return of -1 is a FATAL error case, as it means a
5582 * FW reload/initialization failed.
5584 * Returns 0 for SUCCESS or -1 if FAILED.
5587 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5589 int rc;
5590 unsigned long flags;
5592 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5593 #ifdef MFCNT
5594 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5595 printk("MF count 0x%x !\n", ioc->mfcnt);
5596 #endif
5598 /* Reset the adapter. Prevent more than 1 call to
5599 * mpt_do_ioc_recovery at any instant in time.
5601 spin_lock_irqsave(&ioc->diagLock, flags);
5602 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5603 spin_unlock_irqrestore(&ioc->diagLock, flags);
5604 return 0;
5605 } else {
5606 ioc->diagPending = 1;
5608 spin_unlock_irqrestore(&ioc->diagLock, flags);
5610 /* FIXME: If do_ioc_recovery fails, repeat....
5613 /* The SCSI driver needs to adjust timeouts on all current
5614 * commands prior to the diagnostic reset being issued.
5615 * Prevents timeouts occurring during a diagnostic reset...very bad.
5616 * For all other protocol drivers, this is a no-op.
5619 int ii;
5620 int r = 0;
5622 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5623 if (MptResetHandlers[ii]) {
5624 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5625 ioc->name, ii));
5626 r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
5627 if (ioc->alt_ioc) {
5628 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5629 ioc->name, ioc->alt_ioc->name, ii));
5630 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5636 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5637 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5638 rc, ioc->name);
5640 ioc->reload_fw = 0;
5641 if (ioc->alt_ioc)
5642 ioc->alt_ioc->reload_fw = 0;
5644 spin_lock_irqsave(&ioc->diagLock, flags);
5645 ioc->diagPending = 0;
5646 if (ioc->alt_ioc)
5647 ioc->alt_ioc->diagPending = 0;
5648 spin_unlock_irqrestore(&ioc->diagLock, flags);
5650 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5652 return rc;
5655 # define EVENT_DESCR_STR_SZ 100
5657 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5658 static void
5659 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5661 char *ds = NULL;
5663 switch(event) {
5664 case MPI_EVENT_NONE:
5665 ds = "None";
5666 break;
5667 case MPI_EVENT_LOG_DATA:
5668 ds = "Log Data";
5669 break;
5670 case MPI_EVENT_STATE_CHANGE:
5671 ds = "State Change";
5672 break;
5673 case MPI_EVENT_UNIT_ATTENTION:
5674 ds = "Unit Attention";
5675 break;
5676 case MPI_EVENT_IOC_BUS_RESET:
5677 ds = "IOC Bus Reset";
5678 break;
5679 case MPI_EVENT_EXT_BUS_RESET:
5680 ds = "External Bus Reset";
5681 break;
5682 case MPI_EVENT_RESCAN:
5683 ds = "Bus Rescan Event";
5684 /* Ok, do we need to do anything here? As far as
5685 I can tell, this is when a new device gets added
5686 to the loop. */
5687 break;
5688 case MPI_EVENT_LINK_STATUS_CHANGE:
5689 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5690 ds = "Link Status(FAILURE) Change";
5691 else
5692 ds = "Link Status(ACTIVE) Change";
5693 break;
5694 case MPI_EVENT_LOOP_STATE_CHANGE:
5695 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5696 ds = "Loop State(LIP) Change";
5697 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5698 ds = "Loop State(LPE) Change"; /* ??? */
5699 else
5700 ds = "Loop State(LPB) Change"; /* ??? */
5701 break;
5702 case MPI_EVENT_LOGOUT:
5703 ds = "Logout";
5704 break;
5705 case MPI_EVENT_EVENT_CHANGE:
5706 if (evData0)
5707 ds = "Events(ON) Change";
5708 else
5709 ds = "Events(OFF) Change";
5710 break;
5711 case MPI_EVENT_INTEGRATED_RAID:
5713 u8 ReasonCode = (u8)(evData0 >> 16);
5714 switch (ReasonCode) {
5715 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5716 ds = "Integrated Raid: Volume Created";
5717 break;
5718 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5719 ds = "Integrated Raid: Volume Deleted";
5720 break;
5721 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5722 ds = "Integrated Raid: Volume Settings Changed";
5723 break;
5724 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5725 ds = "Integrated Raid: Volume Status Changed";
5726 break;
5727 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5728 ds = "Integrated Raid: Volume Physdisk Changed";
5729 break;
5730 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5731 ds = "Integrated Raid: Physdisk Created";
5732 break;
5733 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5734 ds = "Integrated Raid: Physdisk Deleted";
5735 break;
5736 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5737 ds = "Integrated Raid: Physdisk Settings Changed";
5738 break;
5739 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5740 ds = "Integrated Raid: Physdisk Status Changed";
5741 break;
5742 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5743 ds = "Integrated Raid: Domain Validation Needed";
5744 break;
5745 case MPI_EVENT_RAID_RC_SMART_DATA :
5746 ds = "Integrated Raid; Smart Data";
5747 break;
5748 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5749 ds = "Integrated Raid: Replace Action Started";
5750 break;
5751 default:
5752 ds = "Integrated Raid";
5753 break;
5755 break;
5757 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5758 ds = "SCSI Device Status Change";
5759 break;
5760 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5762 u8 id = (u8)(evData0);
5763 u8 ReasonCode = (u8)(evData0 >> 16);
5764 switch (ReasonCode) {
5765 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5766 snprintf(evStr, EVENT_DESCR_STR_SZ,
5767 "SAS Device Status Change: Added: id=%d", id);
5768 break;
5769 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5770 snprintf(evStr, EVENT_DESCR_STR_SZ,
5771 "SAS Device Status Change: Deleted: id=%d", id);
5772 break;
5773 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5774 snprintf(evStr, EVENT_DESCR_STR_SZ,
5775 "SAS Device Status Change: SMART Data: id=%d",
5776 id);
5777 break;
5778 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5779 snprintf(evStr, EVENT_DESCR_STR_SZ,
5780 "SAS Device Status Change: No Persistancy "
5781 "Added: id=%d", id);
5782 break;
5783 default:
5784 snprintf(evStr, EVENT_DESCR_STR_SZ,
5785 "SAS Device Status Change: Unknown: id=%d", id);
5786 break;
5788 break;
5790 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5791 ds = "Bus Timer Expired";
5792 break;
5793 case MPI_EVENT_QUEUE_FULL:
5794 ds = "Queue Full";
5795 break;
5796 case MPI_EVENT_SAS_SES:
5797 ds = "SAS SES Event";
5798 break;
5799 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5800 ds = "Persistent Table Full";
5801 break;
5802 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5804 u8 LinkRates = (u8)(evData0 >> 8);
5805 u8 PhyNumber = (u8)(evData0);
5806 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5807 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5808 switch (LinkRates) {
5809 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5810 snprintf(evStr, EVENT_DESCR_STR_SZ,
5811 "SAS PHY Link Status: Phy=%d:"
5812 " Rate Unknown",PhyNumber);
5813 break;
5814 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5815 snprintf(evStr, EVENT_DESCR_STR_SZ,
5816 "SAS PHY Link Status: Phy=%d:"
5817 " Phy Disabled",PhyNumber);
5818 break;
5819 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5820 snprintf(evStr, EVENT_DESCR_STR_SZ,
5821 "SAS PHY Link Status: Phy=%d:"
5822 " Failed Speed Nego",PhyNumber);
5823 break;
5824 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5825 snprintf(evStr, EVENT_DESCR_STR_SZ,
5826 "SAS PHY Link Status: Phy=%d:"
5827 " Sata OOB Completed",PhyNumber);
5828 break;
5829 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5830 snprintf(evStr, EVENT_DESCR_STR_SZ,
5831 "SAS PHY Link Status: Phy=%d:"
5832 " Rate 1.5 Gbps",PhyNumber);
5833 break;
5834 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5835 snprintf(evStr, EVENT_DESCR_STR_SZ,
5836 "SAS PHY Link Status: Phy=%d:"
5837 " Rate 3.0 Gpbs",PhyNumber);
5838 break;
5839 default:
5840 snprintf(evStr, EVENT_DESCR_STR_SZ,
5841 "SAS PHY Link Status: Phy=%d", PhyNumber);
5842 break;
5844 break;
5846 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5847 ds = "SAS Discovery Error";
5848 break;
5849 case MPI_EVENT_IR_RESYNC_UPDATE:
5851 u8 resync_complete = (u8)(evData0 >> 16);
5852 snprintf(evStr, EVENT_DESCR_STR_SZ,
5853 "IR Resync Update: Complete = %d:",resync_complete);
5854 break;
5856 case MPI_EVENT_IR2:
5858 u8 ReasonCode = (u8)(evData0 >> 16);
5859 switch (ReasonCode) {
5860 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5861 ds = "IR2: LD State Changed";
5862 break;
5863 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5864 ds = "IR2: PD State Changed";
5865 break;
5866 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5867 ds = "IR2: Bad Block Table Full";
5868 break;
5869 case MPI_EVENT_IR2_RC_PD_INSERTED:
5870 ds = "IR2: PD Inserted";
5871 break;
5872 case MPI_EVENT_IR2_RC_PD_REMOVED:
5873 ds = "IR2: PD Removed";
5874 break;
5875 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5876 ds = "IR2: Foreign CFG Detected";
5877 break;
5878 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5879 ds = "IR2: Rebuild Medium Error";
5880 break;
5881 default:
5882 ds = "IR2";
5883 break;
5885 break;
5887 case MPI_EVENT_SAS_DISCOVERY:
5889 if (evData0)
5890 ds = "SAS Discovery: Start";
5891 else
5892 ds = "SAS Discovery: Stop";
5893 break;
5895 case MPI_EVENT_LOG_ENTRY_ADDED:
5896 ds = "SAS Log Entry Added";
5897 break;
5900 * MPT base "custom" events may be added here...
5902 default:
5903 ds = "Unknown";
5904 break;
5906 if (ds)
5907 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
5910 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5912 * ProcessEventNotification - Route a received EventNotificationReply to
5913 * all currently regeistered event handlers.
5914 * @ioc: Pointer to MPT_ADAPTER structure
5915 * @pEventReply: Pointer to EventNotification reply frame
5916 * @evHandlers: Pointer to integer, number of event handlers
5918 * Returns sum of event handlers return values.
5920 static int
5921 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5923 u16 evDataLen;
5924 u32 evData0 = 0;
5925 // u32 evCtx;
5926 int ii;
5927 int r = 0;
5928 int handlers = 0;
5929 char evStr[EVENT_DESCR_STR_SZ];
5930 u8 event;
5933 * Do platform normalization of values
5935 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5936 // evCtx = le32_to_cpu(pEventReply->EventContext);
5937 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5938 if (evDataLen) {
5939 evData0 = le32_to_cpu(pEventReply->Data[0]);
5942 EventDescriptionStr(event, evData0, evStr);
5943 devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
5944 ioc->name,
5945 event,
5946 evStr));
5948 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
5949 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5950 for (ii = 0; ii < evDataLen; ii++)
5951 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5952 printk("\n");
5953 #endif
5956 * Do general / base driver event processing
5958 switch(event) {
5959 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5960 if (evDataLen) {
5961 u8 evState = evData0 & 0xFF;
5963 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5965 /* Update EventState field in cached IocFacts */
5966 if (ioc->facts.Function) {
5967 ioc->facts.EventState = evState;
5970 break;
5971 case MPI_EVENT_INTEGRATED_RAID:
5972 mptbase_raid_process_event_data(ioc,
5973 (MpiEventDataRaid_t *)pEventReply->Data);
5974 break;
5975 default:
5976 break;
5980 * Should this event be logged? Events are written sequentially.
5981 * When buffer is full, start again at the top.
5983 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5984 int idx;
5986 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
5988 ioc->events[idx].event = event;
5989 ioc->events[idx].eventContext = ioc->eventContext;
5991 for (ii = 0; ii < 2; ii++) {
5992 if (ii < evDataLen)
5993 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5994 else
5995 ioc->events[idx].data[ii] = 0;
5998 ioc->eventContext++;
6003 * Call each currently registered protocol event handler.
6005 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6006 if (MptEvHandlers[ii]) {
6007 devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6008 ioc->name, ii));
6009 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6010 handlers++;
6013 /* FIXME? Examine results here? */
6016 * If needed, send (a single) EventAck.
6018 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6019 devtverboseprintk((MYIOC_s_WARN_FMT
6020 "EventAck required\n",ioc->name));
6021 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6022 devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6023 ioc->name, ii));
6027 *evHandlers = handlers;
6028 return r;
6031 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6033 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6034 * @ioc: Pointer to MPT_ADAPTER structure
6035 * @log_info: U32 LogInfo reply word from the IOC
6037 * Refer to lsi/fc_log.h.
6039 static void
6040 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6042 static char *subcl_str[8] = {
6043 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6044 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6046 u8 subcl = (log_info >> 24) & 0x7;
6048 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6049 ioc->name, log_info, subcl_str[subcl]);
6052 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6054 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6055 * @ioc: Pointer to MPT_ADAPTER structure
6056 * @mr: Pointer to MPT reply frame
6057 * @log_info: U32 LogInfo word from the IOC
6059 * Refer to lsi/sp_log.h.
6061 static void
6062 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6064 u32 info = log_info & 0x00FF0000;
6065 char *desc = "unknown";
6067 switch (info) {
6068 case 0x00010000:
6069 desc = "bug! MID not found";
6070 if (ioc->reload_fw == 0)
6071 ioc->reload_fw++;
6072 break;
6074 case 0x00020000:
6075 desc = "Parity Error";
6076 break;
6078 case 0x00030000:
6079 desc = "ASYNC Outbound Overrun";
6080 break;
6082 case 0x00040000:
6083 desc = "SYNC Offset Error";
6084 break;
6086 case 0x00050000:
6087 desc = "BM Change";
6088 break;
6090 case 0x00060000:
6091 desc = "Msg In Overflow";
6092 break;
6094 case 0x00070000:
6095 desc = "DMA Error";
6096 break;
6098 case 0x00080000:
6099 desc = "Outbound DMA Overrun";
6100 break;
6102 case 0x00090000:
6103 desc = "Task Management";
6104 break;
6106 case 0x000A0000:
6107 desc = "Device Problem";
6108 break;
6110 case 0x000B0000:
6111 desc = "Invalid Phase Change";
6112 break;
6114 case 0x000C0000:
6115 desc = "Untagged Table Size";
6116 break;
6120 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6123 /* strings for sas loginfo */
6124 static char *originator_str[] = {
6125 "IOP", /* 00h */
6126 "PL", /* 01h */
6127 "IR" /* 02h */
6129 static char *iop_code_str[] = {
6130 NULL, /* 00h */
6131 "Invalid SAS Address", /* 01h */
6132 NULL, /* 02h */
6133 "Invalid Page", /* 03h */
6134 NULL, /* 04h */
6135 "Task Terminated" /* 05h */
6137 static char *pl_code_str[] = {
6138 NULL, /* 00h */
6139 "Open Failure", /* 01h */
6140 "Invalid Scatter Gather List", /* 02h */
6141 "Wrong Relative Offset or Frame Length", /* 03h */
6142 "Frame Transfer Error", /* 04h */
6143 "Transmit Frame Connected Low", /* 05h */
6144 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6145 "SATA Read Log Receive Data Error", /* 07h */
6146 "SATA NCQ Fail All Commands After Error", /* 08h */
6147 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6148 "Receive Frame Invalid Message", /* 0Ah */
6149 "Receive Context Message Valid Error", /* 0Bh */
6150 "Receive Frame Current Frame Error", /* 0Ch */
6151 "SATA Link Down", /* 0Dh */
6152 "Discovery SATA Init W IOS", /* 0Eh */
6153 "Config Invalid Page", /* 0Fh */
6154 "Discovery SATA Init Timeout", /* 10h */
6155 "Reset", /* 11h */
6156 "Abort", /* 12h */
6157 "IO Not Yet Executed", /* 13h */
6158 "IO Executed", /* 14h */
6159 "Persistant Reservation Out Not Affiliation Owner", /* 15h */
6160 "Open Transmit DMA Abort", /* 16h */
6161 NULL, /* 17h */
6162 NULL, /* 18h */
6163 NULL, /* 19h */
6164 NULL, /* 1Ah */
6165 NULL, /* 1Bh */
6166 NULL, /* 1Ch */
6167 NULL, /* 1Dh */
6168 NULL, /* 1Eh */
6169 NULL, /* 1Fh */
6170 "Enclosure Management" /* 20h */
6173 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6175 * mpt_sas_log_info - Log information returned from SAS IOC.
6176 * @ioc: Pointer to MPT_ADAPTER structure
6177 * @log_info: U32 LogInfo reply word from the IOC
6179 * Refer to lsi/mpi_log_sas.h.
6181 static void
6182 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6184 union loginfo_type {
6185 u32 loginfo;
6186 struct {
6187 u32 subcode:16;
6188 u32 code:8;
6189 u32 originator:4;
6190 u32 bus_type:4;
6191 }dw;
6193 union loginfo_type sas_loginfo;
6194 char *code_desc = NULL;
6196 sas_loginfo.loginfo = log_info;
6197 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6198 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6199 return;
6200 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6201 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6202 code_desc = iop_code_str[sas_loginfo.dw.code];
6203 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6204 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6205 code_desc = pl_code_str[sas_loginfo.dw.code];
6208 if (code_desc != NULL)
6209 printk(MYIOC_s_INFO_FMT
6210 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6211 " SubCode(0x%04x)\n",
6212 ioc->name,
6213 log_info,
6214 originator_str[sas_loginfo.dw.originator],
6215 code_desc,
6216 sas_loginfo.dw.subcode);
6217 else
6218 printk(MYIOC_s_INFO_FMT
6219 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6220 " SubCode(0x%04x)\n",
6221 ioc->name,
6222 log_info,
6223 originator_str[sas_loginfo.dw.originator],
6224 sas_loginfo.dw.code,
6225 sas_loginfo.dw.subcode);
6228 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6230 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6231 * @ioc: Pointer to MPT_ADAPTER structure
6232 * @ioc_status: U32 IOCStatus word from IOC
6233 * @mf: Pointer to MPT request frame
6235 * Refer to lsi/mpi.h.
6237 static void
6238 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6240 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6241 char *desc = "";
6243 switch (status) {
6244 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6245 desc = "Invalid Function";
6246 break;
6248 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6249 desc = "Busy";
6250 break;
6252 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6253 desc = "Invalid SGL";
6254 break;
6256 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6257 desc = "Internal Error";
6258 break;
6260 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6261 desc = "Reserved";
6262 break;
6264 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6265 desc = "Insufficient Resources";
6266 break;
6268 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6269 desc = "Invalid Field";
6270 break;
6272 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6273 desc = "Invalid State";
6274 break;
6276 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6277 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6278 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6279 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6280 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6281 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6282 /* No message for Config IOCStatus values */
6283 break;
6285 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6286 /* No message for recovered error
6287 desc = "SCSI Recovered Error";
6289 break;
6291 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6292 desc = "SCSI Invalid Bus";
6293 break;
6295 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6296 desc = "SCSI Invalid TargetID";
6297 break;
6299 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6301 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6302 U8 cdb = pScsiReq->CDB[0];
6303 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6304 desc = "SCSI Device Not There";
6306 break;
6309 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6310 desc = "SCSI Data Overrun";
6311 break;
6313 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6314 /* This error is checked in scsi_io_done(). Skip.
6315 desc = "SCSI Data Underrun";
6317 break;
6319 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6320 desc = "SCSI I/O Data Error";
6321 break;
6323 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6324 desc = "SCSI Protocol Error";
6325 break;
6327 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6328 desc = "SCSI Task Terminated";
6329 break;
6331 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6332 desc = "SCSI Residual Mismatch";
6333 break;
6335 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6336 desc = "SCSI Task Management Failed";
6337 break;
6339 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6340 desc = "SCSI IOC Terminated";
6341 break;
6343 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6344 desc = "SCSI Ext Terminated";
6345 break;
6347 default:
6348 desc = "Others";
6349 break;
6351 if (desc != "")
6352 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6355 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6356 EXPORT_SYMBOL(mpt_attach);
6357 EXPORT_SYMBOL(mpt_detach);
6358 #ifdef CONFIG_PM
6359 EXPORT_SYMBOL(mpt_resume);
6360 EXPORT_SYMBOL(mpt_suspend);
6361 #endif
6362 EXPORT_SYMBOL(ioc_list);
6363 EXPORT_SYMBOL(mpt_proc_root_dir);
6364 EXPORT_SYMBOL(mpt_register);
6365 EXPORT_SYMBOL(mpt_deregister);
6366 EXPORT_SYMBOL(mpt_event_register);
6367 EXPORT_SYMBOL(mpt_event_deregister);
6368 EXPORT_SYMBOL(mpt_reset_register);
6369 EXPORT_SYMBOL(mpt_reset_deregister);
6370 EXPORT_SYMBOL(mpt_device_driver_register);
6371 EXPORT_SYMBOL(mpt_device_driver_deregister);
6372 EXPORT_SYMBOL(mpt_get_msg_frame);
6373 EXPORT_SYMBOL(mpt_put_msg_frame);
6374 EXPORT_SYMBOL(mpt_free_msg_frame);
6375 EXPORT_SYMBOL(mpt_add_sge);
6376 EXPORT_SYMBOL(mpt_send_handshake_request);
6377 EXPORT_SYMBOL(mpt_verify_adapter);
6378 EXPORT_SYMBOL(mpt_GetIocState);
6379 EXPORT_SYMBOL(mpt_print_ioc_summary);
6380 EXPORT_SYMBOL(mpt_lan_index);
6381 EXPORT_SYMBOL(mpt_stm_index);
6382 EXPORT_SYMBOL(mpt_HardResetHandler);
6383 EXPORT_SYMBOL(mpt_config);
6384 EXPORT_SYMBOL(mpt_findImVolumes);
6385 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6386 EXPORT_SYMBOL(mpt_free_fw_memory);
6387 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6390 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6392 * fusion_init - Fusion MPT base driver initialization routine.
6394 * Returns 0 for success, non-zero for failure.
6396 static int __init
6397 fusion_init(void)
6399 int i;
6401 show_mptmod_ver(my_NAME, my_VERSION);
6402 printk(KERN_INFO COPYRIGHT "\n");
6404 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6405 MptCallbacks[i] = NULL;
6406 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6407 MptEvHandlers[i] = NULL;
6408 MptResetHandlers[i] = NULL;
6411 /* Register ourselves (mptbase) in order to facilitate
6412 * EventNotification handling.
6414 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6416 /* Register for hard reset handling callbacks.
6418 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6419 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6420 } else {
6421 /* FIXME! */
6424 #ifdef CONFIG_PROC_FS
6425 (void) procmpt_create();
6426 #endif
6427 return 0;
6430 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6432 * fusion_exit - Perform driver unload cleanup.
6434 * This routine frees all resources associated with each MPT adapter
6435 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6437 static void __exit
6438 fusion_exit(void)
6441 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6443 mpt_reset_deregister(mpt_base_index);
6445 #ifdef CONFIG_PROC_FS
6446 procmpt_destroy();
6447 #endif
6450 module_init(fusion_init);
6451 module_exit(fusion_exit);