Linux 2.6.17.7
[linux/fpc-iii.git] / drivers / message / fusion / mptbase.c
bloba30084076ac8884168c444d04d9377a32238507d
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/config.h>
50 #include <linux/kernel.h>
51 #include <linux/module.h>
52 #include <linux/errno.h>
53 #include <linux/init.h>
54 #include <linux/slab.h>
55 #include <linux/types.h>
56 #include <linux/pci.h>
57 #include <linux/kdev_t.h>
58 #include <linux/blkdev.h>
59 #include <linux/delay.h>
60 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
61 #include <linux/dma-mapping.h>
62 #include <asm/io.h>
63 #ifdef CONFIG_MTRR
64 #include <asm/mtrr.h>
65 #endif
66 #ifdef __sparc__
67 #include <asm/irq.h> /* needed for __irq_itoa() proto */
68 #endif
70 #include "mptbase.h"
72 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
73 #define my_NAME "Fusion MPT base driver"
74 #define my_VERSION MPT_LINUX_VERSION_COMMON
75 #define MYNAM "mptbase"
77 MODULE_AUTHOR(MODULEAUTHOR);
78 MODULE_DESCRIPTION(my_NAME);
79 MODULE_LICENSE("GPL");
82 * cmd line parameters
84 static int mpt_msi_enable;
85 module_param(mpt_msi_enable, int, 0);
86 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
88 #ifdef MFCNT
89 static int mfcounter = 0;
90 #define PRINT_MF_COUNT 20000
91 #endif
93 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
95 * Public data...
97 int mpt_lan_index = -1;
98 int mpt_stm_index = -1;
100 struct proc_dir_entry *mpt_proc_root_dir;
102 #define WHOINIT_UNKNOWN 0xAA
104 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
106 * Private data...
108 /* Adapter link list */
109 LIST_HEAD(ioc_list);
110 /* Callback lookup table */
111 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
112 /* Protocol driver class lookup table */
113 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
114 /* Event handler lookup table */
115 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
116 /* Reset handler lookup table */
117 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
118 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
120 static int mpt_base_index = -1;
121 static int last_drv_idx = -1;
123 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
125 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
127 * Forward protos...
129 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
130 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
131 static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
132 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
133 int sleepFlag);
134 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
135 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
136 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
137 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
139 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
140 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
141 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
142 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
143 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
144 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
145 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
146 static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
147 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
148 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
149 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
150 static int PrimeIocFifos(MPT_ADAPTER *ioc);
151 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
152 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
153 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
154 static int GetLanConfigPages(MPT_ADAPTER *ioc);
155 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
156 int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
157 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
158 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
159 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
160 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
161 static void mpt_timer_expired(unsigned long data);
162 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
163 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
164 static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
165 static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
167 #ifdef CONFIG_PROC_FS
168 static int procmpt_summary_read(char *buf, char **start, off_t offset,
169 int request, int *eof, void *data);
170 static int procmpt_version_read(char *buf, char **start, off_t offset,
171 int request, int *eof, void *data);
172 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
173 int request, int *eof, void *data);
174 #endif
175 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
177 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
178 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
179 static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
180 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
181 static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
182 static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
183 static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
185 /* module entry point */
186 static int __init fusion_init (void);
187 static void __exit fusion_exit (void);
189 #define CHIPREG_READ32(addr) readl_relaxed(addr)
190 #define CHIPREG_READ32_dmasync(addr) readl(addr)
191 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
192 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
193 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
195 static void
196 pci_disable_io_access(struct pci_dev *pdev)
198 u16 command_reg;
200 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
201 command_reg &= ~1;
202 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
205 static void
206 pci_enable_io_access(struct pci_dev *pdev)
208 u16 command_reg;
210 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
211 command_reg |= 1;
212 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
216 * Process turbo (context) reply...
218 static void
219 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
221 MPT_FRAME_HDR *mf = NULL;
222 MPT_FRAME_HDR *mr = NULL;
223 int req_idx = 0;
224 int cb_idx;
226 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
227 ioc->name, pa));
229 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
230 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
231 req_idx = pa & 0x0000FFFF;
232 cb_idx = (pa & 0x00FF0000) >> 16;
233 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
234 break;
235 case MPI_CONTEXT_REPLY_TYPE_LAN:
236 cb_idx = mpt_lan_index;
238 * Blind set of mf to NULL here was fatal
239 * after lan_reply says "freeme"
240 * Fix sort of combined with an optimization here;
241 * added explicit check for case where lan_reply
242 * was just returning 1 and doing nothing else.
243 * For this case skip the callback, but set up
244 * proper mf value first here:-)
246 if ((pa & 0x58000000) == 0x58000000) {
247 req_idx = pa & 0x0000FFFF;
248 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
249 mpt_free_msg_frame(ioc, mf);
250 mb();
251 return;
252 break;
254 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
255 break;
256 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
257 cb_idx = mpt_stm_index;
258 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
259 break;
260 default:
261 cb_idx = 0;
262 BUG();
265 /* Check for (valid) IO callback! */
266 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
267 MptCallbacks[cb_idx] == NULL) {
268 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
269 __FUNCTION__, ioc->name, cb_idx);
270 goto out;
273 if (MptCallbacks[cb_idx](ioc, mf, mr))
274 mpt_free_msg_frame(ioc, mf);
275 out:
276 mb();
279 static void
280 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
282 MPT_FRAME_HDR *mf;
283 MPT_FRAME_HDR *mr;
284 int req_idx;
285 int cb_idx;
286 int freeme;
288 u32 reply_dma_low;
289 u16 ioc_stat;
291 /* non-TURBO reply! Hmmm, something may be up...
292 * Newest turbo reply mechanism; get address
293 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
296 /* Map DMA address of reply header to cpu address.
297 * pa is 32 bits - but the dma address may be 32 or 64 bits
298 * get offset based only only the low addresses
301 reply_dma_low = (pa <<= 1);
302 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
303 (reply_dma_low - ioc->reply_frames_low_dma));
305 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
306 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
307 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
309 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
310 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
311 DBG_DUMP_REPLY_FRAME(mr)
313 /* Check/log IOC log info
315 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
316 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
317 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
318 if (ioc->bus_type == FC)
319 mpt_fc_log_info(ioc, log_info);
320 else if (ioc->bus_type == SPI)
321 mpt_spi_log_info(ioc, log_info);
322 else if (ioc->bus_type == SAS)
323 mpt_sas_log_info(ioc, log_info);
325 if (ioc_stat & MPI_IOCSTATUS_MASK) {
326 if (ioc->bus_type == SPI &&
327 cb_idx != mpt_stm_index &&
328 cb_idx != mpt_lan_index)
329 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
333 /* Check for (valid) IO callback! */
334 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
335 MptCallbacks[cb_idx] == NULL) {
336 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
337 __FUNCTION__, ioc->name, cb_idx);
338 freeme = 0;
339 goto out;
342 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
344 out:
345 /* Flush (non-TURBO) reply with a WRITE! */
346 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
348 if (freeme)
349 mpt_free_msg_frame(ioc, mf);
350 mb();
353 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
355 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
356 * @irq: irq number (not used)
357 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
358 * @r: pt_regs pointer (not used)
360 * This routine is registered via the request_irq() kernel API call,
361 * and handles all interrupts generated from a specific MPT adapter
362 * (also referred to as a IO Controller or IOC).
363 * This routine must clear the interrupt from the adapter and does
364 * so by reading the reply FIFO. Multiple replies may be processed
365 * per single call to this routine.
367 * This routine handles register-level access of the adapter but
368 * dispatches (calls) a protocol-specific callback routine to handle
369 * the protocol-specific details of the MPT request completion.
371 static irqreturn_t
372 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
374 MPT_ADAPTER *ioc = bus_id;
375 u32 pa;
378 * Drain the reply FIFO!
380 while (1) {
381 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
382 if (pa == 0xFFFFFFFF)
383 return IRQ_HANDLED;
384 else if (pa & MPI_ADDRESS_REPLY_A_BIT)
385 mpt_reply(ioc, pa);
386 else
387 mpt_turbo_reply(ioc, pa);
390 return IRQ_HANDLED;
393 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
395 * mpt_base_reply - MPT base driver's callback routine; all base driver
396 * "internal" request/reply processing is routed here.
397 * Currently used for EventNotification and EventAck handling.
398 * @ioc: Pointer to MPT_ADAPTER structure
399 * @mf: Pointer to original MPT request frame
400 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
402 * Returns 1 indicating original alloc'd request frame ptr
403 * should be freed, or 0 if it shouldn't.
405 static int
406 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
408 int freereq = 1;
409 u8 func;
411 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
413 #if defined(MPT_DEBUG_MSG_FRAME)
414 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
415 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
416 DBG_DUMP_REQUEST_FRAME_HDR(mf)
418 #endif
420 func = reply->u.hdr.Function;
421 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
422 ioc->name, func));
424 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
425 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
426 int evHandlers = 0;
427 int results;
429 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
430 if (results != evHandlers) {
431 /* CHECKME! Any special handling needed here? */
432 devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
433 ioc->name, evHandlers, results));
437 * Hmmm... It seems that EventNotificationReply is an exception
438 * to the rule of one reply per request.
440 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
441 freereq = 0;
442 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
443 ioc->name, pEvReply));
444 } else {
445 devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
446 ioc->name, pEvReply));
449 #ifdef CONFIG_PROC_FS
450 // LogEvent(ioc, pEvReply);
451 #endif
453 } else if (func == MPI_FUNCTION_EVENT_ACK) {
454 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
455 ioc->name));
456 } else if (func == MPI_FUNCTION_CONFIG) {
457 CONFIGPARMS *pCfg;
458 unsigned long flags;
460 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
461 ioc->name, mf, reply));
463 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
465 if (pCfg) {
466 /* disable timer and remove from linked list */
467 del_timer(&pCfg->timer);
469 spin_lock_irqsave(&ioc->FreeQlock, flags);
470 list_del(&pCfg->linkage);
471 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
474 * If IOC Status is SUCCESS, save the header
475 * and set the status code to GOOD.
477 pCfg->status = MPT_CONFIG_ERROR;
478 if (reply) {
479 ConfigReply_t *pReply = (ConfigReply_t *)reply;
480 u16 status;
482 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
483 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
484 status, le32_to_cpu(pReply->IOCLogInfo)));
486 pCfg->status = status;
487 if (status == MPI_IOCSTATUS_SUCCESS) {
488 if ((pReply->Header.PageType &
489 MPI_CONFIG_PAGETYPE_MASK) ==
490 MPI_CONFIG_PAGETYPE_EXTENDED) {
491 pCfg->cfghdr.ehdr->ExtPageLength =
492 le16_to_cpu(pReply->ExtPageLength);
493 pCfg->cfghdr.ehdr->ExtPageType =
494 pReply->ExtPageType;
496 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
498 /* If this is a regular header, save PageLength. */
499 /* LMP Do this better so not using a reserved field! */
500 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
501 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
502 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
507 * Wake up the original calling thread
509 pCfg->wait_done = 1;
510 wake_up(&mpt_waitq);
512 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
513 /* we should be always getting a reply frame */
514 memcpy(ioc->persist_reply_frame, reply,
515 min(MPT_DEFAULT_FRAME_SIZE,
516 4*reply->u.reply.MsgLength));
517 del_timer(&ioc->persist_timer);
518 ioc->persist_wait_done = 1;
519 wake_up(&mpt_waitq);
520 } else {
521 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
522 ioc->name, func);
526 * Conditionally tell caller to free the original
527 * EventNotification/EventAck/unexpected request frame!
529 return freereq;
532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
534 * mpt_register - Register protocol-specific main callback handler.
535 * @cbfunc: callback function pointer
536 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
538 * This routine is called by a protocol-specific driver (SCSI host,
539 * LAN, SCSI target) to register it's reply callback routine. Each
540 * protocol-specific driver must do this before it will be able to
541 * use any IOC resources, such as obtaining request frames.
543 * NOTES: The SCSI protocol driver currently calls this routine thrice
544 * in order to register separate callbacks; one for "normal" SCSI IO;
545 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
547 * Returns a positive integer valued "handle" in the
548 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
549 * Any non-positive return value (including zero!) should be considered
550 * an error by the caller.
553 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
555 int i;
557 last_drv_idx = -1;
560 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
561 * (slot/handle 0 is reserved!)
563 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
564 if (MptCallbacks[i] == NULL) {
565 MptCallbacks[i] = cbfunc;
566 MptDriverClass[i] = dclass;
567 MptEvHandlers[i] = NULL;
568 last_drv_idx = i;
569 break;
573 return last_drv_idx;
576 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
578 * mpt_deregister - Deregister a protocol drivers resources.
579 * @cb_idx: previously registered callback handle
581 * Each protocol-specific driver should call this routine when it's
582 * module is unloaded.
584 void
585 mpt_deregister(int cb_idx)
587 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
588 MptCallbacks[cb_idx] = NULL;
589 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
590 MptEvHandlers[cb_idx] = NULL;
592 last_drv_idx++;
596 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
598 * mpt_event_register - Register protocol-specific event callback
599 * handler.
600 * @cb_idx: previously registered (via mpt_register) callback handle
601 * @ev_cbfunc: callback function
603 * This routine can be called by one or more protocol-specific drivers
604 * if/when they choose to be notified of MPT events.
606 * Returns 0 for success.
609 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
611 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
612 return -1;
614 MptEvHandlers[cb_idx] = ev_cbfunc;
615 return 0;
618 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
620 * mpt_event_deregister - Deregister protocol-specific event callback
621 * handler.
622 * @cb_idx: previously registered callback handle
624 * Each protocol-specific driver should call this routine
625 * when it does not (or can no longer) handle events,
626 * or when it's module is unloaded.
628 void
629 mpt_event_deregister(int cb_idx)
631 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
632 return;
634 MptEvHandlers[cb_idx] = NULL;
637 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
639 * mpt_reset_register - Register protocol-specific IOC reset handler.
640 * @cb_idx: previously registered (via mpt_register) callback handle
641 * @reset_func: reset function
643 * This routine can be called by one or more protocol-specific drivers
644 * if/when they choose to be notified of IOC resets.
646 * Returns 0 for success.
649 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
651 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
652 return -1;
654 MptResetHandlers[cb_idx] = reset_func;
655 return 0;
658 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
660 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
661 * @cb_idx: previously registered callback handle
663 * Each protocol-specific driver should call this routine
664 * when it does not (or can no longer) handle IOC reset handling,
665 * or when it's module is unloaded.
667 void
668 mpt_reset_deregister(int cb_idx)
670 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
671 return;
673 MptResetHandlers[cb_idx] = NULL;
676 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
678 * mpt_device_driver_register - Register device driver hooks
681 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
683 MPT_ADAPTER *ioc;
685 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
686 return -EINVAL;
689 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
691 /* call per pci device probe entry point */
692 list_for_each_entry(ioc, &ioc_list, list) {
693 if(dd_cbfunc->probe) {
694 dd_cbfunc->probe(ioc->pcidev,
695 ioc->pcidev->driver->id_table);
699 return 0;
702 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
704 * mpt_device_driver_deregister - DeRegister device driver hooks
706 void
707 mpt_device_driver_deregister(int cb_idx)
709 struct mpt_pci_driver *dd_cbfunc;
710 MPT_ADAPTER *ioc;
712 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
713 return;
715 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
717 list_for_each_entry(ioc, &ioc_list, list) {
718 if (dd_cbfunc->remove)
719 dd_cbfunc->remove(ioc->pcidev);
722 MptDeviceDriverHandlers[cb_idx] = NULL;
726 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
728 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
729 * allocated per MPT adapter.
730 * @handle: Handle of registered MPT protocol driver
731 * @ioc: Pointer to MPT adapter structure
733 * Returns pointer to a MPT request frame or %NULL if none are available
734 * or IOC is not active.
736 MPT_FRAME_HDR*
737 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
739 MPT_FRAME_HDR *mf;
740 unsigned long flags;
741 u16 req_idx; /* Request index */
743 /* validate handle and ioc identifier */
745 #ifdef MFCNT
746 if (!ioc->active)
747 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
748 #endif
750 /* If interrupts are not attached, do not return a request frame */
751 if (!ioc->active)
752 return NULL;
754 spin_lock_irqsave(&ioc->FreeQlock, flags);
755 if (!list_empty(&ioc->FreeQ)) {
756 int req_offset;
758 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
759 u.frame.linkage.list);
760 list_del(&mf->u.frame.linkage.list);
761 mf->u.frame.linkage.arg1 = 0;
762 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
763 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
764 /* u16! */
765 req_idx = req_offset / ioc->req_sz;
766 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
767 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
768 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
769 #ifdef MFCNT
770 ioc->mfcnt++;
771 #endif
773 else
774 mf = NULL;
775 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
777 #ifdef MFCNT
778 if (mf == NULL)
779 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
780 mfcounter++;
781 if (mfcounter == PRINT_MF_COUNT)
782 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
783 #endif
785 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
786 ioc->name, handle, ioc->id, mf));
787 return mf;
790 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
792 * mpt_put_msg_frame - Send a protocol specific MPT request frame
793 * to a IOC.
794 * @handle: Handle of registered MPT protocol driver
795 * @ioc: Pointer to MPT adapter structure
796 * @mf: Pointer to MPT request frame
798 * This routine posts a MPT request frame to the request post FIFO of a
799 * specific MPT adapter.
801 void
802 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
804 u32 mf_dma_addr;
805 int req_offset;
806 u16 req_idx; /* Request index */
808 /* ensure values are reset properly! */
809 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
810 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
811 /* u16! */
812 req_idx = req_offset / ioc->req_sz;
813 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
814 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
816 #ifdef MPT_DEBUG_MSG_FRAME
818 u32 *m = mf->u.frame.hwhdr.__hdr;
819 int ii, n;
821 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
822 ioc->name, m);
823 n = ioc->req_sz/4 - 1;
824 while (m[n] == 0)
825 n--;
826 for (ii=0; ii<=n; ii++) {
827 if (ii && ((ii%8)==0))
828 printk("\n" KERN_INFO " ");
829 printk(" %08x", le32_to_cpu(m[ii]));
831 printk("\n");
833 #endif
835 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
836 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]));
837 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
840 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
842 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
843 * @handle: Handle of registered MPT protocol driver
844 * @ioc: Pointer to MPT adapter structure
845 * @mf: Pointer to MPT request frame
847 * This routine places a MPT request frame back on the MPT adapter's
848 * FreeQ.
850 void
851 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
853 unsigned long flags;
855 /* Put Request back on FreeQ! */
856 spin_lock_irqsave(&ioc->FreeQlock, flags);
857 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
858 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
859 #ifdef MFCNT
860 ioc->mfcnt--;
861 #endif
862 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
865 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
867 * mpt_add_sge - Place a simple SGE at address pAddr.
868 * @pAddr: virtual address for SGE
869 * @flagslength: SGE flags and data transfer length
870 * @dma_addr: Physical address
872 * This routine places a MPT request frame back on the MPT adapter's
873 * FreeQ.
875 void
876 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
878 if (sizeof(dma_addr_t) == sizeof(u64)) {
879 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
880 u32 tmp = dma_addr & 0xFFFFFFFF;
882 pSge->FlagsLength = cpu_to_le32(flagslength);
883 pSge->Address.Low = cpu_to_le32(tmp);
884 tmp = (u32) ((u64)dma_addr >> 32);
885 pSge->Address.High = cpu_to_le32(tmp);
887 } else {
888 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
889 pSge->FlagsLength = cpu_to_le32(flagslength);
890 pSge->Address = cpu_to_le32(dma_addr);
894 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
896 * mpt_send_handshake_request - Send MPT request via doorbell
897 * handshake method.
898 * @handle: Handle of registered MPT protocol driver
899 * @ioc: Pointer to MPT adapter structure
900 * @reqBytes: Size of the request in bytes
901 * @req: Pointer to MPT request frame
902 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
904 * This routine is used exclusively to send MptScsiTaskMgmt
905 * requests since they are required to be sent via doorbell handshake.
907 * NOTE: It is the callers responsibility to byte-swap fields in the
908 * request which are greater than 1 byte in size.
910 * Returns 0 for success, non-zero for failure.
913 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
915 int r = 0;
916 u8 *req_as_bytes;
917 int ii;
919 /* State is known to be good upon entering
920 * this function so issue the bus reset
921 * request.
925 * Emulate what mpt_put_msg_frame() does /wrt to sanity
926 * setting cb_idx/req_idx. But ONLY if this request
927 * is in proper (pre-alloc'd) request buffer range...
929 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
930 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
931 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
932 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
933 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
936 /* Make sure there are no doorbells */
937 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
939 CHIPREG_WRITE32(&ioc->chip->Doorbell,
940 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
941 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
943 /* Wait for IOC doorbell int */
944 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
945 return ii;
948 /* Read doorbell and check for active bit */
949 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
950 return -5;
952 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
953 ioc->name, ii));
955 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
957 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
958 return -2;
961 /* Send request via doorbell handshake */
962 req_as_bytes = (u8 *) req;
963 for (ii = 0; ii < reqBytes/4; ii++) {
964 u32 word;
966 word = ((req_as_bytes[(ii*4) + 0] << 0) |
967 (req_as_bytes[(ii*4) + 1] << 8) |
968 (req_as_bytes[(ii*4) + 2] << 16) |
969 (req_as_bytes[(ii*4) + 3] << 24));
970 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
971 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
972 r = -3;
973 break;
977 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
978 r = 0;
979 else
980 r = -4;
982 /* Make sure there are no doorbells */
983 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
985 return r;
988 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
990 * mpt_host_page_access_control - provides mechanism for the host
991 * driver to control the IOC's Host Page Buffer access.
992 * @ioc: Pointer to MPT adapter structure
993 * @access_control_value: define bits below
995 * Access Control Value - bits[15:12]
996 * 0h Reserved
997 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
998 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
999 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1001 * Returns 0 for success, non-zero for failure.
1004 static int
1005 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1007 int r = 0;
1009 /* return if in use */
1010 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1011 & MPI_DOORBELL_ACTIVE)
1012 return -1;
1014 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1016 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1017 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1018 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1019 (access_control_value<<12)));
1021 /* Wait for IOC to clear Doorbell Status bit */
1022 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1023 return -2;
1024 }else
1025 return 0;
1028 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1030 * mpt_host_page_alloc - allocate system memory for the fw
1031 * If we already allocated memory in past, then resend the same pointer.
1032 * ioc@: Pointer to pointer to IOC adapter
1033 * ioc_init@: Pointer to ioc init config page
1035 * Returns 0 for success, non-zero for failure.
1037 static int
1038 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1040 char *psge;
1041 int flags_length;
1042 u32 host_page_buffer_sz=0;
1044 if(!ioc->HostPageBuffer) {
1046 host_page_buffer_sz =
1047 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1049 if(!host_page_buffer_sz)
1050 return 0; /* fw doesn't need any host buffers */
1052 /* spin till we get enough memory */
1053 while(host_page_buffer_sz > 0) {
1055 if((ioc->HostPageBuffer = pci_alloc_consistent(
1056 ioc->pcidev,
1057 host_page_buffer_sz,
1058 &ioc->HostPageBuffer_dma)) != NULL) {
1060 dinitprintk((MYIOC_s_INFO_FMT
1061 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1062 ioc->name,
1063 ioc->HostPageBuffer,
1064 ioc->HostPageBuffer_dma,
1065 host_page_buffer_sz));
1066 ioc->alloc_total += host_page_buffer_sz;
1067 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1068 break;
1071 host_page_buffer_sz -= (4*1024);
1075 if(!ioc->HostPageBuffer) {
1076 printk(MYIOC_s_ERR_FMT
1077 "Failed to alloc memory for host_page_buffer!\n",
1078 ioc->name);
1079 return -999;
1082 psge = (char *)&ioc_init->HostPageBufferSGE;
1083 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1084 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1085 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1086 MPI_SGE_FLAGS_HOST_TO_IOC |
1087 MPI_SGE_FLAGS_END_OF_BUFFER;
1088 if (sizeof(dma_addr_t) == sizeof(u64)) {
1089 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1091 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1092 flags_length |= ioc->HostPageBuffer_sz;
1093 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1094 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1096 return 0;
1099 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1101 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1102 * the associated MPT adapter structure.
1103 * @iocid: IOC unique identifier (integer)
1104 * @iocpp: Pointer to pointer to IOC adapter
1106 * Returns iocid and sets iocpp.
1109 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1111 MPT_ADAPTER *ioc;
1113 list_for_each_entry(ioc,&ioc_list,list) {
1114 if (ioc->id == iocid) {
1115 *iocpp =ioc;
1116 return iocid;
1120 *iocpp = NULL;
1121 return -1;
1124 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1126 * mpt_attach - Install a PCI intelligent MPT adapter.
1127 * @pdev: Pointer to pci_dev structure
1129 * This routine performs all the steps necessary to bring the IOC of
1130 * a MPT adapter to a OPERATIONAL state. This includes registering
1131 * memory regions, registering the interrupt, and allocating request
1132 * and reply memory pools.
1134 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1135 * MPT adapter.
1137 * Returns 0 for success, non-zero for failure.
1139 * TODO: Add support for polled controllers
1142 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1144 MPT_ADAPTER *ioc;
1145 u8 __iomem *mem;
1146 unsigned long mem_phys;
1147 unsigned long port;
1148 u32 msize;
1149 u32 psize;
1150 int ii;
1151 int r = -ENODEV;
1152 u8 revision;
1153 u8 pcixcmd;
1154 static int mpt_ids = 0;
1155 #ifdef CONFIG_PROC_FS
1156 struct proc_dir_entry *dent, *ent;
1157 #endif
1159 if (pci_enable_device(pdev))
1160 return r;
1162 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1164 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1165 dprintk((KERN_INFO MYNAM
1166 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1167 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1168 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1169 return r;
1172 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1173 dprintk((KERN_INFO MYNAM
1174 ": Using 64 bit consistent mask\n"));
1175 else
1176 dprintk((KERN_INFO MYNAM
1177 ": Not using 64 bit consistent mask\n"));
1179 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1180 if (ioc == NULL) {
1181 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1182 return -ENOMEM;
1184 ioc->alloc_total = sizeof(MPT_ADAPTER);
1185 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1186 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1188 ioc->pcidev = pdev;
1189 ioc->diagPending = 0;
1190 spin_lock_init(&ioc->diagLock);
1191 spin_lock_init(&ioc->fc_rescan_work_lock);
1192 spin_lock_init(&ioc->initializing_hba_lock);
1194 /* Initialize the event logging.
1196 ioc->eventTypes = 0; /* None */
1197 ioc->eventContext = 0;
1198 ioc->eventLogSize = 0;
1199 ioc->events = NULL;
1201 #ifdef MFCNT
1202 ioc->mfcnt = 0;
1203 #endif
1205 ioc->cached_fw = NULL;
1207 /* Initilize SCSI Config Data structure
1209 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1211 /* Initialize the running configQ head.
1213 INIT_LIST_HEAD(&ioc->configQ);
1215 /* Initialize the fc rport list head.
1217 INIT_LIST_HEAD(&ioc->fc_rports);
1219 /* Find lookup slot. */
1220 INIT_LIST_HEAD(&ioc->list);
1221 ioc->id = mpt_ids++;
1223 mem_phys = msize = 0;
1224 port = psize = 0;
1225 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1226 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1227 /* Get I/O space! */
1228 port = pci_resource_start(pdev, ii);
1229 psize = pci_resource_len(pdev,ii);
1230 } else {
1231 /* Get memmap */
1232 mem_phys = pci_resource_start(pdev, ii);
1233 msize = pci_resource_len(pdev,ii);
1234 break;
1237 ioc->mem_size = msize;
1239 if (ii == DEVICE_COUNT_RESOURCE) {
1240 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1241 kfree(ioc);
1242 return -EINVAL;
1245 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1246 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1248 mem = NULL;
1249 /* Get logical ptr for PciMem0 space */
1250 /*mem = ioremap(mem_phys, msize);*/
1251 mem = ioremap(mem_phys, 0x100);
1252 if (mem == NULL) {
1253 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1254 kfree(ioc);
1255 return -EINVAL;
1257 ioc->memmap = mem;
1258 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1260 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1261 &ioc->facts, &ioc->pfacts[0]));
1263 ioc->mem_phys = mem_phys;
1264 ioc->chip = (SYSIF_REGS __iomem *)mem;
1266 /* Save Port IO values in case we need to do downloadboot */
1268 u8 *pmem = (u8*)port;
1269 ioc->pio_mem_phys = port;
1270 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1273 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1274 ioc->prod_name = "LSIFC909";
1275 ioc->bus_type = FC;
1277 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1278 ioc->prod_name = "LSIFC929";
1279 ioc->bus_type = FC;
1281 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1282 ioc->prod_name = "LSIFC919";
1283 ioc->bus_type = FC;
1285 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1286 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1287 ioc->bus_type = FC;
1288 if (revision < XL_929) {
1289 ioc->prod_name = "LSIFC929X";
1290 /* 929X Chip Fix. Set Split transactions level
1291 * for PCIX. Set MOST bits to zero.
1293 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1294 pcixcmd &= 0x8F;
1295 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1296 } else {
1297 ioc->prod_name = "LSIFC929XL";
1298 /* 929XL Chip Fix. Set MMRBC to 0x08.
1300 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1301 pcixcmd |= 0x08;
1302 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1305 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1306 ioc->prod_name = "LSIFC919X";
1307 ioc->bus_type = FC;
1308 /* 919X Chip Fix. Set Split transactions level
1309 * for PCIX. Set MOST bits to zero.
1311 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1312 pcixcmd &= 0x8F;
1313 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1315 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1316 ioc->prod_name = "LSIFC939X";
1317 ioc->bus_type = FC;
1318 ioc->errata_flag_1064 = 1;
1320 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1321 ioc->prod_name = "LSIFC949X";
1322 ioc->bus_type = FC;
1323 ioc->errata_flag_1064 = 1;
1325 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1326 ioc->prod_name = "LSIFC949E";
1327 ioc->bus_type = FC;
1329 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1330 ioc->prod_name = "LSI53C1030";
1331 ioc->bus_type = SPI;
1332 /* 1030 Chip Fix. Disable Split transactions
1333 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1335 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1336 if (revision < C0_1030) {
1337 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1338 pcixcmd &= 0x8F;
1339 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1342 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1343 ioc->prod_name = "LSI53C1035";
1344 ioc->bus_type = SPI;
1346 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1347 ioc->prod_name = "LSISAS1064";
1348 ioc->bus_type = SAS;
1349 ioc->errata_flag_1064 = 1;
1351 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
1352 ioc->prod_name = "LSISAS1066";
1353 ioc->bus_type = SAS;
1354 ioc->errata_flag_1064 = 1;
1356 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1357 ioc->prod_name = "LSISAS1068";
1358 ioc->bus_type = SAS;
1359 ioc->errata_flag_1064 = 1;
1361 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1362 ioc->prod_name = "LSISAS1064E";
1363 ioc->bus_type = SAS;
1365 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
1366 ioc->prod_name = "LSISAS1066E";
1367 ioc->bus_type = SAS;
1369 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1370 ioc->prod_name = "LSISAS1068E";
1371 ioc->bus_type = SAS;
1374 if (ioc->errata_flag_1064)
1375 pci_disable_io_access(pdev);
1377 sprintf(ioc->name, "ioc%d", ioc->id);
1379 spin_lock_init(&ioc->FreeQlock);
1381 /* Disable all! */
1382 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1383 ioc->active = 0;
1384 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1386 /* Set lookup ptr. */
1387 list_add_tail(&ioc->list, &ioc_list);
1389 ioc->pci_irq = -1;
1390 if (pdev->irq) {
1391 if (mpt_msi_enable && !pci_enable_msi(pdev))
1392 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
1394 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1396 if (r < 0) {
1397 #ifndef __sparc__
1398 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1399 ioc->name, pdev->irq);
1400 #else
1401 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1402 ioc->name, __irq_itoa(pdev->irq));
1403 #endif
1404 list_del(&ioc->list);
1405 iounmap(mem);
1406 kfree(ioc);
1407 return -EBUSY;
1410 ioc->pci_irq = pdev->irq;
1412 pci_set_master(pdev); /* ?? */
1413 pci_set_drvdata(pdev, ioc);
1415 #ifndef __sparc__
1416 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1417 #else
1418 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1419 #endif
1422 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1424 mpt_detect_bound_ports(ioc, pdev);
1426 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1427 CAN_SLEEP)) != 0){
1428 printk(KERN_WARNING MYNAM
1429 ": WARNING - %s did not initialize properly! (%d)\n",
1430 ioc->name, r);
1432 list_del(&ioc->list);
1433 free_irq(ioc->pci_irq, ioc);
1434 if (mpt_msi_enable)
1435 pci_disable_msi(pdev);
1436 if (ioc->alt_ioc)
1437 ioc->alt_ioc->alt_ioc = NULL;
1438 iounmap(mem);
1439 kfree(ioc);
1440 pci_set_drvdata(pdev, NULL);
1441 return r;
1444 /* call per device driver probe entry point */
1445 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1446 if(MptDeviceDriverHandlers[ii] &&
1447 MptDeviceDriverHandlers[ii]->probe) {
1448 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1452 #ifdef CONFIG_PROC_FS
1454 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1456 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1457 if (dent) {
1458 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1459 if (ent) {
1460 ent->read_proc = procmpt_iocinfo_read;
1461 ent->data = ioc;
1463 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1464 if (ent) {
1465 ent->read_proc = procmpt_summary_read;
1466 ent->data = ioc;
1469 #endif
1471 return 0;
1474 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1476 * mpt_detach - Remove a PCI intelligent MPT adapter.
1477 * @pdev: Pointer to pci_dev structure
1481 void
1482 mpt_detach(struct pci_dev *pdev)
1484 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1485 char pname[32];
1486 int ii;
1488 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1489 remove_proc_entry(pname, NULL);
1490 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1491 remove_proc_entry(pname, NULL);
1492 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1493 remove_proc_entry(pname, NULL);
1495 /* call per device driver remove entry point */
1496 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1497 if(MptDeviceDriverHandlers[ii] &&
1498 MptDeviceDriverHandlers[ii]->remove) {
1499 MptDeviceDriverHandlers[ii]->remove(pdev);
1503 /* Disable interrupts! */
1504 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1506 ioc->active = 0;
1507 synchronize_irq(pdev->irq);
1509 /* Clear any lingering interrupt */
1510 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1512 CHIPREG_READ32(&ioc->chip->IntStatus);
1514 mpt_adapter_dispose(ioc);
1516 pci_set_drvdata(pdev, NULL);
1519 /**************************************************************************
1520 * Power Management
1522 #ifdef CONFIG_PM
1523 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1525 * mpt_suspend - Fusion MPT base driver suspend routine.
1530 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1532 u32 device_state;
1533 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1535 device_state=pci_choose_state(pdev, state);
1537 printk(MYIOC_s_INFO_FMT
1538 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1539 ioc->name, pdev, pci_name(pdev), device_state);
1541 pci_save_state(pdev);
1543 /* put ioc into READY_STATE */
1544 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1545 printk(MYIOC_s_ERR_FMT
1546 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1549 /* disable interrupts */
1550 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1551 ioc->active = 0;
1553 /* Clear any lingering interrupt */
1554 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1556 pci_disable_device(pdev);
1557 pci_set_power_state(pdev, device_state);
1559 return 0;
1562 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1564 * mpt_resume - Fusion MPT base driver resume routine.
1569 mpt_resume(struct pci_dev *pdev)
1571 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1572 u32 device_state = pdev->current_state;
1573 int recovery_state;
1575 printk(MYIOC_s_INFO_FMT
1576 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1577 ioc->name, pdev, pci_name(pdev), device_state);
1579 pci_set_power_state(pdev, 0);
1580 pci_restore_state(pdev);
1581 pci_enable_device(pdev);
1583 /* enable interrupts */
1584 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1585 ioc->active = 1;
1587 printk(MYIOC_s_INFO_FMT
1588 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1589 ioc->name,
1590 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1591 CHIPREG_READ32(&ioc->chip->Doorbell));
1593 /* bring ioc to operational state */
1594 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1595 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1596 printk(MYIOC_s_INFO_FMT
1597 "pci-resume: Cannot recover, error:[%x]\n",
1598 ioc->name, recovery_state);
1599 } else {
1600 printk(MYIOC_s_INFO_FMT
1601 "pci-resume: success\n", ioc->name);
1604 return 0;
1606 #endif
1608 static int
1609 mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
1611 if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1612 ioc->bus_type != SPI) ||
1613 (MptDriverClass[index] == MPTFC_DRIVER &&
1614 ioc->bus_type != FC) ||
1615 (MptDriverClass[index] == MPTSAS_DRIVER &&
1616 ioc->bus_type != SAS))
1617 /* make sure we only call the relevant reset handler
1618 * for the bus */
1619 return 0;
1620 return (MptResetHandlers[index])(ioc, reset_phase);
1623 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1625 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1626 * @ioc: Pointer to MPT adapter structure
1627 * @reason: Event word / reason
1628 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1630 * This routine performs all the steps necessary to bring the IOC
1631 * to a OPERATIONAL state.
1633 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1634 * MPT adapter.
1636 * Returns:
1637 * 0 for success
1638 * -1 if failed to get board READY
1639 * -2 if READY but IOCFacts Failed
1640 * -3 if READY but PrimeIOCFifos Failed
1641 * -4 if READY but IOCInit Failed
1643 static int
1644 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1646 int hard_reset_done = 0;
1647 int alt_ioc_ready = 0;
1648 int hard;
1649 int rc=0;
1650 int ii;
1651 int handlers;
1652 int ret = 0;
1653 int reset_alt_ioc_active = 0;
1655 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1656 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1658 /* Disable reply interrupts (also blocks FreeQ) */
1659 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1660 ioc->active = 0;
1662 if (ioc->alt_ioc) {
1663 if (ioc->alt_ioc->active)
1664 reset_alt_ioc_active = 1;
1666 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1667 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1668 ioc->alt_ioc->active = 0;
1671 hard = 1;
1672 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1673 hard = 0;
1675 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1676 if (hard_reset_done == -4) {
1677 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1678 ioc->name);
1680 if (reset_alt_ioc_active && ioc->alt_ioc) {
1681 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1682 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1683 ioc->alt_ioc->name));
1684 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1685 ioc->alt_ioc->active = 1;
1688 } else {
1689 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1690 ioc->name);
1692 return -1;
1695 /* hard_reset_done = 0 if a soft reset was performed
1696 * and 1 if a hard reset was performed.
1698 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1699 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1700 alt_ioc_ready = 1;
1701 else
1702 printk(KERN_WARNING MYNAM
1703 ": alt-%s: Not ready WARNING!\n",
1704 ioc->alt_ioc->name);
1707 for (ii=0; ii<5; ii++) {
1708 /* Get IOC facts! Allow 5 retries */
1709 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1710 break;
1714 if (ii == 5) {
1715 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1716 ret = -2;
1717 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1718 MptDisplayIocCapabilities(ioc);
1721 if (alt_ioc_ready) {
1722 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1723 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1724 /* Retry - alt IOC was initialized once
1726 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1728 if (rc) {
1729 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1730 alt_ioc_ready = 0;
1731 reset_alt_ioc_active = 0;
1732 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1733 MptDisplayIocCapabilities(ioc->alt_ioc);
1737 /* Prime reply & request queues!
1738 * (mucho alloc's) Must be done prior to
1739 * init as upper addresses are needed for init.
1740 * If fails, continue with alt-ioc processing
1742 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1743 ret = -3;
1745 /* May need to check/upload firmware & data here!
1746 * If fails, continue with alt-ioc processing
1748 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1749 ret = -4;
1750 // NEW!
1751 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1752 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1753 ioc->alt_ioc->name, rc);
1754 alt_ioc_ready = 0;
1755 reset_alt_ioc_active = 0;
1758 if (alt_ioc_ready) {
1759 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1760 alt_ioc_ready = 0;
1761 reset_alt_ioc_active = 0;
1762 printk(KERN_WARNING MYNAM
1763 ": alt-%s: (%d) init failure WARNING!\n",
1764 ioc->alt_ioc->name, rc);
1768 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1769 if (ioc->upload_fw) {
1770 ddlprintk((MYIOC_s_INFO_FMT
1771 "firmware upload required!\n", ioc->name));
1773 /* Controller is not operational, cannot do upload
1775 if (ret == 0) {
1776 rc = mpt_do_upload(ioc, sleepFlag);
1777 if (rc == 0) {
1778 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1780 * Maintain only one pointer to FW memory
1781 * so there will not be two attempt to
1782 * downloadboot onboard dual function
1783 * chips (mpt_adapter_disable,
1784 * mpt_diag_reset)
1786 ioc->cached_fw = NULL;
1787 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1788 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1790 } else {
1791 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1792 ret = -5;
1798 if (ret == 0) {
1799 /* Enable! (reply interrupt) */
1800 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1801 ioc->active = 1;
1804 if (reset_alt_ioc_active && ioc->alt_ioc) {
1805 /* (re)Enable alt-IOC! (reply interrupt) */
1806 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1807 ioc->alt_ioc->name));
1808 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1809 ioc->alt_ioc->active = 1;
1812 /* Enable MPT base driver management of EventNotification
1813 * and EventAck handling.
1815 if ((ret == 0) && (!ioc->facts.EventState))
1816 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1818 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1819 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1821 /* Add additional "reason" check before call to GetLanConfigPages
1822 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1823 * recursive scenario; GetLanConfigPages times out, timer expired
1824 * routine calls HardResetHandler, which calls into here again,
1825 * and we try GetLanConfigPages again...
1827 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1828 if (ioc->bus_type == SAS) {
1830 /* clear persistency table */
1831 if(ioc->facts.IOCExceptions &
1832 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1833 ret = mptbase_sas_persist_operation(ioc,
1834 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1835 if(ret != 0)
1836 return -1;
1839 /* Find IM volumes
1841 mpt_findImVolumes(ioc);
1843 } else if (ioc->bus_type == FC) {
1845 * Pre-fetch FC port WWN and stuff...
1846 * (FCPortPage0_t stuff)
1848 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1849 (void) mptbase_GetFcPortPage0(ioc, ii);
1852 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1853 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1855 * Pre-fetch the ports LAN MAC address!
1856 * (LANPage1_t stuff)
1858 (void) GetLanConfigPages(ioc);
1859 #ifdef MPT_DEBUG
1861 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1862 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1863 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1865 #endif
1867 } else {
1868 /* Get NVRAM and adapter maximums from SPP 0 and 2
1870 mpt_GetScsiPortSettings(ioc, 0);
1872 /* Get version and length of SDP 1
1874 mpt_readScsiDevicePageHeaders(ioc, 0);
1876 /* Find IM volumes
1878 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1879 mpt_findImVolumes(ioc);
1881 /* Check, and possibly reset, the coalescing value
1883 mpt_read_ioc_pg_1(ioc);
1885 mpt_read_ioc_pg_4(ioc);
1888 GetIoUnitPage2(ioc);
1892 * Call each currently registered protocol IOC reset handler
1893 * with post-reset indication.
1894 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1895 * MptResetHandlers[] registered yet.
1897 if (hard_reset_done) {
1898 rc = handlers = 0;
1899 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1900 if ((ret == 0) && MptResetHandlers[ii]) {
1901 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1902 ioc->name, ii));
1903 rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
1904 handlers++;
1907 if (alt_ioc_ready && MptResetHandlers[ii]) {
1908 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1909 ioc->name, ioc->alt_ioc->name, ii));
1910 rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
1911 handlers++;
1914 /* FIXME? Examine results here? */
1917 return ret;
1920 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1922 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1923 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1924 * 929X, 1030 or 1035.
1925 * @ioc: Pointer to MPT adapter structure
1926 * @pdev: Pointer to (struct pci_dev) structure
1928 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1929 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1931 static void
1932 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1934 struct pci_dev *peer=NULL;
1935 unsigned int slot = PCI_SLOT(pdev->devfn);
1936 unsigned int func = PCI_FUNC(pdev->devfn);
1937 MPT_ADAPTER *ioc_srch;
1939 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1940 " searching for devfn match on %x or %x\n",
1941 ioc->name, pci_name(pdev), pdev->bus->number,
1942 pdev->devfn, func-1, func+1));
1944 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1945 if (!peer) {
1946 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1947 if (!peer)
1948 return;
1951 list_for_each_entry(ioc_srch, &ioc_list, list) {
1952 struct pci_dev *_pcidev = ioc_srch->pcidev;
1953 if (_pcidev == peer) {
1954 /* Paranoia checks */
1955 if (ioc->alt_ioc != NULL) {
1956 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1957 ioc->name, ioc->alt_ioc->name);
1958 break;
1959 } else if (ioc_srch->alt_ioc != NULL) {
1960 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1961 ioc_srch->name, ioc_srch->alt_ioc->name);
1962 break;
1964 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1965 ioc->name, ioc_srch->name));
1966 ioc_srch->alt_ioc = ioc;
1967 ioc->alt_ioc = ioc_srch;
1970 pci_dev_put(peer);
1973 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1975 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1976 * @this: Pointer to MPT adapter structure
1978 static void
1979 mpt_adapter_disable(MPT_ADAPTER *ioc)
1981 int sz;
1982 int ret;
1984 if (ioc->cached_fw != NULL) {
1985 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1986 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1987 printk(KERN_WARNING MYNAM
1988 ": firmware downloadboot failure (%d)!\n", ret);
1992 /* Disable adapter interrupts! */
1993 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1994 ioc->active = 0;
1995 /* Clear any lingering interrupt */
1996 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1998 if (ioc->alloc != NULL) {
1999 sz = ioc->alloc_sz;
2000 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
2001 ioc->name, ioc->alloc, ioc->alloc_sz));
2002 pci_free_consistent(ioc->pcidev, sz,
2003 ioc->alloc, ioc->alloc_dma);
2004 ioc->reply_frames = NULL;
2005 ioc->req_frames = NULL;
2006 ioc->alloc = NULL;
2007 ioc->alloc_total -= sz;
2010 if (ioc->sense_buf_pool != NULL) {
2011 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2012 pci_free_consistent(ioc->pcidev, sz,
2013 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2014 ioc->sense_buf_pool = NULL;
2015 ioc->alloc_total -= sz;
2018 if (ioc->events != NULL){
2019 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2020 kfree(ioc->events);
2021 ioc->events = NULL;
2022 ioc->alloc_total -= sz;
2025 if (ioc->cached_fw != NULL) {
2026 sz = ioc->facts.FWImageSize;
2027 pci_free_consistent(ioc->pcidev, sz,
2028 ioc->cached_fw, ioc->cached_fw_dma);
2029 ioc->cached_fw = NULL;
2030 ioc->alloc_total -= sz;
2033 kfree(ioc->spi_data.nvram);
2034 kfree(ioc->raid_data.pIocPg3);
2035 ioc->spi_data.nvram = NULL;
2036 ioc->raid_data.pIocPg3 = NULL;
2038 if (ioc->spi_data.pIocPg4 != NULL) {
2039 sz = ioc->spi_data.IocPg4Sz;
2040 pci_free_consistent(ioc->pcidev, sz,
2041 ioc->spi_data.pIocPg4,
2042 ioc->spi_data.IocPg4_dma);
2043 ioc->spi_data.pIocPg4 = NULL;
2044 ioc->alloc_total -= sz;
2047 if (ioc->ReqToChain != NULL) {
2048 kfree(ioc->ReqToChain);
2049 kfree(ioc->RequestNB);
2050 ioc->ReqToChain = NULL;
2053 kfree(ioc->ChainToChain);
2054 ioc->ChainToChain = NULL;
2056 if (ioc->HostPageBuffer != NULL) {
2057 if((ret = mpt_host_page_access_control(ioc,
2058 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2059 printk(KERN_ERR MYNAM
2060 ": %s: host page buffers free failed (%d)!\n",
2061 __FUNCTION__, ret);
2063 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2064 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2065 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2066 ioc->HostPageBuffer,
2067 ioc->HostPageBuffer_dma);
2068 ioc->HostPageBuffer = NULL;
2069 ioc->HostPageBuffer_sz = 0;
2070 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2074 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2076 * mpt_adapter_dispose - Free all resources associated with a MPT
2077 * adapter.
2078 * @ioc: Pointer to MPT adapter structure
2080 * This routine unregisters h/w resources and frees all alloc'd memory
2081 * associated with a MPT adapter structure.
2083 static void
2084 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2086 int sz_first, sz_last;
2088 if (ioc == NULL)
2089 return;
2091 sz_first = ioc->alloc_total;
2093 mpt_adapter_disable(ioc);
2095 if (ioc->pci_irq != -1) {
2096 free_irq(ioc->pci_irq, ioc);
2097 if (mpt_msi_enable)
2098 pci_disable_msi(ioc->pcidev);
2099 ioc->pci_irq = -1;
2102 if (ioc->memmap != NULL) {
2103 iounmap(ioc->memmap);
2104 ioc->memmap = NULL;
2107 #if defined(CONFIG_MTRR) && 0
2108 if (ioc->mtrr_reg > 0) {
2109 mtrr_del(ioc->mtrr_reg, 0, 0);
2110 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2112 #endif
2114 /* Zap the adapter lookup ptr! */
2115 list_del(&ioc->list);
2117 sz_last = ioc->alloc_total;
2118 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2119 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2121 if (ioc->alt_ioc)
2122 ioc->alt_ioc->alt_ioc = NULL;
2124 kfree(ioc);
2127 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2129 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2130 * @ioc: Pointer to MPT adapter structure
2132 static void
2133 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2135 int i = 0;
2137 printk(KERN_INFO "%s: ", ioc->name);
2138 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2139 printk("%s: ", ioc->prod_name+3);
2140 printk("Capabilities={");
2142 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2143 printk("Initiator");
2144 i++;
2147 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2148 printk("%sTarget", i ? "," : "");
2149 i++;
2152 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2153 printk("%sLAN", i ? "," : "");
2154 i++;
2157 #if 0
2159 * This would probably evoke more questions than it's worth
2161 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2162 printk("%sLogBusAddr", i ? "," : "");
2163 i++;
2165 #endif
2167 printk("}\n");
2170 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2172 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2173 * @ioc: Pointer to MPT_ADAPTER structure
2174 * @force: Force hard KickStart of IOC
2175 * @sleepFlag: Specifies whether the process can sleep
2177 * Returns:
2178 * 1 - DIAG reset and READY
2179 * 0 - READY initially OR soft reset and READY
2180 * -1 - Any failure on KickStart
2181 * -2 - Msg Unit Reset Failed
2182 * -3 - IO Unit Reset Failed
2183 * -4 - IOC owned by a PEER
2185 static int
2186 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2188 u32 ioc_state;
2189 int statefault = 0;
2190 int cntdn;
2191 int hard_reset_done = 0;
2192 int r;
2193 int ii;
2194 int whoinit;
2196 /* Get current [raw] IOC state */
2197 ioc_state = mpt_GetIocState(ioc, 0);
2198 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2201 * Check to see if IOC got left/stuck in doorbell handshake
2202 * grip of death. If so, hard reset the IOC.
2204 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2205 statefault = 1;
2206 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2207 ioc->name);
2210 /* Is it already READY? */
2211 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2212 return 0;
2215 * Check to see if IOC is in FAULT state.
2217 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2218 statefault = 2;
2219 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2220 ioc->name);
2221 printk(KERN_WARNING " FAULT code = %04xh\n",
2222 ioc_state & MPI_DOORBELL_DATA_MASK);
2226 * Hmmm... Did it get left operational?
2228 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2229 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2230 ioc->name));
2232 /* Check WhoInit.
2233 * If PCI Peer, exit.
2234 * Else, if no fault conditions are present, issue a MessageUnitReset
2235 * Else, fall through to KickStart case
2237 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2238 dinitprintk((KERN_INFO MYNAM
2239 ": whoinit 0x%x statefault %d force %d\n",
2240 whoinit, statefault, force));
2241 if (whoinit == MPI_WHOINIT_PCI_PEER)
2242 return -4;
2243 else {
2244 if ((statefault == 0 ) && (force == 0)) {
2245 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2246 return 0;
2248 statefault = 3;
2252 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2253 if (hard_reset_done < 0)
2254 return -1;
2257 * Loop here waiting for IOC to come READY.
2259 ii = 0;
2260 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2262 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2263 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2265 * BIOS or previous driver load left IOC in OP state.
2266 * Reset messaging FIFOs.
2268 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2269 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2270 return -2;
2272 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2274 * Something is wrong. Try to get IOC back
2275 * to a known state.
2277 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2278 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2279 return -3;
2283 ii++; cntdn--;
2284 if (!cntdn) {
2285 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2286 ioc->name, (int)((ii+5)/HZ));
2287 return -ETIME;
2290 if (sleepFlag == CAN_SLEEP) {
2291 msleep_interruptible(1);
2292 } else {
2293 mdelay (1); /* 1 msec delay */
2298 if (statefault < 3) {
2299 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2300 ioc->name,
2301 statefault==1 ? "stuck handshake" : "IOC FAULT");
2304 return hard_reset_done;
2307 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2309 * mpt_GetIocState - Get the current state of a MPT adapter.
2310 * @ioc: Pointer to MPT_ADAPTER structure
2311 * @cooked: Request raw or cooked IOC state
2313 * Returns all IOC Doorbell register bits if cooked==0, else just the
2314 * Doorbell bits in MPI_IOC_STATE_MASK.
2317 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2319 u32 s, sc;
2321 /* Get! */
2322 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2323 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2324 sc = s & MPI_IOC_STATE_MASK;
2326 /* Save! */
2327 ioc->last_state = sc;
2329 return cooked ? sc : s;
2332 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2334 * GetIocFacts - Send IOCFacts request to MPT adapter.
2335 * @ioc: Pointer to MPT_ADAPTER structure
2336 * @sleepFlag: Specifies whether the process can sleep
2337 * @reason: If recovery, only update facts.
2339 * Returns 0 for success, non-zero for failure.
2341 static int
2342 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2344 IOCFacts_t get_facts;
2345 IOCFactsReply_t *facts;
2346 int r;
2347 int req_sz;
2348 int reply_sz;
2349 int sz;
2350 u32 status, vv;
2351 u8 shiftFactor=1;
2353 /* IOC *must* NOT be in RESET state! */
2354 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2355 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2356 ioc->name,
2357 ioc->last_state );
2358 return -44;
2361 facts = &ioc->facts;
2363 /* Destination (reply area)... */
2364 reply_sz = sizeof(*facts);
2365 memset(facts, 0, reply_sz);
2367 /* Request area (get_facts on the stack right now!) */
2368 req_sz = sizeof(get_facts);
2369 memset(&get_facts, 0, req_sz);
2371 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2372 /* Assert: All other get_facts fields are zero! */
2374 dinitprintk((MYIOC_s_INFO_FMT
2375 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2376 ioc->name, req_sz, reply_sz));
2378 /* No non-zero fields in the get_facts request are greater than
2379 * 1 byte in size, so we can just fire it off as is.
2381 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2382 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2383 if (r != 0)
2384 return r;
2387 * Now byte swap (GRRR) the necessary fields before any further
2388 * inspection of reply contents.
2390 * But need to do some sanity checks on MsgLength (byte) field
2391 * to make sure we don't zero IOC's req_sz!
2393 /* Did we get a valid reply? */
2394 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2395 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2397 * If not been here, done that, save off first WhoInit value
2399 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2400 ioc->FirstWhoInit = facts->WhoInit;
2403 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2404 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2405 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2406 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2407 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2408 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2409 /* CHECKME! IOCStatus, IOCLogInfo */
2411 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2412 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2415 * FC f/w version changed between 1.1 and 1.2
2416 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2417 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2419 if (facts->MsgVersion < 0x0102) {
2421 * Handle old FC f/w style, convert to new...
2423 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2424 facts->FWVersion.Word =
2425 ((oldv<<12) & 0xFF000000) |
2426 ((oldv<<8) & 0x000FFF00);
2427 } else
2428 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2430 facts->ProductID = le16_to_cpu(facts->ProductID);
2431 facts->CurrentHostMfaHighAddr =
2432 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2433 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2434 facts->CurrentSenseBufferHighAddr =
2435 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2436 facts->CurReplyFrameSize =
2437 le16_to_cpu(facts->CurReplyFrameSize);
2438 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2441 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2442 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2443 * to 14 in MPI-1.01.0x.
2445 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2446 facts->MsgVersion > 0x0100) {
2447 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2450 sz = facts->FWImageSize;
2451 if ( sz & 0x01 )
2452 sz += 1;
2453 if ( sz & 0x02 )
2454 sz += 2;
2455 facts->FWImageSize = sz;
2457 if (!facts->RequestFrameSize) {
2458 /* Something is wrong! */
2459 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2460 ioc->name);
2461 return -55;
2464 r = sz = facts->BlockSize;
2465 vv = ((63 / (sz * 4)) + 1) & 0x03;
2466 ioc->NB_for_64_byte_frame = vv;
2467 while ( sz )
2469 shiftFactor++;
2470 sz = sz >> 1;
2472 ioc->NBShiftFactor = shiftFactor;
2473 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2474 ioc->name, vv, shiftFactor, r));
2476 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2478 * Set values for this IOC's request & reply frame sizes,
2479 * and request & reply queue depths...
2481 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2482 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2483 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2484 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2486 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2487 ioc->name, ioc->reply_sz, ioc->reply_depth));
2488 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2489 ioc->name, ioc->req_sz, ioc->req_depth));
2491 /* Get port facts! */
2492 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2493 return r;
2495 } else {
2496 printk(MYIOC_s_ERR_FMT
2497 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2498 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2499 RequestFrameSize)/sizeof(u32)));
2500 return -66;
2503 return 0;
2506 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2508 * GetPortFacts - Send PortFacts request to MPT adapter.
2509 * @ioc: Pointer to MPT_ADAPTER structure
2510 * @portnum: Port number
2511 * @sleepFlag: Specifies whether the process can sleep
2513 * Returns 0 for success, non-zero for failure.
2515 static int
2516 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2518 PortFacts_t get_pfacts;
2519 PortFactsReply_t *pfacts;
2520 int ii;
2521 int req_sz;
2522 int reply_sz;
2524 /* IOC *must* NOT be in RESET state! */
2525 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2526 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2527 ioc->name,
2528 ioc->last_state );
2529 return -4;
2532 pfacts = &ioc->pfacts[portnum];
2534 /* Destination (reply area)... */
2535 reply_sz = sizeof(*pfacts);
2536 memset(pfacts, 0, reply_sz);
2538 /* Request area (get_pfacts on the stack right now!) */
2539 req_sz = sizeof(get_pfacts);
2540 memset(&get_pfacts, 0, req_sz);
2542 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2543 get_pfacts.PortNumber = portnum;
2544 /* Assert: All other get_pfacts fields are zero! */
2546 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2547 ioc->name, portnum));
2549 /* No non-zero fields in the get_pfacts request are greater than
2550 * 1 byte in size, so we can just fire it off as is.
2552 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2553 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2554 if (ii != 0)
2555 return ii;
2557 /* Did we get a valid reply? */
2559 /* Now byte swap the necessary fields in the response. */
2560 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2561 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2562 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2563 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2564 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2565 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2566 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2567 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2568 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2570 return 0;
2573 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2575 * SendIocInit - Send IOCInit request to MPT adapter.
2576 * @ioc: Pointer to MPT_ADAPTER structure
2577 * @sleepFlag: Specifies whether the process can sleep
2579 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2581 * Returns 0 for success, non-zero for failure.
2583 static int
2584 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2586 IOCInit_t ioc_init;
2587 MPIDefaultReply_t init_reply;
2588 u32 state;
2589 int r;
2590 int count;
2591 int cntdn;
2593 memset(&ioc_init, 0, sizeof(ioc_init));
2594 memset(&init_reply, 0, sizeof(init_reply));
2596 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2597 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2599 /* If we are in a recovery mode and we uploaded the FW image,
2600 * then this pointer is not NULL. Skip the upload a second time.
2601 * Set this flag if cached_fw set for either IOC.
2603 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2604 ioc->upload_fw = 1;
2605 else
2606 ioc->upload_fw = 0;
2607 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2608 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2610 if(ioc->bus_type == SAS)
2611 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2612 else if(ioc->bus_type == FC)
2613 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2614 else
2615 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2616 ioc_init.MaxBuses = MPT_MAX_BUS;
2617 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2618 ioc->name, ioc->facts.MsgVersion));
2619 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2620 // set MsgVersion and HeaderVersion host driver was built with
2621 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2622 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2624 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2625 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2626 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2627 return -99;
2629 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2631 if (sizeof(dma_addr_t) == sizeof(u64)) {
2632 /* Save the upper 32-bits of the request
2633 * (reply) and sense buffers.
2635 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2636 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2637 } else {
2638 /* Force 32-bit addressing */
2639 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2640 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2643 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2644 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2645 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2646 ioc->facts.MaxBuses = ioc_init.MaxBuses;
2648 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2649 ioc->name, &ioc_init));
2651 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2652 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2653 if (r != 0) {
2654 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
2655 return r;
2658 /* No need to byte swap the multibyte fields in the reply
2659 * since we don't even look at it's contents.
2662 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2663 ioc->name, &ioc_init));
2665 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2666 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
2667 return r;
2670 /* YIKES! SUPER IMPORTANT!!!
2671 * Poll IocState until _OPERATIONAL while IOC is doing
2672 * LoopInit and TargetDiscovery!
2674 count = 0;
2675 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2676 state = mpt_GetIocState(ioc, 1);
2677 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2678 if (sleepFlag == CAN_SLEEP) {
2679 msleep_interruptible(1);
2680 } else {
2681 mdelay(1);
2684 if (!cntdn) {
2685 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2686 ioc->name, (int)((count+5)/HZ));
2687 return -9;
2690 state = mpt_GetIocState(ioc, 1);
2691 count++;
2693 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2694 ioc->name, count));
2696 return r;
2699 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2701 * SendPortEnable - Send PortEnable request to MPT adapter port.
2702 * @ioc: Pointer to MPT_ADAPTER structure
2703 * @portnum: Port number to enable
2704 * @sleepFlag: Specifies whether the process can sleep
2706 * Send PortEnable to bring IOC to OPERATIONAL state.
2708 * Returns 0 for success, non-zero for failure.
2710 static int
2711 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2713 PortEnable_t port_enable;
2714 MPIDefaultReply_t reply_buf;
2715 int rc;
2716 int req_sz;
2717 int reply_sz;
2719 /* Destination... */
2720 reply_sz = sizeof(MPIDefaultReply_t);
2721 memset(&reply_buf, 0, reply_sz);
2723 req_sz = sizeof(PortEnable_t);
2724 memset(&port_enable, 0, req_sz);
2726 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2727 port_enable.PortNumber = portnum;
2728 /* port_enable.ChainOffset = 0; */
2729 /* port_enable.MsgFlags = 0; */
2730 /* port_enable.MsgContext = 0; */
2732 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2733 ioc->name, portnum, &port_enable));
2735 /* RAID FW may take a long time to enable
2737 if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2738 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2739 (ioc->bus_type == SAS)) {
2740 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2741 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2742 300 /*seconds*/, sleepFlag);
2743 } else {
2744 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2745 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2746 30 /*seconds*/, sleepFlag);
2748 return rc;
2752 * ioc: Pointer to MPT_ADAPTER structure
2753 * size - total FW bytes
2755 void
2756 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2758 if (ioc->cached_fw)
2759 return; /* use already allocated memory */
2760 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2761 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2762 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2763 } else {
2764 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2765 ioc->alloc_total += size;
2769 * If alt_img is NULL, delete from ioc structure.
2770 * Else, delete a secondary image in same format.
2772 void
2773 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2775 int sz;
2777 sz = ioc->facts.FWImageSize;
2778 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2779 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2780 pci_free_consistent(ioc->pcidev, sz,
2781 ioc->cached_fw, ioc->cached_fw_dma);
2782 ioc->cached_fw = NULL;
2784 return;
2788 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2790 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2791 * @ioc: Pointer to MPT_ADAPTER structure
2792 * @sleepFlag: Specifies whether the process can sleep
2794 * Returns 0 for success, >0 for handshake failure
2795 * <0 for fw upload failure.
2797 * Remark: If bound IOC and a successful FWUpload was performed
2798 * on the bound IOC, the second image is discarded
2799 * and memory is free'd. Both channels must upload to prevent
2800 * IOC from running in degraded mode.
2802 static int
2803 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2805 u8 request[ioc->req_sz];
2806 u8 reply[sizeof(FWUploadReply_t)];
2807 FWUpload_t *prequest;
2808 FWUploadReply_t *preply;
2809 FWUploadTCSGE_t *ptcsge;
2810 int sgeoffset;
2811 u32 flagsLength;
2812 int ii, sz, reply_sz;
2813 int cmdStatus;
2815 /* If the image size is 0, we are done.
2817 if ((sz = ioc->facts.FWImageSize) == 0)
2818 return 0;
2820 mpt_alloc_fw_memory(ioc, sz);
2822 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2823 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2825 if (ioc->cached_fw == NULL) {
2826 /* Major Failure.
2828 return -ENOMEM;
2831 prequest = (FWUpload_t *)&request;
2832 preply = (FWUploadReply_t *)&reply;
2834 /* Destination... */
2835 memset(prequest, 0, ioc->req_sz);
2837 reply_sz = sizeof(reply);
2838 memset(preply, 0, reply_sz);
2840 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2841 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2843 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2844 ptcsge->DetailsLength = 12;
2845 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2846 ptcsge->ImageSize = cpu_to_le32(sz);
2848 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2850 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2851 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2853 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2854 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2855 prequest, sgeoffset));
2856 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2858 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2859 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2861 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2863 cmdStatus = -EFAULT;
2864 if (ii == 0) {
2865 /* Handshake transfer was complete and successful.
2866 * Check the Reply Frame.
2868 int status, transfer_sz;
2869 status = le16_to_cpu(preply->IOCStatus);
2870 if (status == MPI_IOCSTATUS_SUCCESS) {
2871 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2872 if (transfer_sz == sz)
2873 cmdStatus = 0;
2876 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2877 ioc->name, cmdStatus));
2880 if (cmdStatus) {
2882 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2883 ioc->name));
2884 mpt_free_fw_memory(ioc);
2887 return cmdStatus;
2890 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2892 * mpt_downloadboot - DownloadBoot code
2893 * @ioc: Pointer to MPT_ADAPTER structure
2894 * @flag: Specify which part of IOC memory is to be uploaded.
2895 * @sleepFlag: Specifies whether the process can sleep
2897 * FwDownloadBoot requires Programmed IO access.
2899 * Returns 0 for success
2900 * -1 FW Image size is 0
2901 * -2 No valid cached_fw Pointer
2902 * <0 for fw upload failure.
2904 static int
2905 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2907 MpiExtImageHeader_t *pExtImage;
2908 u32 fwSize;
2909 u32 diag0val;
2910 int count;
2911 u32 *ptrFw;
2912 u32 diagRwData;
2913 u32 nextImage;
2914 u32 load_addr;
2915 u32 ioc_state=0;
2917 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2918 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2920 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2921 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2922 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2923 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2924 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2925 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2927 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2929 /* wait 1 msec */
2930 if (sleepFlag == CAN_SLEEP) {
2931 msleep_interruptible(1);
2932 } else {
2933 mdelay (1);
2936 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2937 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2939 for (count = 0; count < 30; count ++) {
2940 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2941 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2942 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2943 ioc->name, count));
2944 break;
2946 /* wait .1 sec */
2947 if (sleepFlag == CAN_SLEEP) {
2948 msleep_interruptible (100);
2949 } else {
2950 mdelay (100);
2954 if ( count == 30 ) {
2955 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2956 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2957 ioc->name, diag0val));
2958 return -3;
2961 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2962 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2963 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2964 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2965 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2966 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2968 /* Set the DiagRwEn and Disable ARM bits */
2969 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2971 fwSize = (pFwHeader->ImageSize + 3)/4;
2972 ptrFw = (u32 *) pFwHeader;
2974 /* Write the LoadStartAddress to the DiagRw Address Register
2975 * using Programmed IO
2977 if (ioc->errata_flag_1064)
2978 pci_enable_io_access(ioc->pcidev);
2980 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2981 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2982 ioc->name, pFwHeader->LoadStartAddress));
2984 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2985 ioc->name, fwSize*4, ptrFw));
2986 while (fwSize--) {
2987 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2990 nextImage = pFwHeader->NextImageHeaderOffset;
2991 while (nextImage) {
2992 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2994 load_addr = pExtImage->LoadStartAddress;
2996 fwSize = (pExtImage->ImageSize + 3) >> 2;
2997 ptrFw = (u32 *)pExtImage;
2999 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3000 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3001 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3003 while (fwSize--) {
3004 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3006 nextImage = pExtImage->NextImageHeaderOffset;
3009 /* Write the IopResetVectorRegAddr */
3010 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3011 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3013 /* Write the IopResetVectorValue */
3014 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3015 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3017 /* Clear the internal flash bad bit - autoincrementing register,
3018 * so must do two writes.
3020 if (ioc->bus_type == SPI) {
3022 * 1030 and 1035 H/W errata, workaround to access
3023 * the ClearFlashBadSignatureBit
3025 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3026 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3027 diagRwData |= 0x40000000;
3028 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3029 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3031 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3032 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3033 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3034 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3036 /* wait 1 msec */
3037 if (sleepFlag == CAN_SLEEP) {
3038 msleep_interruptible (1);
3039 } else {
3040 mdelay (1);
3044 if (ioc->errata_flag_1064)
3045 pci_disable_io_access(ioc->pcidev);
3047 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3048 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3049 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3050 ioc->name, diag0val));
3051 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3052 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3053 ioc->name, diag0val));
3054 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3056 /* Write 0xFF to reset the sequencer */
3057 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3059 if (ioc->bus_type == SAS) {
3060 ioc_state = mpt_GetIocState(ioc, 0);
3061 if ( (GetIocFacts(ioc, sleepFlag,
3062 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3063 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3064 ioc->name, ioc_state));
3065 return -EFAULT;
3069 for (count=0; count<HZ*20; count++) {
3070 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3071 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3072 ioc->name, count, ioc_state));
3073 if (ioc->bus_type == SAS) {
3074 return 0;
3076 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3077 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3078 ioc->name));
3079 return -EFAULT;
3081 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3082 ioc->name));
3083 return 0;
3085 if (sleepFlag == CAN_SLEEP) {
3086 msleep_interruptible (10);
3087 } else {
3088 mdelay (10);
3091 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3092 ioc->name, ioc_state));
3093 return -EFAULT;
3096 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3098 * KickStart - Perform hard reset of MPT adapter.
3099 * @ioc: Pointer to MPT_ADAPTER structure
3100 * @force: Force hard reset
3101 * @sleepFlag: Specifies whether the process can sleep
3103 * This routine places MPT adapter in diagnostic mode via the
3104 * WriteSequence register, and then performs a hard reset of adapter
3105 * via the Diagnostic register.
3107 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3108 * or NO_SLEEP (interrupt thread, use mdelay)
3109 * force - 1 if doorbell active, board fault state
3110 * board operational, IOC_RECOVERY or
3111 * IOC_BRINGUP and there is an alt_ioc.
3112 * 0 else
3114 * Returns:
3115 * 1 - hard reset, READY
3116 * 0 - no reset due to History bit, READY
3117 * -1 - no reset due to History bit but not READY
3118 * OR reset but failed to come READY
3119 * -2 - no reset, could not enter DIAG mode
3120 * -3 - reset but bad FW bit
3122 static int
3123 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3125 int hard_reset_done = 0;
3126 u32 ioc_state=0;
3127 int cnt,cntdn;
3129 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3130 if (ioc->bus_type == SPI) {
3131 /* Always issue a Msg Unit Reset first. This will clear some
3132 * SCSI bus hang conditions.
3134 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3136 if (sleepFlag == CAN_SLEEP) {
3137 msleep_interruptible (1000);
3138 } else {
3139 mdelay (1000);
3143 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3144 if (hard_reset_done < 0)
3145 return hard_reset_done;
3147 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3148 ioc->name));
3150 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3151 for (cnt=0; cnt<cntdn; cnt++) {
3152 ioc_state = mpt_GetIocState(ioc, 1);
3153 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3154 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3155 ioc->name, cnt));
3156 return hard_reset_done;
3158 if (sleepFlag == CAN_SLEEP) {
3159 msleep_interruptible (10);
3160 } else {
3161 mdelay (10);
3165 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3166 ioc->name, ioc_state);
3167 return -1;
3170 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3172 * mpt_diag_reset - Perform hard reset of the adapter.
3173 * @ioc: Pointer to MPT_ADAPTER structure
3174 * @ignore: Set if to honor and clear to ignore
3175 * the reset history bit
3176 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3177 * else set to NO_SLEEP (use mdelay instead)
3179 * This routine places the adapter in diagnostic mode via the
3180 * WriteSequence register and then performs a hard reset of adapter
3181 * via the Diagnostic register. Adapter should be in ready state
3182 * upon successful completion.
3184 * Returns: 1 hard reset successful
3185 * 0 no reset performed because reset history bit set
3186 * -2 enabling diagnostic mode failed
3187 * -3 diagnostic reset failed
3189 static int
3190 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3192 u32 diag0val;
3193 u32 doorbell;
3194 int hard_reset_done = 0;
3195 int count = 0;
3196 #ifdef MPT_DEBUG
3197 u32 diag1val = 0;
3198 #endif
3200 /* Clear any existing interrupts */
3201 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3203 /* Use "Diagnostic reset" method! (only thing available!) */
3204 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3206 #ifdef MPT_DEBUG
3207 if (ioc->alt_ioc)
3208 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3209 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3210 ioc->name, diag0val, diag1val));
3211 #endif
3213 /* Do the reset if we are told to ignore the reset history
3214 * or if the reset history is 0
3216 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3217 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3218 /* Write magic sequence to WriteSequence register
3219 * Loop until in diagnostic mode
3221 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3222 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3223 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3224 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3225 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3226 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3228 /* wait 100 msec */
3229 if (sleepFlag == CAN_SLEEP) {
3230 msleep_interruptible (100);
3231 } else {
3232 mdelay (100);
3235 count++;
3236 if (count > 20) {
3237 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3238 ioc->name, diag0val);
3239 return -2;
3243 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3245 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3246 ioc->name, diag0val));
3249 #ifdef MPT_DEBUG
3250 if (ioc->alt_ioc)
3251 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3252 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3253 ioc->name, diag0val, diag1val));
3254 #endif
3256 * Disable the ARM (Bug fix)
3259 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3260 mdelay(1);
3263 * Now hit the reset bit in the Diagnostic register
3264 * (THE BIG HAMMER!) (Clears DRWE bit).
3266 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3267 hard_reset_done = 1;
3268 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3269 ioc->name));
3272 * Call each currently registered protocol IOC reset handler
3273 * with pre-reset indication.
3274 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3275 * MptResetHandlers[] registered yet.
3278 int ii;
3279 int r = 0;
3281 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3282 if (MptResetHandlers[ii]) {
3283 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3284 ioc->name, ii));
3285 r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
3286 if (ioc->alt_ioc) {
3287 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3288 ioc->name, ioc->alt_ioc->name, ii));
3289 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3293 /* FIXME? Examine results here? */
3296 if (ioc->cached_fw) {
3297 /* If the DownloadBoot operation fails, the
3298 * IOC will be left unusable. This is a fatal error
3299 * case. _diag_reset will return < 0
3301 for (count = 0; count < 30; count ++) {
3302 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3303 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3304 break;
3307 /* wait 1 sec */
3308 if (sleepFlag == CAN_SLEEP) {
3309 msleep_interruptible (1000);
3310 } else {
3311 mdelay (1000);
3314 if ((count = mpt_downloadboot(ioc,
3315 (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
3316 printk(KERN_WARNING MYNAM
3317 ": firmware downloadboot failure (%d)!\n", count);
3320 } else {
3321 /* Wait for FW to reload and for board
3322 * to go to the READY state.
3323 * Maximum wait is 60 seconds.
3324 * If fail, no error will check again
3325 * with calling program.
3327 for (count = 0; count < 60; count ++) {
3328 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3329 doorbell &= MPI_IOC_STATE_MASK;
3331 if (doorbell == MPI_IOC_STATE_READY) {
3332 break;
3335 /* wait 1 sec */
3336 if (sleepFlag == CAN_SLEEP) {
3337 msleep_interruptible (1000);
3338 } else {
3339 mdelay (1000);
3345 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3346 #ifdef MPT_DEBUG
3347 if (ioc->alt_ioc)
3348 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3349 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3350 ioc->name, diag0val, diag1val));
3351 #endif
3353 /* Clear RESET_HISTORY bit! Place board in the
3354 * diagnostic mode to update the diag register.
3356 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3357 count = 0;
3358 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3359 /* Write magic sequence to WriteSequence register
3360 * Loop until in diagnostic mode
3362 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3363 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3364 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3365 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3366 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3367 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3369 /* wait 100 msec */
3370 if (sleepFlag == CAN_SLEEP) {
3371 msleep_interruptible (100);
3372 } else {
3373 mdelay (100);
3376 count++;
3377 if (count > 20) {
3378 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3379 ioc->name, diag0val);
3380 break;
3382 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3384 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3385 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3386 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3387 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3388 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3389 ioc->name);
3392 /* Disable Diagnostic Mode
3394 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3396 /* Check FW reload status flags.
3398 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3399 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3400 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3401 ioc->name, diag0val);
3402 return -3;
3405 #ifdef MPT_DEBUG
3406 if (ioc->alt_ioc)
3407 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3408 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3409 ioc->name, diag0val, diag1val));
3410 #endif
3413 * Reset flag that says we've enabled event notification
3415 ioc->facts.EventState = 0;
3417 if (ioc->alt_ioc)
3418 ioc->alt_ioc->facts.EventState = 0;
3420 return hard_reset_done;
3423 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3425 * SendIocReset - Send IOCReset request to MPT adapter.
3426 * @ioc: Pointer to MPT_ADAPTER structure
3427 * @reset_type: reset type, expected values are
3428 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3430 * Send IOCReset request to the MPT adapter.
3432 * Returns 0 for success, non-zero for failure.
3434 static int
3435 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3437 int r;
3438 u32 state;
3439 int cntdn, count;
3441 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3442 ioc->name, reset_type));
3443 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3444 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3445 return r;
3447 /* FW ACK'd request, wait for READY state
3449 count = 0;
3450 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3452 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3453 cntdn--;
3454 count++;
3455 if (!cntdn) {
3456 if (sleepFlag != CAN_SLEEP)
3457 count *= 10;
3459 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3460 ioc->name, (int)((count+5)/HZ));
3461 return -ETIME;
3464 if (sleepFlag == CAN_SLEEP) {
3465 msleep_interruptible(1);
3466 } else {
3467 mdelay (1); /* 1 msec delay */
3471 /* TODO!
3472 * Cleanup all event stuff for this IOC; re-issue EventNotification
3473 * request if needed.
3475 if (ioc->facts.Function)
3476 ioc->facts.EventState = 0;
3478 return 0;
3481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3483 * initChainBuffers - Allocate memory for and initialize
3484 * chain buffers, chain buffer control arrays and spinlock.
3485 * @hd: Pointer to MPT_SCSI_HOST structure
3486 * @init: If set, initialize the spin lock.
3488 static int
3489 initChainBuffers(MPT_ADAPTER *ioc)
3491 u8 *mem;
3492 int sz, ii, num_chain;
3493 int scale, num_sge, numSGE;
3495 /* ReqToChain size must equal the req_depth
3496 * index = req_idx
3498 if (ioc->ReqToChain == NULL) {
3499 sz = ioc->req_depth * sizeof(int);
3500 mem = kmalloc(sz, GFP_ATOMIC);
3501 if (mem == NULL)
3502 return -1;
3504 ioc->ReqToChain = (int *) mem;
3505 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3506 ioc->name, mem, sz));
3507 mem = kmalloc(sz, GFP_ATOMIC);
3508 if (mem == NULL)
3509 return -1;
3511 ioc->RequestNB = (int *) mem;
3512 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3513 ioc->name, mem, sz));
3515 for (ii = 0; ii < ioc->req_depth; ii++) {
3516 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3519 /* ChainToChain size must equal the total number
3520 * of chain buffers to be allocated.
3521 * index = chain_idx
3523 * Calculate the number of chain buffers needed(plus 1) per I/O
3524 * then multiply the the maximum number of simultaneous cmds
3526 * num_sge = num sge in request frame + last chain buffer
3527 * scale = num sge per chain buffer if no chain element
3529 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3530 if (sizeof(dma_addr_t) == sizeof(u64))
3531 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3532 else
3533 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3535 if (sizeof(dma_addr_t) == sizeof(u64)) {
3536 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3537 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3538 } else {
3539 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3540 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3542 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3543 ioc->name, num_sge, numSGE));
3545 if ( numSGE > MPT_SCSI_SG_DEPTH )
3546 numSGE = MPT_SCSI_SG_DEPTH;
3548 num_chain = 1;
3549 while (numSGE - num_sge > 0) {
3550 num_chain++;
3551 num_sge += (scale - 1);
3553 num_chain++;
3555 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3556 ioc->name, numSGE, num_sge, num_chain));
3558 if (ioc->bus_type == SPI)
3559 num_chain *= MPT_SCSI_CAN_QUEUE;
3560 else
3561 num_chain *= MPT_FC_CAN_QUEUE;
3563 ioc->num_chain = num_chain;
3565 sz = num_chain * sizeof(int);
3566 if (ioc->ChainToChain == NULL) {
3567 mem = kmalloc(sz, GFP_ATOMIC);
3568 if (mem == NULL)
3569 return -1;
3571 ioc->ChainToChain = (int *) mem;
3572 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3573 ioc->name, mem, sz));
3574 } else {
3575 mem = (u8 *) ioc->ChainToChain;
3577 memset(mem, 0xFF, sz);
3578 return num_chain;
3581 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3583 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3584 * @ioc: Pointer to MPT_ADAPTER structure
3586 * This routine allocates memory for the MPT reply and request frame
3587 * pools (if necessary), and primes the IOC reply FIFO with
3588 * reply frames.
3590 * Returns 0 for success, non-zero for failure.
3592 static int
3593 PrimeIocFifos(MPT_ADAPTER *ioc)
3595 MPT_FRAME_HDR *mf;
3596 unsigned long flags;
3597 dma_addr_t alloc_dma;
3598 u8 *mem;
3599 int i, reply_sz, sz, total_size, num_chain;
3601 /* Prime reply FIFO... */
3603 if (ioc->reply_frames == NULL) {
3604 if ( (num_chain = initChainBuffers(ioc)) < 0)
3605 return -1;
3607 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3608 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3609 ioc->name, ioc->reply_sz, ioc->reply_depth));
3610 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3611 ioc->name, reply_sz, reply_sz));
3613 sz = (ioc->req_sz * ioc->req_depth);
3614 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3615 ioc->name, ioc->req_sz, ioc->req_depth));
3616 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3617 ioc->name, sz, sz));
3618 total_size += sz;
3620 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3621 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3622 ioc->name, ioc->req_sz, num_chain));
3623 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3624 ioc->name, sz, sz, num_chain));
3626 total_size += sz;
3627 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3628 if (mem == NULL) {
3629 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3630 ioc->name);
3631 goto out_fail;
3634 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3635 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3637 memset(mem, 0, total_size);
3638 ioc->alloc_total += total_size;
3639 ioc->alloc = mem;
3640 ioc->alloc_dma = alloc_dma;
3641 ioc->alloc_sz = total_size;
3642 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3643 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3645 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3646 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3648 alloc_dma += reply_sz;
3649 mem += reply_sz;
3651 /* Request FIFO - WE manage this! */
3653 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3654 ioc->req_frames_dma = alloc_dma;
3656 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3657 ioc->name, mem, (void *)(ulong)alloc_dma));
3659 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3661 #if defined(CONFIG_MTRR) && 0
3663 * Enable Write Combining MTRR for IOC's memory region.
3664 * (at least as much as we can; "size and base must be
3665 * multiples of 4 kiB"
3667 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3669 MTRR_TYPE_WRCOMB, 1);
3670 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3671 ioc->name, ioc->req_frames_dma, sz));
3672 #endif
3674 for (i = 0; i < ioc->req_depth; i++) {
3675 alloc_dma += ioc->req_sz;
3676 mem += ioc->req_sz;
3679 ioc->ChainBuffer = mem;
3680 ioc->ChainBufferDMA = alloc_dma;
3682 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3683 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3685 /* Initialize the free chain Q.
3688 INIT_LIST_HEAD(&ioc->FreeChainQ);
3690 /* Post the chain buffers to the FreeChainQ.
3692 mem = (u8 *)ioc->ChainBuffer;
3693 for (i=0; i < num_chain; i++) {
3694 mf = (MPT_FRAME_HDR *) mem;
3695 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3696 mem += ioc->req_sz;
3699 /* Initialize Request frames linked list
3701 alloc_dma = ioc->req_frames_dma;
3702 mem = (u8 *) ioc->req_frames;
3704 spin_lock_irqsave(&ioc->FreeQlock, flags);
3705 INIT_LIST_HEAD(&ioc->FreeQ);
3706 for (i = 0; i < ioc->req_depth; i++) {
3707 mf = (MPT_FRAME_HDR *) mem;
3709 /* Queue REQUESTs *internally*! */
3710 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3712 mem += ioc->req_sz;
3714 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3716 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3717 ioc->sense_buf_pool =
3718 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3719 if (ioc->sense_buf_pool == NULL) {
3720 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3721 ioc->name);
3722 goto out_fail;
3725 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3726 ioc->alloc_total += sz;
3727 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3728 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3732 /* Post Reply frames to FIFO
3734 alloc_dma = ioc->alloc_dma;
3735 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3736 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3738 for (i = 0; i < ioc->reply_depth; i++) {
3739 /* Write each address to the IOC! */
3740 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3741 alloc_dma += ioc->reply_sz;
3744 return 0;
3746 out_fail:
3747 if (ioc->alloc != NULL) {
3748 sz = ioc->alloc_sz;
3749 pci_free_consistent(ioc->pcidev,
3751 ioc->alloc, ioc->alloc_dma);
3752 ioc->reply_frames = NULL;
3753 ioc->req_frames = NULL;
3754 ioc->alloc_total -= sz;
3756 if (ioc->sense_buf_pool != NULL) {
3757 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3758 pci_free_consistent(ioc->pcidev,
3760 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3761 ioc->sense_buf_pool = NULL;
3763 return -1;
3766 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3768 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3769 * from IOC via doorbell handshake method.
3770 * @ioc: Pointer to MPT_ADAPTER structure
3771 * @reqBytes: Size of the request in bytes
3772 * @req: Pointer to MPT request frame
3773 * @replyBytes: Expected size of the reply in bytes
3774 * @u16reply: Pointer to area where reply should be written
3775 * @maxwait: Max wait time for a reply (in seconds)
3776 * @sleepFlag: Specifies whether the process can sleep
3778 * NOTES: It is the callers responsibility to byte-swap fields in the
3779 * request which are greater than 1 byte in size. It is also the
3780 * callers responsibility to byte-swap response fields which are
3781 * greater than 1 byte in size.
3783 * Returns 0 for success, non-zero for failure.
3785 static int
3786 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3787 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3789 MPIDefaultReply_t *mptReply;
3790 int failcnt = 0;
3791 int t;
3794 * Get ready to cache a handshake reply
3796 ioc->hs_reply_idx = 0;
3797 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3798 mptReply->MsgLength = 0;
3801 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3802 * then tell IOC that we want to handshake a request of N words.
3803 * (WRITE u32val to Doorbell reg).
3805 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3806 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3807 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3808 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3811 * Wait for IOC's doorbell handshake int
3813 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3814 failcnt++;
3816 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3817 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3819 /* Read doorbell and check for active bit */
3820 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3821 return -1;
3824 * Clear doorbell int (WRITE 0 to IntStatus reg),
3825 * then wait for IOC to ACKnowledge that it's ready for
3826 * our handshake request.
3828 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3829 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3830 failcnt++;
3832 if (!failcnt) {
3833 int ii;
3834 u8 *req_as_bytes = (u8 *) req;
3837 * Stuff request words via doorbell handshake,
3838 * with ACK from IOC for each.
3840 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3841 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3842 (req_as_bytes[(ii*4) + 1] << 8) |
3843 (req_as_bytes[(ii*4) + 2] << 16) |
3844 (req_as_bytes[(ii*4) + 3] << 24));
3846 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3847 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3848 failcnt++;
3851 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3852 DBG_DUMP_REQUEST_FRAME_HDR(req)
3854 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3855 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3858 * Wait for completion of doorbell handshake reply from the IOC
3860 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3861 failcnt++;
3863 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3864 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3867 * Copy out the cached reply...
3869 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3870 u16reply[ii] = ioc->hs_reply[ii];
3871 } else {
3872 return -99;
3875 return -failcnt;
3878 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3880 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3881 * in it's IntStatus register.
3882 * @ioc: Pointer to MPT_ADAPTER structure
3883 * @howlong: How long to wait (in seconds)
3884 * @sleepFlag: Specifies whether the process can sleep
3886 * This routine waits (up to ~2 seconds max) for IOC doorbell
3887 * handshake ACKnowledge.
3889 * Returns a negative value on failure, else wait loop count.
3891 static int
3892 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3894 int cntdn;
3895 int count = 0;
3896 u32 intstat=0;
3898 cntdn = 1000 * howlong;
3900 if (sleepFlag == CAN_SLEEP) {
3901 while (--cntdn) {
3902 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3903 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3904 break;
3905 msleep_interruptible (1);
3906 count++;
3908 } else {
3909 while (--cntdn) {
3910 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3911 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3912 break;
3913 mdelay (1);
3914 count++;
3918 if (cntdn) {
3919 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3920 ioc->name, count));
3921 return count;
3924 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3925 ioc->name, count, intstat);
3926 return -1;
3929 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3931 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3932 * in it's IntStatus register.
3933 * @ioc: Pointer to MPT_ADAPTER structure
3934 * @howlong: How long to wait (in seconds)
3935 * @sleepFlag: Specifies whether the process can sleep
3937 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3939 * Returns a negative value on failure, else wait loop count.
3941 static int
3942 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3944 int cntdn;
3945 int count = 0;
3946 u32 intstat=0;
3948 cntdn = 1000 * howlong;
3949 if (sleepFlag == CAN_SLEEP) {
3950 while (--cntdn) {
3951 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3952 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3953 break;
3954 msleep_interruptible(1);
3955 count++;
3957 } else {
3958 while (--cntdn) {
3959 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3960 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3961 break;
3962 mdelay(1);
3963 count++;
3967 if (cntdn) {
3968 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3969 ioc->name, count, howlong));
3970 return count;
3973 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3974 ioc->name, count, intstat);
3975 return -1;
3978 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3980 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3981 * @ioc: Pointer to MPT_ADAPTER structure
3982 * @howlong: How long to wait (in seconds)
3983 * @sleepFlag: Specifies whether the process can sleep
3985 * This routine polls the IOC for a handshake reply, 16 bits at a time.
3986 * Reply is cached to IOC private area large enough to hold a maximum
3987 * of 128 bytes of reply data.
3989 * Returns a negative value on failure, else size of reply in WORDS.
3991 static int
3992 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3994 int u16cnt = 0;
3995 int failcnt = 0;
3996 int t;
3997 u16 *hs_reply = ioc->hs_reply;
3998 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3999 u16 hword;
4001 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4004 * Get first two u16's so we can look at IOC's intended reply MsgLength
4006 u16cnt=0;
4007 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4008 failcnt++;
4009 } else {
4010 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4011 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4012 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4013 failcnt++;
4014 else {
4015 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4016 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4020 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4021 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4022 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4025 * If no error (and IOC said MsgLength is > 0), piece together
4026 * reply 16 bits at a time.
4028 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4029 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4030 failcnt++;
4031 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4032 /* don't overflow our IOC hs_reply[] buffer! */
4033 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4034 hs_reply[u16cnt] = hword;
4035 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4038 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4039 failcnt++;
4040 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4042 if (failcnt) {
4043 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4044 ioc->name);
4045 return -failcnt;
4047 #if 0
4048 else if (u16cnt != (2 * mptReply->MsgLength)) {
4049 return -101;
4051 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4052 return -102;
4054 #endif
4056 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4057 DBG_DUMP_REPLY_FRAME(mptReply)
4059 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4060 ioc->name, t, u16cnt/2));
4061 return u16cnt/2;
4064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4066 * GetLanConfigPages - Fetch LANConfig pages.
4067 * @ioc: Pointer to MPT_ADAPTER structure
4069 * Return: 0 for success
4070 * -ENOMEM if no memory available
4071 * -EPERM if not allowed due to ISR context
4072 * -EAGAIN if no msg frames currently available
4073 * -EFAULT for non-successful reply or no reply (timeout)
4075 static int
4076 GetLanConfigPages(MPT_ADAPTER *ioc)
4078 ConfigPageHeader_t hdr;
4079 CONFIGPARMS cfg;
4080 LANPage0_t *ppage0_alloc;
4081 dma_addr_t page0_dma;
4082 LANPage1_t *ppage1_alloc;
4083 dma_addr_t page1_dma;
4084 int rc = 0;
4085 int data_sz;
4086 int copy_sz;
4088 /* Get LAN Page 0 header */
4089 hdr.PageVersion = 0;
4090 hdr.PageLength = 0;
4091 hdr.PageNumber = 0;
4092 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4093 cfg.cfghdr.hdr = &hdr;
4094 cfg.physAddr = -1;
4095 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4096 cfg.dir = 0;
4097 cfg.pageAddr = 0;
4098 cfg.timeout = 0;
4100 if ((rc = mpt_config(ioc, &cfg)) != 0)
4101 return rc;
4103 if (hdr.PageLength > 0) {
4104 data_sz = hdr.PageLength * 4;
4105 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4106 rc = -ENOMEM;
4107 if (ppage0_alloc) {
4108 memset((u8 *)ppage0_alloc, 0, data_sz);
4109 cfg.physAddr = page0_dma;
4110 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4112 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4113 /* save the data */
4114 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4115 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4119 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4121 /* FIXME!
4122 * Normalize endianness of structure data,
4123 * by byte-swapping all > 1 byte fields!
4128 if (rc)
4129 return rc;
4132 /* Get LAN Page 1 header */
4133 hdr.PageVersion = 0;
4134 hdr.PageLength = 0;
4135 hdr.PageNumber = 1;
4136 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4137 cfg.cfghdr.hdr = &hdr;
4138 cfg.physAddr = -1;
4139 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4140 cfg.dir = 0;
4141 cfg.pageAddr = 0;
4143 if ((rc = mpt_config(ioc, &cfg)) != 0)
4144 return rc;
4146 if (hdr.PageLength == 0)
4147 return 0;
4149 data_sz = hdr.PageLength * 4;
4150 rc = -ENOMEM;
4151 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4152 if (ppage1_alloc) {
4153 memset((u8 *)ppage1_alloc, 0, data_sz);
4154 cfg.physAddr = page1_dma;
4155 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4157 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4158 /* save the data */
4159 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4160 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4163 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4165 /* FIXME!
4166 * Normalize endianness of structure data,
4167 * by byte-swapping all > 1 byte fields!
4172 return rc;
4175 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4177 * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
4178 * @ioc: Pointer to MPT_ADAPTER structure
4179 * @portnum: IOC Port number
4181 * Return: 0 for success
4182 * -ENOMEM if no memory available
4183 * -EPERM if not allowed due to ISR context
4184 * -EAGAIN if no msg frames currently available
4185 * -EFAULT for non-successful reply or no reply (timeout)
4188 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4190 ConfigPageHeader_t hdr;
4191 CONFIGPARMS cfg;
4192 FCPortPage0_t *ppage0_alloc;
4193 FCPortPage0_t *pp0dest;
4194 dma_addr_t page0_dma;
4195 int data_sz;
4196 int copy_sz;
4197 int rc;
4198 int count = 400;
4201 /* Get FCPort Page 0 header */
4202 hdr.PageVersion = 0;
4203 hdr.PageLength = 0;
4204 hdr.PageNumber = 0;
4205 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4206 cfg.cfghdr.hdr = &hdr;
4207 cfg.physAddr = -1;
4208 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4209 cfg.dir = 0;
4210 cfg.pageAddr = portnum;
4211 cfg.timeout = 0;
4213 if ((rc = mpt_config(ioc, &cfg)) != 0)
4214 return rc;
4216 if (hdr.PageLength == 0)
4217 return 0;
4219 data_sz = hdr.PageLength * 4;
4220 rc = -ENOMEM;
4221 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4222 if (ppage0_alloc) {
4224 try_again:
4225 memset((u8 *)ppage0_alloc, 0, data_sz);
4226 cfg.physAddr = page0_dma;
4227 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4229 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4230 /* save the data */
4231 pp0dest = &ioc->fc_port_page0[portnum];
4232 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4233 memcpy(pp0dest, ppage0_alloc, copy_sz);
4236 * Normalize endianness of structure data,
4237 * by byte-swapping all > 1 byte fields!
4239 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4240 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4241 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4242 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4243 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4244 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4245 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4246 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4247 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4248 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4249 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4250 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4251 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4252 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4253 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4254 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4257 * if still doing discovery,
4258 * hang loose a while until finished
4260 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
4261 if (count-- > 0) {
4262 msleep_interruptible(100);
4263 goto try_again;
4265 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
4266 " complete.\n",
4267 ioc->name);
4271 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4274 return rc;
4277 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4279 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4280 * @ioc: Pointer to MPT_ADAPTER structure
4281 * @sas_address: 64bit SAS Address for operation.
4282 * @target_id: specified target for operation
4283 * @bus: specified bus for operation
4284 * @persist_opcode: see below
4286 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4287 * devices not currently present.
4288 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4290 * NOTE: Don't use not this function during interrupt time.
4292 * Returns: 0 for success, non-zero error
4295 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4297 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4299 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4300 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4301 MPT_FRAME_HDR *mf = NULL;
4302 MPIHeader_t *mpi_hdr;
4305 /* insure garbage is not sent to fw */
4306 switch(persist_opcode) {
4308 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4309 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4310 break;
4312 default:
4313 return -1;
4314 break;
4317 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4319 /* Get a MF for this command.
4321 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4322 printk("%s: no msg frames!\n",__FUNCTION__);
4323 return -1;
4326 mpi_hdr = (MPIHeader_t *) mf;
4327 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4328 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4329 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4330 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4331 sasIoUnitCntrReq->Operation = persist_opcode;
4333 init_timer(&ioc->persist_timer);
4334 ioc->persist_timer.data = (unsigned long) ioc;
4335 ioc->persist_timer.function = mpt_timer_expired;
4336 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4337 ioc->persist_wait_done=0;
4338 add_timer(&ioc->persist_timer);
4339 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4340 wait_event(mpt_waitq, ioc->persist_wait_done);
4342 sasIoUnitCntrReply =
4343 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4344 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4345 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4346 __FUNCTION__,
4347 sasIoUnitCntrReply->IOCStatus,
4348 sasIoUnitCntrReply->IOCLogInfo);
4349 return -1;
4352 printk("%s: success\n",__FUNCTION__);
4353 return 0;
4356 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4358 static void
4359 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4360 MpiEventDataRaid_t * pRaidEventData)
4362 int volume;
4363 int reason;
4364 int disk;
4365 int status;
4366 int flags;
4367 int state;
4369 volume = pRaidEventData->VolumeID;
4370 reason = pRaidEventData->ReasonCode;
4371 disk = pRaidEventData->PhysDiskNum;
4372 status = le32_to_cpu(pRaidEventData->SettingsStatus);
4373 flags = (status >> 0) & 0xff;
4374 state = (status >> 8) & 0xff;
4376 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4377 return;
4380 if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4381 reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4382 (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4383 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4384 ioc->name, disk);
4385 } else {
4386 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4387 ioc->name, volume);
4390 switch(reason) {
4391 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4392 printk(MYIOC_s_INFO_FMT " volume has been created\n",
4393 ioc->name);
4394 break;
4396 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4398 printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
4399 ioc->name);
4400 break;
4402 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4403 printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
4404 ioc->name);
4405 break;
4407 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4408 printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
4409 ioc->name,
4410 state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4411 ? "optimal"
4412 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4413 ? "degraded"
4414 : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4415 ? "failed"
4416 : "state unknown",
4417 flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4418 ? ", enabled" : "",
4419 flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4420 ? ", quiesced" : "",
4421 flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4422 ? ", resync in progress" : "" );
4423 break;
4425 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4426 printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
4427 ioc->name, disk);
4428 break;
4430 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4431 printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
4432 ioc->name);
4433 break;
4435 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4436 printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
4437 ioc->name);
4438 break;
4440 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4441 printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
4442 ioc->name);
4443 break;
4445 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4446 printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
4447 ioc->name,
4448 state == MPI_PHYSDISK0_STATUS_ONLINE
4449 ? "online"
4450 : state == MPI_PHYSDISK0_STATUS_MISSING
4451 ? "missing"
4452 : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4453 ? "not compatible"
4454 : state == MPI_PHYSDISK0_STATUS_FAILED
4455 ? "failed"
4456 : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4457 ? "initializing"
4458 : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4459 ? "offline requested"
4460 : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4461 ? "failed requested"
4462 : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4463 ? "offline"
4464 : "state unknown",
4465 flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4466 ? ", out of sync" : "",
4467 flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4468 ? ", quiesced" : "" );
4469 break;
4471 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4472 printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
4473 ioc->name, disk);
4474 break;
4476 case MPI_EVENT_RAID_RC_SMART_DATA:
4477 printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4478 ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4479 break;
4481 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4482 printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
4483 ioc->name, disk);
4484 break;
4488 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4490 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4491 * @ioc: Pointer to MPT_ADAPTER structure
4493 * Returns: 0 for success
4494 * -ENOMEM if no memory available
4495 * -EPERM if not allowed due to ISR context
4496 * -EAGAIN if no msg frames currently available
4497 * -EFAULT for non-successful reply or no reply (timeout)
4499 static int
4500 GetIoUnitPage2(MPT_ADAPTER *ioc)
4502 ConfigPageHeader_t hdr;
4503 CONFIGPARMS cfg;
4504 IOUnitPage2_t *ppage_alloc;
4505 dma_addr_t page_dma;
4506 int data_sz;
4507 int rc;
4509 /* Get the page header */
4510 hdr.PageVersion = 0;
4511 hdr.PageLength = 0;
4512 hdr.PageNumber = 2;
4513 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4514 cfg.cfghdr.hdr = &hdr;
4515 cfg.physAddr = -1;
4516 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4517 cfg.dir = 0;
4518 cfg.pageAddr = 0;
4519 cfg.timeout = 0;
4521 if ((rc = mpt_config(ioc, &cfg)) != 0)
4522 return rc;
4524 if (hdr.PageLength == 0)
4525 return 0;
4527 /* Read the config page */
4528 data_sz = hdr.PageLength * 4;
4529 rc = -ENOMEM;
4530 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4531 if (ppage_alloc) {
4532 memset((u8 *)ppage_alloc, 0, data_sz);
4533 cfg.physAddr = page_dma;
4534 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4536 /* If Good, save data */
4537 if ((rc = mpt_config(ioc, &cfg)) == 0)
4538 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4540 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4543 return rc;
4546 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4547 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4548 * @ioc: Pointer to a Adapter Strucutre
4549 * @portnum: IOC port number
4551 * Return: -EFAULT if read of config page header fails
4552 * or if no nvram
4553 * If read of SCSI Port Page 0 fails,
4554 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4555 * Adapter settings: async, narrow
4556 * Return 1
4557 * If read of SCSI Port Page 2 fails,
4558 * Adapter settings valid
4559 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4560 * Return 1
4561 * Else
4562 * Both valid
4563 * Return 0
4564 * CHECK - what type of locking mechanisms should be used????
4566 static int
4567 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4569 u8 *pbuf;
4570 dma_addr_t buf_dma;
4571 CONFIGPARMS cfg;
4572 ConfigPageHeader_t header;
4573 int ii;
4574 int data, rc = 0;
4576 /* Allocate memory
4578 if (!ioc->spi_data.nvram) {
4579 int sz;
4580 u8 *mem;
4581 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4582 mem = kmalloc(sz, GFP_ATOMIC);
4583 if (mem == NULL)
4584 return -EFAULT;
4586 ioc->spi_data.nvram = (int *) mem;
4588 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4589 ioc->name, ioc->spi_data.nvram, sz));
4592 /* Invalidate NVRAM information
4594 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4595 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4598 /* Read SPP0 header, allocate memory, then read page.
4600 header.PageVersion = 0;
4601 header.PageLength = 0;
4602 header.PageNumber = 0;
4603 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4604 cfg.cfghdr.hdr = &header;
4605 cfg.physAddr = -1;
4606 cfg.pageAddr = portnum;
4607 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4608 cfg.dir = 0;
4609 cfg.timeout = 0; /* use default */
4610 if (mpt_config(ioc, &cfg) != 0)
4611 return -EFAULT;
4613 if (header.PageLength > 0) {
4614 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4615 if (pbuf) {
4616 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4617 cfg.physAddr = buf_dma;
4618 if (mpt_config(ioc, &cfg) != 0) {
4619 ioc->spi_data.maxBusWidth = MPT_NARROW;
4620 ioc->spi_data.maxSyncOffset = 0;
4621 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4622 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4623 rc = 1;
4624 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4625 ioc->name, ioc->spi_data.minSyncFactor));
4626 } else {
4627 /* Save the Port Page 0 data
4629 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4630 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4631 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4633 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4634 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4635 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4636 ioc->name, pPP0->Capabilities));
4638 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4639 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4640 if (data) {
4641 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4642 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4643 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4644 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4645 ioc->name, ioc->spi_data.minSyncFactor));
4646 } else {
4647 ioc->spi_data.maxSyncOffset = 0;
4648 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4651 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4653 /* Update the minSyncFactor based on bus type.
4655 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4656 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4658 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4659 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4660 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4661 ioc->name, ioc->spi_data.minSyncFactor));
4665 if (pbuf) {
4666 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4671 /* SCSI Port Page 2 - Read the header then the page.
4673 header.PageVersion = 0;
4674 header.PageLength = 0;
4675 header.PageNumber = 2;
4676 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4677 cfg.cfghdr.hdr = &header;
4678 cfg.physAddr = -1;
4679 cfg.pageAddr = portnum;
4680 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4681 cfg.dir = 0;
4682 if (mpt_config(ioc, &cfg) != 0)
4683 return -EFAULT;
4685 if (header.PageLength > 0) {
4686 /* Allocate memory and read SCSI Port Page 2
4688 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4689 if (pbuf) {
4690 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4691 cfg.physAddr = buf_dma;
4692 if (mpt_config(ioc, &cfg) != 0) {
4693 /* Nvram data is left with INVALID mark
4695 rc = 1;
4696 } else {
4697 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4698 MpiDeviceInfo_t *pdevice = NULL;
4701 * Save "Set to Avoid SCSI Bus Resets" flag
4703 ioc->spi_data.bus_reset =
4704 (le32_to_cpu(pPP2->PortFlags) &
4705 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4706 0 : 1 ;
4708 /* Save the Port Page 2 data
4709 * (reformat into a 32bit quantity)
4711 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4712 ioc->spi_data.PortFlags = data;
4713 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4714 pdevice = &pPP2->DeviceSettings[ii];
4715 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4716 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4717 ioc->spi_data.nvram[ii] = data;
4721 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4725 /* Update Adapter limits with those from NVRAM
4726 * Comment: Don't need to do this. Target performance
4727 * parameters will never exceed the adapters limits.
4730 return rc;
4733 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4734 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4735 * @ioc: Pointer to a Adapter Strucutre
4736 * @portnum: IOC port number
4738 * Return: -EFAULT if read of config page header fails
4739 * or 0 if success.
4741 static int
4742 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4744 CONFIGPARMS cfg;
4745 ConfigPageHeader_t header;
4747 /* Read the SCSI Device Page 1 header
4749 header.PageVersion = 0;
4750 header.PageLength = 0;
4751 header.PageNumber = 1;
4752 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4753 cfg.cfghdr.hdr = &header;
4754 cfg.physAddr = -1;
4755 cfg.pageAddr = portnum;
4756 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4757 cfg.dir = 0;
4758 cfg.timeout = 0;
4759 if (mpt_config(ioc, &cfg) != 0)
4760 return -EFAULT;
4762 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4763 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4765 header.PageVersion = 0;
4766 header.PageLength = 0;
4767 header.PageNumber = 0;
4768 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4769 if (mpt_config(ioc, &cfg) != 0)
4770 return -EFAULT;
4772 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4773 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4775 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4776 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4778 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4779 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4780 return 0;
4783 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4785 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4786 * @ioc: Pointer to a Adapter Strucutre
4787 * @portnum: IOC port number
4789 * Return:
4790 * 0 on success
4791 * -EFAULT if read of config page header fails or data pointer not NULL
4792 * -ENOMEM if pci_alloc failed
4795 mpt_findImVolumes(MPT_ADAPTER *ioc)
4797 IOCPage2_t *pIoc2;
4798 u8 *mem;
4799 ConfigPageIoc2RaidVol_t *pIocRv;
4800 dma_addr_t ioc2_dma;
4801 CONFIGPARMS cfg;
4802 ConfigPageHeader_t header;
4803 int jj;
4804 int rc = 0;
4805 int iocpage2sz;
4806 u8 nVols, nPhys;
4807 u8 vid, vbus, vioc;
4809 /* Read IOCP2 header then the page.
4811 header.PageVersion = 0;
4812 header.PageLength = 0;
4813 header.PageNumber = 2;
4814 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4815 cfg.cfghdr.hdr = &header;
4816 cfg.physAddr = -1;
4817 cfg.pageAddr = 0;
4818 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4819 cfg.dir = 0;
4820 cfg.timeout = 0;
4821 if (mpt_config(ioc, &cfg) != 0)
4822 return -EFAULT;
4824 if (header.PageLength == 0)
4825 return -EFAULT;
4827 iocpage2sz = header.PageLength * 4;
4828 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4829 if (!pIoc2)
4830 return -ENOMEM;
4832 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4833 cfg.physAddr = ioc2_dma;
4834 if (mpt_config(ioc, &cfg) != 0)
4835 goto done_and_free;
4837 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4838 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4839 if (mem) {
4840 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4841 } else {
4842 goto done_and_free;
4845 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4847 /* Identify RAID Volume Id's */
4848 nVols = pIoc2->NumActiveVolumes;
4849 if ( nVols == 0) {
4850 /* No RAID Volume.
4852 goto done_and_free;
4853 } else {
4854 /* At least 1 RAID Volume
4856 pIocRv = pIoc2->RaidVolume;
4857 ioc->raid_data.isRaid = 0;
4858 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4859 vid = pIocRv->VolumeID;
4860 vbus = pIocRv->VolumeBus;
4861 vioc = pIocRv->VolumeIOC;
4863 /* find the match
4865 if (vbus == 0) {
4866 ioc->raid_data.isRaid |= (1 << vid);
4867 } else {
4868 /* Error! Always bus 0
4874 /* Identify Hidden Physical Disk Id's */
4875 nPhys = pIoc2->NumActivePhysDisks;
4876 if (nPhys == 0) {
4877 /* No physical disks.
4879 } else {
4880 mpt_read_ioc_pg_3(ioc);
4883 done_and_free:
4884 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4886 return rc;
4889 static int
4890 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4892 IOCPage3_t *pIoc3;
4893 u8 *mem;
4894 CONFIGPARMS cfg;
4895 ConfigPageHeader_t header;
4896 dma_addr_t ioc3_dma;
4897 int iocpage3sz = 0;
4899 /* Free the old page
4901 kfree(ioc->raid_data.pIocPg3);
4902 ioc->raid_data.pIocPg3 = NULL;
4904 /* There is at least one physical disk.
4905 * Read and save IOC Page 3
4907 header.PageVersion = 0;
4908 header.PageLength = 0;
4909 header.PageNumber = 3;
4910 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4911 cfg.cfghdr.hdr = &header;
4912 cfg.physAddr = -1;
4913 cfg.pageAddr = 0;
4914 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4915 cfg.dir = 0;
4916 cfg.timeout = 0;
4917 if (mpt_config(ioc, &cfg) != 0)
4918 return 0;
4920 if (header.PageLength == 0)
4921 return 0;
4923 /* Read Header good, alloc memory
4925 iocpage3sz = header.PageLength * 4;
4926 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4927 if (!pIoc3)
4928 return 0;
4930 /* Read the Page and save the data
4931 * into malloc'd memory.
4933 cfg.physAddr = ioc3_dma;
4934 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4935 if (mpt_config(ioc, &cfg) == 0) {
4936 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4937 if (mem) {
4938 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4939 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4943 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4945 return 0;
4948 static void
4949 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4951 IOCPage4_t *pIoc4;
4952 CONFIGPARMS cfg;
4953 ConfigPageHeader_t header;
4954 dma_addr_t ioc4_dma;
4955 int iocpage4sz;
4957 /* Read and save IOC Page 4
4959 header.PageVersion = 0;
4960 header.PageLength = 0;
4961 header.PageNumber = 4;
4962 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4963 cfg.cfghdr.hdr = &header;
4964 cfg.physAddr = -1;
4965 cfg.pageAddr = 0;
4966 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4967 cfg.dir = 0;
4968 cfg.timeout = 0;
4969 if (mpt_config(ioc, &cfg) != 0)
4970 return;
4972 if (header.PageLength == 0)
4973 return;
4975 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4976 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4977 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4978 if (!pIoc4)
4979 return;
4980 } else {
4981 ioc4_dma = ioc->spi_data.IocPg4_dma;
4982 iocpage4sz = ioc->spi_data.IocPg4Sz;
4985 /* Read the Page into dma memory.
4987 cfg.physAddr = ioc4_dma;
4988 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4989 if (mpt_config(ioc, &cfg) == 0) {
4990 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4991 ioc->spi_data.IocPg4_dma = ioc4_dma;
4992 ioc->spi_data.IocPg4Sz = iocpage4sz;
4993 } else {
4994 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4995 ioc->spi_data.pIocPg4 = NULL;
4999 static void
5000 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
5002 IOCPage1_t *pIoc1;
5003 CONFIGPARMS cfg;
5004 ConfigPageHeader_t header;
5005 dma_addr_t ioc1_dma;
5006 int iocpage1sz = 0;
5007 u32 tmp;
5009 /* Check the Coalescing Timeout in IOC Page 1
5011 header.PageVersion = 0;
5012 header.PageLength = 0;
5013 header.PageNumber = 1;
5014 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5015 cfg.cfghdr.hdr = &header;
5016 cfg.physAddr = -1;
5017 cfg.pageAddr = 0;
5018 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5019 cfg.dir = 0;
5020 cfg.timeout = 0;
5021 if (mpt_config(ioc, &cfg) != 0)
5022 return;
5024 if (header.PageLength == 0)
5025 return;
5027 /* Read Header good, alloc memory
5029 iocpage1sz = header.PageLength * 4;
5030 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5031 if (!pIoc1)
5032 return;
5034 /* Read the Page and check coalescing timeout
5036 cfg.physAddr = ioc1_dma;
5037 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5038 if (mpt_config(ioc, &cfg) == 0) {
5040 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5041 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5042 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5044 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
5045 ioc->name, tmp));
5047 if (tmp > MPT_COALESCING_TIMEOUT) {
5048 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5050 /* Write NVRAM and current
5052 cfg.dir = 1;
5053 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5054 if (mpt_config(ioc, &cfg) == 0) {
5055 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
5056 ioc->name, MPT_COALESCING_TIMEOUT));
5058 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5059 if (mpt_config(ioc, &cfg) == 0) {
5060 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
5061 ioc->name, MPT_COALESCING_TIMEOUT));
5062 } else {
5063 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
5064 ioc->name));
5067 } else {
5068 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
5069 ioc->name));
5073 } else {
5074 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5078 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5080 return;
5083 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5085 * SendEventNotification - Send EventNotification (on or off) request
5086 * to MPT adapter.
5087 * @ioc: Pointer to MPT_ADAPTER structure
5088 * @EvSwitch: Event switch flags
5090 static int
5091 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5093 EventNotification_t *evnp;
5095 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5096 if (evnp == NULL) {
5097 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5098 ioc->name));
5099 return 0;
5101 memset(evnp, 0, sizeof(*evnp));
5103 devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5105 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5106 evnp->ChainOffset = 0;
5107 evnp->MsgFlags = 0;
5108 evnp->Switch = EvSwitch;
5110 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5112 return 0;
5115 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5117 * SendEventAck - Send EventAck request to MPT adapter.
5118 * @ioc: Pointer to MPT_ADAPTER structure
5119 * @evnp: Pointer to original EventNotification request
5121 static int
5122 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5124 EventAck_t *pAck;
5126 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5127 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
5128 "request frame for Event=%x EventContext=%x EventData=%x!\n",
5129 ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
5130 le32_to_cpu(evnp->Data[0]));
5131 return -1;
5133 memset(pAck, 0, sizeof(*pAck));
5135 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5137 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5138 pAck->ChainOffset = 0;
5139 pAck->MsgFlags = 0;
5140 pAck->Event = evnp->Event;
5141 pAck->EventContext = evnp->EventContext;
5143 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5145 return 0;
5148 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5150 * mpt_config - Generic function to issue config message
5151 * @ioc - Pointer to an adapter structure
5152 * @cfg - Pointer to a configuration structure. Struct contains
5153 * action, page address, direction, physical address
5154 * and pointer to a configuration page header
5155 * Page header is updated.
5157 * Returns 0 for success
5158 * -EPERM if not allowed due to ISR context
5159 * -EAGAIN if no msg frames currently available
5160 * -EFAULT for non-successful reply or no reply (timeout)
5163 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5165 Config_t *pReq;
5166 ConfigExtendedPageHeader_t *pExtHdr = NULL;
5167 MPT_FRAME_HDR *mf;
5168 unsigned long flags;
5169 int ii, rc;
5170 int flagsLength;
5171 int in_isr;
5173 /* Prevent calling wait_event() (below), if caller happens
5174 * to be in ISR context, because that is fatal!
5176 in_isr = in_interrupt();
5177 if (in_isr) {
5178 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5179 ioc->name));
5180 return -EPERM;
5183 /* Get and Populate a free Frame
5185 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5186 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5187 ioc->name));
5188 return -EAGAIN;
5190 pReq = (Config_t *)mf;
5191 pReq->Action = pCfg->action;
5192 pReq->Reserved = 0;
5193 pReq->ChainOffset = 0;
5194 pReq->Function = MPI_FUNCTION_CONFIG;
5196 /* Assume page type is not extended and clear "reserved" fields. */
5197 pReq->ExtPageLength = 0;
5198 pReq->ExtPageType = 0;
5199 pReq->MsgFlags = 0;
5201 for (ii=0; ii < 8; ii++)
5202 pReq->Reserved2[ii] = 0;
5204 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5205 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5206 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5207 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5209 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5210 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5211 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5212 pReq->ExtPageType = pExtHdr->ExtPageType;
5213 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5215 /* Page Length must be treated as a reserved field for the extended header. */
5216 pReq->Header.PageLength = 0;
5219 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5221 /* Add a SGE to the config request.
5223 if (pCfg->dir)
5224 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5225 else
5226 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5228 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5229 flagsLength |= pExtHdr->ExtPageLength * 4;
5231 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5232 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5234 else {
5235 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5237 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5238 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5241 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5243 /* Append pCfg pointer to end of mf
5245 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5247 /* Initalize the timer
5249 init_timer(&pCfg->timer);
5250 pCfg->timer.data = (unsigned long) ioc;
5251 pCfg->timer.function = mpt_timer_expired;
5252 pCfg->wait_done = 0;
5254 /* Set the timer; ensure 10 second minimum */
5255 if (pCfg->timeout < 10)
5256 pCfg->timer.expires = jiffies + HZ*10;
5257 else
5258 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5260 /* Add to end of Q, set timer and then issue this command */
5261 spin_lock_irqsave(&ioc->FreeQlock, flags);
5262 list_add_tail(&pCfg->linkage, &ioc->configQ);
5263 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5265 add_timer(&pCfg->timer);
5266 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5267 wait_event(mpt_waitq, pCfg->wait_done);
5269 /* mf has been freed - do not access */
5271 rc = pCfg->status;
5273 return rc;
5276 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5278 * mpt_timer_expired - Call back for timer process.
5279 * Used only internal config functionality.
5280 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5282 static void
5283 mpt_timer_expired(unsigned long data)
5285 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5287 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5289 /* Perform a FW reload */
5290 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5291 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5293 /* No more processing.
5294 * Hard reset clean-up will wake up
5295 * process and free all resources.
5297 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5299 return;
5302 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5304 * mpt_ioc_reset - Base cleanup for hard reset
5305 * @ioc: Pointer to the adapter structure
5306 * @reset_phase: Indicates pre- or post-reset functionality
5308 * Remark: Free's resources with internally generated commands.
5310 static int
5311 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5313 CONFIGPARMS *pCfg;
5314 unsigned long flags;
5316 dprintk((KERN_WARNING MYNAM
5317 ": IOC %s_reset routed to MPT base driver!\n",
5318 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5319 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5321 if (reset_phase == MPT_IOC_SETUP_RESET) {
5323 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5324 /* If the internal config Q is not empty -
5325 * delete timer. MF resources will be freed when
5326 * the FIFO's are primed.
5328 spin_lock_irqsave(&ioc->FreeQlock, flags);
5329 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5330 del_timer(&pCfg->timer);
5331 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5333 } else {
5334 CONFIGPARMS *pNext;
5336 /* Search the configQ for internal commands.
5337 * Flush the Q, and wake up all suspended threads.
5339 spin_lock_irqsave(&ioc->FreeQlock, flags);
5340 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5341 list_del(&pCfg->linkage);
5343 pCfg->status = MPT_CONFIG_ERROR;
5344 pCfg->wait_done = 1;
5345 wake_up(&mpt_waitq);
5347 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5350 return 1; /* currently means nothing really */
5354 #ifdef CONFIG_PROC_FS /* { */
5355 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5357 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5359 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5361 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5363 * Returns 0 for success, non-zero for failure.
5365 static int
5366 procmpt_create(void)
5368 struct proc_dir_entry *ent;
5370 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5371 if (mpt_proc_root_dir == NULL)
5372 return -ENOTDIR;
5374 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5375 if (ent)
5376 ent->read_proc = procmpt_summary_read;
5378 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5379 if (ent)
5380 ent->read_proc = procmpt_version_read;
5382 return 0;
5385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5387 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5389 * Returns 0 for success, non-zero for failure.
5391 static void
5392 procmpt_destroy(void)
5394 remove_proc_entry("version", mpt_proc_root_dir);
5395 remove_proc_entry("summary", mpt_proc_root_dir);
5396 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5399 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5401 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5402 * or from /proc/mpt/iocN/summary.
5403 * @buf: Pointer to area to write information
5404 * @start: Pointer to start pointer
5405 * @offset: Offset to start writing
5406 * @request:
5407 * @eof: Pointer to EOF integer
5408 * @data: Pointer
5410 * Returns number of characters written to process performing the read.
5412 static int
5413 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5415 MPT_ADAPTER *ioc;
5416 char *out = buf;
5417 int len;
5419 if (data) {
5420 int more = 0;
5422 ioc = data;
5423 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5425 out += more;
5426 } else {
5427 list_for_each_entry(ioc, &ioc_list, list) {
5428 int more = 0;
5430 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5432 out += more;
5433 if ((out-buf) >= request)
5434 break;
5438 len = out - buf;
5440 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5443 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5445 * procmpt_version_read - Handle read request from /proc/mpt/version.
5446 * @buf: Pointer to area to write information
5447 * @start: Pointer to start pointer
5448 * @offset: Offset to start writing
5449 * @request:
5450 * @eof: Pointer to EOF integer
5451 * @data: Pointer
5453 * Returns number of characters written to process performing the read.
5455 static int
5456 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5458 int ii;
5459 int scsi, fc, sas, lan, ctl, targ, dmp;
5460 char *drvname;
5461 int len;
5463 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5464 len += sprintf(buf+len, " Fusion MPT base driver\n");
5466 scsi = fc = sas = lan = ctl = targ = dmp = 0;
5467 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5468 drvname = NULL;
5469 if (MptCallbacks[ii]) {
5470 switch (MptDriverClass[ii]) {
5471 case MPTSPI_DRIVER:
5472 if (!scsi++) drvname = "SPI host";
5473 break;
5474 case MPTFC_DRIVER:
5475 if (!fc++) drvname = "FC host";
5476 break;
5477 case MPTSAS_DRIVER:
5478 if (!sas++) drvname = "SAS host";
5479 break;
5480 case MPTLAN_DRIVER:
5481 if (!lan++) drvname = "LAN";
5482 break;
5483 case MPTSTM_DRIVER:
5484 if (!targ++) drvname = "SCSI target";
5485 break;
5486 case MPTCTL_DRIVER:
5487 if (!ctl++) drvname = "ioctl";
5488 break;
5491 if (drvname)
5492 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5496 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5499 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5501 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5502 * @buf: Pointer to area to write information
5503 * @start: Pointer to start pointer
5504 * @offset: Offset to start writing
5505 * @request:
5506 * @eof: Pointer to EOF integer
5507 * @data: Pointer
5509 * Returns number of characters written to process performing the read.
5511 static int
5512 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5514 MPT_ADAPTER *ioc = data;
5515 int len;
5516 char expVer[32];
5517 int sz;
5518 int p;
5520 mpt_get_fw_exp_ver(expVer, ioc);
5522 len = sprintf(buf, "%s:", ioc->name);
5523 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5524 len += sprintf(buf+len, " (f/w download boot flag set)");
5525 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5526 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5528 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5529 ioc->facts.ProductID,
5530 ioc->prod_name);
5531 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5532 if (ioc->facts.FWImageSize)
5533 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5534 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5535 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5536 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5538 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5539 ioc->facts.CurrentHostMfaHighAddr);
5540 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5541 ioc->facts.CurrentSenseBufferHighAddr);
5543 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5544 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5546 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5547 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5549 * Rounding UP to nearest 4-kB boundary here...
5551 sz = (ioc->req_sz * ioc->req_depth) + 128;
5552 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5553 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5554 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5555 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5556 4*ioc->facts.RequestFrameSize,
5557 ioc->facts.GlobalCredits);
5559 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5560 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5561 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5562 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5563 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5564 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5565 ioc->facts.CurReplyFrameSize,
5566 ioc->facts.ReplyQueueDepth);
5568 len += sprintf(buf+len, " MaxDevices = %d\n",
5569 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5570 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5572 /* per-port info */
5573 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5574 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5575 p+1,
5576 ioc->facts.NumberOfPorts);
5577 if (ioc->bus_type == FC) {
5578 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5579 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5580 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5581 a[5], a[4], a[3], a[2], a[1], a[0]);
5583 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5584 ioc->fc_port_page0[p].WWNN.High,
5585 ioc->fc_port_page0[p].WWNN.Low,
5586 ioc->fc_port_page0[p].WWPN.High,
5587 ioc->fc_port_page0[p].WWPN.Low);
5591 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5594 #endif /* CONFIG_PROC_FS } */
5596 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5597 static void
5598 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5600 buf[0] ='\0';
5601 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5602 sprintf(buf, " (Exp %02d%02d)",
5603 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5604 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5606 /* insider hack! */
5607 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5608 strcat(buf, " [MDBG]");
5612 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5614 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5615 * @ioc: Pointer to MPT_ADAPTER structure
5616 * @buffer: Pointer to buffer where IOC summary info should be written
5617 * @size: Pointer to number of bytes we wrote (set by this routine)
5618 * @len: Offset at which to start writing in buffer
5619 * @showlan: Display LAN stuff?
5621 * This routine writes (english readable) ASCII text, which represents
5622 * a summary of IOC information, to a buffer.
5624 void
5625 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5627 char expVer[32];
5628 int y;
5630 mpt_get_fw_exp_ver(expVer, ioc);
5633 * Shorter summary of attached ioc's...
5635 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5636 ioc->name,
5637 ioc->prod_name,
5638 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5639 ioc->facts.FWVersion.Word,
5640 expVer,
5641 ioc->facts.NumberOfPorts,
5642 ioc->req_depth);
5644 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5645 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5646 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5647 a[5], a[4], a[3], a[2], a[1], a[0]);
5650 #ifndef __sparc__
5651 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5652 #else
5653 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5654 #endif
5656 if (!ioc->active)
5657 y += sprintf(buffer+len+y, " (disabled)");
5659 y += sprintf(buffer+len+y, "\n");
5661 *size = y;
5664 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5666 * Reset Handling
5668 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5670 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5671 * Management call based on input arg values. If TaskMgmt fails,
5672 * return associated SCSI request.
5673 * @ioc: Pointer to MPT_ADAPTER structure
5674 * @sleepFlag: Indicates if sleep or schedule must be called.
5676 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5677 * or a non-interrupt thread. In the former, must not call schedule().
5679 * Remark: A return of -1 is a FATAL error case, as it means a
5680 * FW reload/initialization failed.
5682 * Returns 0 for SUCCESS or -1 if FAILED.
5685 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5687 int rc;
5688 unsigned long flags;
5690 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5691 #ifdef MFCNT
5692 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5693 printk("MF count 0x%x !\n", ioc->mfcnt);
5694 #endif
5696 /* Reset the adapter. Prevent more than 1 call to
5697 * mpt_do_ioc_recovery at any instant in time.
5699 spin_lock_irqsave(&ioc->diagLock, flags);
5700 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5701 spin_unlock_irqrestore(&ioc->diagLock, flags);
5702 return 0;
5703 } else {
5704 ioc->diagPending = 1;
5706 spin_unlock_irqrestore(&ioc->diagLock, flags);
5708 /* FIXME: If do_ioc_recovery fails, repeat....
5711 /* The SCSI driver needs to adjust timeouts on all current
5712 * commands prior to the diagnostic reset being issued.
5713 * Prevents timeouts occuring during a diagnostic reset...very bad.
5714 * For all other protocol drivers, this is a no-op.
5717 int ii;
5718 int r = 0;
5720 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5721 if (MptResetHandlers[ii]) {
5722 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5723 ioc->name, ii));
5724 r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
5725 if (ioc->alt_ioc) {
5726 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5727 ioc->name, ioc->alt_ioc->name, ii));
5728 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5734 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5735 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5736 rc, ioc->name);
5738 ioc->reload_fw = 0;
5739 if (ioc->alt_ioc)
5740 ioc->alt_ioc->reload_fw = 0;
5742 spin_lock_irqsave(&ioc->diagLock, flags);
5743 ioc->diagPending = 0;
5744 if (ioc->alt_ioc)
5745 ioc->alt_ioc->diagPending = 0;
5746 spin_unlock_irqrestore(&ioc->diagLock, flags);
5748 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5750 return rc;
5753 # define EVENT_DESCR_STR_SZ 100
5755 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5756 static void
5757 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5759 char *ds = NULL;
5761 switch(event) {
5762 case MPI_EVENT_NONE:
5763 ds = "None";
5764 break;
5765 case MPI_EVENT_LOG_DATA:
5766 ds = "Log Data";
5767 break;
5768 case MPI_EVENT_STATE_CHANGE:
5769 ds = "State Change";
5770 break;
5771 case MPI_EVENT_UNIT_ATTENTION:
5772 ds = "Unit Attention";
5773 break;
5774 case MPI_EVENT_IOC_BUS_RESET:
5775 ds = "IOC Bus Reset";
5776 break;
5777 case MPI_EVENT_EXT_BUS_RESET:
5778 ds = "External Bus Reset";
5779 break;
5780 case MPI_EVENT_RESCAN:
5781 ds = "Bus Rescan Event";
5782 /* Ok, do we need to do anything here? As far as
5783 I can tell, this is when a new device gets added
5784 to the loop. */
5785 break;
5786 case MPI_EVENT_LINK_STATUS_CHANGE:
5787 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5788 ds = "Link Status(FAILURE) Change";
5789 else
5790 ds = "Link Status(ACTIVE) Change";
5791 break;
5792 case MPI_EVENT_LOOP_STATE_CHANGE:
5793 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5794 ds = "Loop State(LIP) Change";
5795 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5796 ds = "Loop State(LPE) Change"; /* ??? */
5797 else
5798 ds = "Loop State(LPB) Change"; /* ??? */
5799 break;
5800 case MPI_EVENT_LOGOUT:
5801 ds = "Logout";
5802 break;
5803 case MPI_EVENT_EVENT_CHANGE:
5804 if (evData0)
5805 ds = "Events(ON) Change";
5806 else
5807 ds = "Events(OFF) Change";
5808 break;
5809 case MPI_EVENT_INTEGRATED_RAID:
5811 u8 ReasonCode = (u8)(evData0 >> 16);
5812 switch (ReasonCode) {
5813 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5814 ds = "Integrated Raid: Volume Created";
5815 break;
5816 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5817 ds = "Integrated Raid: Volume Deleted";
5818 break;
5819 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5820 ds = "Integrated Raid: Volume Settings Changed";
5821 break;
5822 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5823 ds = "Integrated Raid: Volume Status Changed";
5824 break;
5825 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5826 ds = "Integrated Raid: Volume Physdisk Changed";
5827 break;
5828 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5829 ds = "Integrated Raid: Physdisk Created";
5830 break;
5831 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5832 ds = "Integrated Raid: Physdisk Deleted";
5833 break;
5834 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5835 ds = "Integrated Raid: Physdisk Settings Changed";
5836 break;
5837 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5838 ds = "Integrated Raid: Physdisk Status Changed";
5839 break;
5840 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5841 ds = "Integrated Raid: Domain Validation Needed";
5842 break;
5843 case MPI_EVENT_RAID_RC_SMART_DATA :
5844 ds = "Integrated Raid; Smart Data";
5845 break;
5846 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5847 ds = "Integrated Raid: Replace Action Started";
5848 break;
5849 default:
5850 ds = "Integrated Raid";
5851 break;
5853 break;
5855 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5856 ds = "SCSI Device Status Change";
5857 break;
5858 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5860 u8 id = (u8)(evData0);
5861 u8 ReasonCode = (u8)(evData0 >> 16);
5862 switch (ReasonCode) {
5863 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5864 snprintf(evStr, EVENT_DESCR_STR_SZ,
5865 "SAS Device Status Change: Added: id=%d", id);
5866 break;
5867 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5868 snprintf(evStr, EVENT_DESCR_STR_SZ,
5869 "SAS Device Status Change: Deleted: id=%d", id);
5870 break;
5871 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5872 snprintf(evStr, EVENT_DESCR_STR_SZ,
5873 "SAS Device Status Change: SMART Data: id=%d",
5874 id);
5875 break;
5876 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5877 snprintf(evStr, EVENT_DESCR_STR_SZ,
5878 "SAS Device Status Change: No Persistancy "
5879 "Added: id=%d", id);
5880 break;
5881 default:
5882 snprintf(evStr, EVENT_DESCR_STR_SZ,
5883 "SAS Device Status Change: Unknown: id=%d", id);
5884 break;
5886 break;
5888 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5889 ds = "Bus Timer Expired";
5890 break;
5891 case MPI_EVENT_QUEUE_FULL:
5892 ds = "Queue Full";
5893 break;
5894 case MPI_EVENT_SAS_SES:
5895 ds = "SAS SES Event";
5896 break;
5897 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5898 ds = "Persistent Table Full";
5899 break;
5900 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5902 u8 LinkRates = (u8)(evData0 >> 8);
5903 u8 PhyNumber = (u8)(evData0);
5904 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5905 MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5906 switch (LinkRates) {
5907 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5908 snprintf(evStr, EVENT_DESCR_STR_SZ,
5909 "SAS PHY Link Status: Phy=%d:"
5910 " Rate Unknown",PhyNumber);
5911 break;
5912 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5913 snprintf(evStr, EVENT_DESCR_STR_SZ,
5914 "SAS PHY Link Status: Phy=%d:"
5915 " Phy Disabled",PhyNumber);
5916 break;
5917 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5918 snprintf(evStr, EVENT_DESCR_STR_SZ,
5919 "SAS PHY Link Status: Phy=%d:"
5920 " Failed Speed Nego",PhyNumber);
5921 break;
5922 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5923 snprintf(evStr, EVENT_DESCR_STR_SZ,
5924 "SAS PHY Link Status: Phy=%d:"
5925 " Sata OOB Completed",PhyNumber);
5926 break;
5927 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5928 snprintf(evStr, EVENT_DESCR_STR_SZ,
5929 "SAS PHY Link Status: Phy=%d:"
5930 " Rate 1.5 Gbps",PhyNumber);
5931 break;
5932 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5933 snprintf(evStr, EVENT_DESCR_STR_SZ,
5934 "SAS PHY Link Status: Phy=%d:"
5935 " Rate 3.0 Gpbs",PhyNumber);
5936 break;
5937 default:
5938 snprintf(evStr, EVENT_DESCR_STR_SZ,
5939 "SAS PHY Link Status: Phy=%d", PhyNumber);
5940 break;
5942 break;
5944 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5945 ds = "SAS Discovery Error";
5946 break;
5947 case MPI_EVENT_IR_RESYNC_UPDATE:
5949 u8 resync_complete = (u8)(evData0 >> 16);
5950 snprintf(evStr, EVENT_DESCR_STR_SZ,
5951 "IR Resync Update: Complete = %d:",resync_complete);
5952 break;
5954 case MPI_EVENT_IR2:
5956 u8 ReasonCode = (u8)(evData0 >> 16);
5957 switch (ReasonCode) {
5958 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5959 ds = "IR2: LD State Changed";
5960 break;
5961 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5962 ds = "IR2: PD State Changed";
5963 break;
5964 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5965 ds = "IR2: Bad Block Table Full";
5966 break;
5967 case MPI_EVENT_IR2_RC_PD_INSERTED:
5968 ds = "IR2: PD Inserted";
5969 break;
5970 case MPI_EVENT_IR2_RC_PD_REMOVED:
5971 ds = "IR2: PD Removed";
5972 break;
5973 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5974 ds = "IR2: Foreign CFG Detected";
5975 break;
5976 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5977 ds = "IR2: Rebuild Medium Error";
5978 break;
5979 default:
5980 ds = "IR2";
5981 break;
5983 break;
5985 case MPI_EVENT_SAS_DISCOVERY:
5987 if (evData0)
5988 ds = "SAS Discovery: Start";
5989 else
5990 ds = "SAS Discovery: Stop";
5991 break;
5993 case MPI_EVENT_LOG_ENTRY_ADDED:
5994 ds = "SAS Log Entry Added";
5995 break;
5998 * MPT base "custom" events may be added here...
6000 default:
6001 ds = "Unknown";
6002 break;
6004 if (ds)
6005 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6008 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6010 * ProcessEventNotification - Route a received EventNotificationReply to
6011 * all currently regeistered event handlers.
6012 * @ioc: Pointer to MPT_ADAPTER structure
6013 * @pEventReply: Pointer to EventNotification reply frame
6014 * @evHandlers: Pointer to integer, number of event handlers
6016 * Returns sum of event handlers return values.
6018 static int
6019 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6021 u16 evDataLen;
6022 u32 evData0 = 0;
6023 // u32 evCtx;
6024 int ii;
6025 int r = 0;
6026 int handlers = 0;
6027 char evStr[EVENT_DESCR_STR_SZ];
6028 u8 event;
6031 * Do platform normalization of values
6033 event = le32_to_cpu(pEventReply->Event) & 0xFF;
6034 // evCtx = le32_to_cpu(pEventReply->EventContext);
6035 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6036 if (evDataLen) {
6037 evData0 = le32_to_cpu(pEventReply->Data[0]);
6040 EventDescriptionStr(event, evData0, evStr);
6041 devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
6042 ioc->name,
6043 event,
6044 evStr));
6046 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
6047 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
6048 for (ii = 0; ii < evDataLen; ii++)
6049 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
6050 printk("\n");
6051 #endif
6054 * Do general / base driver event processing
6056 switch(event) {
6057 case MPI_EVENT_EVENT_CHANGE: /* 0A */
6058 if (evDataLen) {
6059 u8 evState = evData0 & 0xFF;
6061 /* CHECKME! What if evState unexpectedly says OFF (0)? */
6063 /* Update EventState field in cached IocFacts */
6064 if (ioc->facts.Function) {
6065 ioc->facts.EventState = evState;
6068 break;
6069 case MPI_EVENT_INTEGRATED_RAID:
6070 mptbase_raid_process_event_data(ioc,
6071 (MpiEventDataRaid_t *)pEventReply->Data);
6072 break;
6073 default:
6074 break;
6078 * Should this event be logged? Events are written sequentially.
6079 * When buffer is full, start again at the top.
6081 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6082 int idx;
6084 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6086 ioc->events[idx].event = event;
6087 ioc->events[idx].eventContext = ioc->eventContext;
6089 for (ii = 0; ii < 2; ii++) {
6090 if (ii < evDataLen)
6091 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6092 else
6093 ioc->events[idx].data[ii] = 0;
6096 ioc->eventContext++;
6101 * Call each currently registered protocol event handler.
6103 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6104 if (MptEvHandlers[ii]) {
6105 devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6106 ioc->name, ii));
6107 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6108 handlers++;
6111 /* FIXME? Examine results here? */
6114 * If needed, send (a single) EventAck.
6116 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6117 devtverboseprintk((MYIOC_s_WARN_FMT
6118 "EventAck required\n",ioc->name));
6119 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6120 devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6121 ioc->name, ii));
6125 *evHandlers = handlers;
6126 return r;
6129 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6131 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6132 * @ioc: Pointer to MPT_ADAPTER structure
6133 * @log_info: U32 LogInfo reply word from the IOC
6135 * Refer to lsi/fc_log.h.
6137 static void
6138 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6140 static char *subcl_str[8] = {
6141 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6142 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6144 u8 subcl = (log_info >> 24) & 0x7;
6146 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6147 ioc->name, log_info, subcl_str[subcl]);
6150 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6152 * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6153 * @ioc: Pointer to MPT_ADAPTER structure
6154 * @mr: Pointer to MPT reply frame
6155 * @log_info: U32 LogInfo word from the IOC
6157 * Refer to lsi/sp_log.h.
6159 static void
6160 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6162 u32 info = log_info & 0x00FF0000;
6163 char *desc = "unknown";
6165 switch (info) {
6166 case 0x00010000:
6167 desc = "bug! MID not found";
6168 if (ioc->reload_fw == 0)
6169 ioc->reload_fw++;
6170 break;
6172 case 0x00020000:
6173 desc = "Parity Error";
6174 break;
6176 case 0x00030000:
6177 desc = "ASYNC Outbound Overrun";
6178 break;
6180 case 0x00040000:
6181 desc = "SYNC Offset Error";
6182 break;
6184 case 0x00050000:
6185 desc = "BM Change";
6186 break;
6188 case 0x00060000:
6189 desc = "Msg In Overflow";
6190 break;
6192 case 0x00070000:
6193 desc = "DMA Error";
6194 break;
6196 case 0x00080000:
6197 desc = "Outbound DMA Overrun";
6198 break;
6200 case 0x00090000:
6201 desc = "Task Management";
6202 break;
6204 case 0x000A0000:
6205 desc = "Device Problem";
6206 break;
6208 case 0x000B0000:
6209 desc = "Invalid Phase Change";
6210 break;
6212 case 0x000C0000:
6213 desc = "Untagged Table Size";
6214 break;
6218 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6221 /* strings for sas loginfo */
6222 static char *originator_str[] = {
6223 "IOP", /* 00h */
6224 "PL", /* 01h */
6225 "IR" /* 02h */
6227 static char *iop_code_str[] = {
6228 NULL, /* 00h */
6229 "Invalid SAS Address", /* 01h */
6230 NULL, /* 02h */
6231 "Invalid Page", /* 03h */
6232 NULL, /* 04h */
6233 "Task Terminated" /* 05h */
6235 static char *pl_code_str[] = {
6236 NULL, /* 00h */
6237 "Open Failure", /* 01h */
6238 "Invalid Scatter Gather List", /* 02h */
6239 "Wrong Relative Offset or Frame Length", /* 03h */
6240 "Frame Transfer Error", /* 04h */
6241 "Transmit Frame Connected Low", /* 05h */
6242 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6243 "SATA Read Log Receive Data Error", /* 07h */
6244 "SATA NCQ Fail All Commands After Error", /* 08h */
6245 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6246 "Receive Frame Invalid Message", /* 0Ah */
6247 "Receive Context Message Valid Error", /* 0Bh */
6248 "Receive Frame Current Frame Error", /* 0Ch */
6249 "SATA Link Down", /* 0Dh */
6250 "Discovery SATA Init W IOS", /* 0Eh */
6251 "Config Invalid Page", /* 0Fh */
6252 "Discovery SATA Init Timeout", /* 10h */
6253 "Reset", /* 11h */
6254 "Abort", /* 12h */
6255 "IO Not Yet Executed", /* 13h */
6256 "IO Executed", /* 14h */
6257 "Persistant Reservation Out Not Affiliation Owner", /* 15h */
6258 "Open Transmit DMA Abort", /* 16h */
6259 NULL, /* 17h */
6260 NULL, /* 18h */
6261 NULL, /* 19h */
6262 NULL, /* 1Ah */
6263 NULL, /* 1Bh */
6264 NULL, /* 1Ch */
6265 NULL, /* 1Dh */
6266 NULL, /* 1Eh */
6267 NULL, /* 1Fh */
6268 "Enclosure Management" /* 20h */
6271 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6273 * mpt_sas_log_info - Log information returned from SAS IOC.
6274 * @ioc: Pointer to MPT_ADAPTER structure
6275 * @log_info: U32 LogInfo reply word from the IOC
6277 * Refer to lsi/mpi_log_sas.h.
6279 static void
6280 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6282 union loginfo_type {
6283 u32 loginfo;
6284 struct {
6285 u32 subcode:16;
6286 u32 code:8;
6287 u32 originator:4;
6288 u32 bus_type:4;
6289 }dw;
6291 union loginfo_type sas_loginfo;
6292 char *code_desc = NULL;
6294 sas_loginfo.loginfo = log_info;
6295 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6296 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6297 return;
6298 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6299 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6300 code_desc = iop_code_str[sas_loginfo.dw.code];
6301 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6302 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6303 code_desc = pl_code_str[sas_loginfo.dw.code];
6306 if (code_desc != NULL)
6307 printk(MYIOC_s_INFO_FMT
6308 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6309 " SubCode(0x%04x)\n",
6310 ioc->name,
6311 log_info,
6312 originator_str[sas_loginfo.dw.originator],
6313 code_desc,
6314 sas_loginfo.dw.subcode);
6315 else
6316 printk(MYIOC_s_INFO_FMT
6317 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6318 " SubCode(0x%04x)\n",
6319 ioc->name,
6320 log_info,
6321 originator_str[sas_loginfo.dw.originator],
6322 sas_loginfo.dw.code,
6323 sas_loginfo.dw.subcode);
6326 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6328 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6329 * @ioc: Pointer to MPT_ADAPTER structure
6330 * @ioc_status: U32 IOCStatus word from IOC
6331 * @mf: Pointer to MPT request frame
6333 * Refer to lsi/mpi.h.
6335 static void
6336 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6338 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6339 char *desc = "";
6341 switch (status) {
6342 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6343 desc = "Invalid Function";
6344 break;
6346 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6347 desc = "Busy";
6348 break;
6350 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6351 desc = "Invalid SGL";
6352 break;
6354 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6355 desc = "Internal Error";
6356 break;
6358 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6359 desc = "Reserved";
6360 break;
6362 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6363 desc = "Insufficient Resources";
6364 break;
6366 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6367 desc = "Invalid Field";
6368 break;
6370 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6371 desc = "Invalid State";
6372 break;
6374 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6375 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6376 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6377 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6378 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6379 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6380 /* No message for Config IOCStatus values */
6381 break;
6383 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6384 /* No message for recovered error
6385 desc = "SCSI Recovered Error";
6387 break;
6389 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6390 desc = "SCSI Invalid Bus";
6391 break;
6393 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6394 desc = "SCSI Invalid TargetID";
6395 break;
6397 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6399 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6400 U8 cdb = pScsiReq->CDB[0];
6401 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6402 desc = "SCSI Device Not There";
6404 break;
6407 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6408 desc = "SCSI Data Overrun";
6409 break;
6411 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6412 /* This error is checked in scsi_io_done(). Skip.
6413 desc = "SCSI Data Underrun";
6415 break;
6417 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6418 desc = "SCSI I/O Data Error";
6419 break;
6421 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6422 desc = "SCSI Protocol Error";
6423 break;
6425 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6426 desc = "SCSI Task Terminated";
6427 break;
6429 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6430 desc = "SCSI Residual Mismatch";
6431 break;
6433 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6434 desc = "SCSI Task Management Failed";
6435 break;
6437 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6438 desc = "SCSI IOC Terminated";
6439 break;
6441 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6442 desc = "SCSI Ext Terminated";
6443 break;
6445 default:
6446 desc = "Others";
6447 break;
6449 if (desc != "")
6450 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6453 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6454 EXPORT_SYMBOL(mpt_attach);
6455 EXPORT_SYMBOL(mpt_detach);
6456 #ifdef CONFIG_PM
6457 EXPORT_SYMBOL(mpt_resume);
6458 EXPORT_SYMBOL(mpt_suspend);
6459 #endif
6460 EXPORT_SYMBOL(ioc_list);
6461 EXPORT_SYMBOL(mpt_proc_root_dir);
6462 EXPORT_SYMBOL(mpt_register);
6463 EXPORT_SYMBOL(mpt_deregister);
6464 EXPORT_SYMBOL(mpt_event_register);
6465 EXPORT_SYMBOL(mpt_event_deregister);
6466 EXPORT_SYMBOL(mpt_reset_register);
6467 EXPORT_SYMBOL(mpt_reset_deregister);
6468 EXPORT_SYMBOL(mpt_device_driver_register);
6469 EXPORT_SYMBOL(mpt_device_driver_deregister);
6470 EXPORT_SYMBOL(mpt_get_msg_frame);
6471 EXPORT_SYMBOL(mpt_put_msg_frame);
6472 EXPORT_SYMBOL(mpt_free_msg_frame);
6473 EXPORT_SYMBOL(mpt_add_sge);
6474 EXPORT_SYMBOL(mpt_send_handshake_request);
6475 EXPORT_SYMBOL(mpt_verify_adapter);
6476 EXPORT_SYMBOL(mpt_GetIocState);
6477 EXPORT_SYMBOL(mpt_print_ioc_summary);
6478 EXPORT_SYMBOL(mpt_lan_index);
6479 EXPORT_SYMBOL(mpt_stm_index);
6480 EXPORT_SYMBOL(mpt_HardResetHandler);
6481 EXPORT_SYMBOL(mpt_config);
6482 EXPORT_SYMBOL(mpt_findImVolumes);
6483 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6484 EXPORT_SYMBOL(mpt_free_fw_memory);
6485 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6486 EXPORT_SYMBOL(mptbase_GetFcPortPage0);
6489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6491 * fusion_init - Fusion MPT base driver initialization routine.
6493 * Returns 0 for success, non-zero for failure.
6495 static int __init
6496 fusion_init(void)
6498 int i;
6500 show_mptmod_ver(my_NAME, my_VERSION);
6501 printk(KERN_INFO COPYRIGHT "\n");
6503 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6504 MptCallbacks[i] = NULL;
6505 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6506 MptEvHandlers[i] = NULL;
6507 MptResetHandlers[i] = NULL;
6510 /* Register ourselves (mptbase) in order to facilitate
6511 * EventNotification handling.
6513 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6515 /* Register for hard reset handling callbacks.
6517 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6518 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6519 } else {
6520 /* FIXME! */
6523 #ifdef CONFIG_PROC_FS
6524 (void) procmpt_create();
6525 #endif
6526 return 0;
6529 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6531 * fusion_exit - Perform driver unload cleanup.
6533 * This routine frees all resources associated with each MPT adapter
6534 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6536 static void __exit
6537 fusion_exit(void)
6540 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6542 mpt_reset_deregister(mpt_base_index);
6544 #ifdef CONFIG_PROC_FS
6545 procmpt_destroy();
6546 #endif
6549 module_init(fusion_init);
6550 module_exit(fusion_exit);