]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/message/fusion/mptbase.c
[SCSI] fusion - iocstatus, loginfo, and event debug updates
[linux-2.6-omap-h63xx.git] / drivers / message / fusion / mptbase.c
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.
7  *
8  *  Copyright (c) 1999-2007 LSI Logic Corporation
9  *  (mailto:mpt_linux_developer@lsil.com)
10  *
11  */
12 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13 /*
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.
17
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.
22
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.
33
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
42
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
46 */
47 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
48
49 #include <linux/kernel.h>
50 #include <linux/module.h>
51 #include <linux/errno.h>
52 #include <linux/init.h>
53 #include <linux/slab.h>
54 #include <linux/types.h>
55 #include <linux/pci.h>
56 #include <linux/kdev_t.h>
57 #include <linux/blkdev.h>
58 #include <linux/delay.h>
59 #include <linux/interrupt.h>            /* needed for in_interrupt() proto */
60 #include <linux/dma-mapping.h>
61 #include <asm/io.h>
62 #ifdef CONFIG_MTRR
63 #include <asm/mtrr.h>
64 #endif
65
66 #include "mptbase.h"
67
68 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69 #define my_NAME         "Fusion MPT base driver"
70 #define my_VERSION      MPT_LINUX_VERSION_COMMON
71 #define MYNAM           "mptbase"
72
73 MODULE_AUTHOR(MODULEAUTHOR);
74 MODULE_DESCRIPTION(my_NAME);
75 MODULE_LICENSE("GPL");
76 MODULE_VERSION(my_VERSION);
77
78 /*
79  *  cmd line parameters
80  */
81 static int mpt_msi_enable;
82 module_param(mpt_msi_enable, int, 0);
83 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
84
85 static int mpt_channel_mapping;
86 module_param(mpt_channel_mapping, int, 0);
87 MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
88
89 #ifdef MFCNT
90 static int mfcounter = 0;
91 #define PRINT_MF_COUNT 20000
92 #endif
93
94 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
95 /*
96  *  Public data...
97  */
98 int mpt_lan_index = -1;
99 int mpt_stm_index = -1;
100
101 struct proc_dir_entry *mpt_proc_root_dir;
102
103 #define WHOINIT_UNKNOWN         0xAA
104
105 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
106 /*
107  *  Private data...
108  */
109                                         /* Adapter link list */
110 LIST_HEAD(ioc_list);
111                                         /* Callback lookup table */
112 static MPT_CALLBACK              MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
113                                         /* Protocol driver class lookup table */
114 static int                       MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
115                                         /* Event handler lookup table */
116 static MPT_EVHANDLER             MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
117                                         /* Reset handler lookup table */
118 static MPT_RESETHANDLER          MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
119 static struct mpt_pci_driver    *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
120
121 static int      mpt_base_index = -1;
122 static int      last_drv_idx = -1;
123
124 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
125
126 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
127 /*
128  *  Forward protos...
129  */
130 static irqreturn_t mpt_interrupt(int irq, void *bus_id);
131 static int      mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
132 static int      mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
133                         u32 *req, int replyBytes, u16 *u16reply, int maxwait,
134                         int sleepFlag);
135 static int      mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
136 static void     mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
137 static void     mpt_adapter_disable(MPT_ADAPTER *ioc);
138 static void     mpt_adapter_dispose(MPT_ADAPTER *ioc);
139
140 static void     MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
141 static int      MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
142 static int      GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
143 static int      GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
144 static int      SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
145 static int      SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
146 static int      mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
147 static int      mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
148 static int      mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
149 static int      KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
150 static int      SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
151 static int      PrimeIocFifos(MPT_ADAPTER *ioc);
152 static int      WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
153 static int      WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
154 static int      WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
155 static int      GetLanConfigPages(MPT_ADAPTER *ioc);
156 static int      GetIoUnitPage2(MPT_ADAPTER *ioc);
157 int             mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
158 static int      mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
159 static int      mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
160 static void     mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
161 static void     mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
162 static void     mpt_timer_expired(unsigned long data);
163 static int      SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
164 static int      SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
165 static int      mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
166 static int      mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
167
168 #ifdef CONFIG_PROC_FS
169 static int      procmpt_summary_read(char *buf, char **start, off_t offset,
170                                 int request, int *eof, void *data);
171 static int      procmpt_version_read(char *buf, char **start, off_t offset,
172                                 int request, int *eof, void *data);
173 static int      procmpt_iocinfo_read(char *buf, char **start, off_t offset,
174                                 int request, int *eof, void *data);
175 #endif
176 static void     mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
177
178 //int           mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
179 static int      ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
180 #ifdef MPT_DEBUG_REPLY
181 static void     mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
182 #endif
183 static void     mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
184 static void     mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
185 static void     mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
186 static int      mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
187
188 /* module entry point */
189 static int  __init    fusion_init  (void);
190 static void __exit    fusion_exit  (void);
191
192 #define CHIPREG_READ32(addr)            readl_relaxed(addr)
193 #define CHIPREG_READ32_dmasync(addr)    readl(addr)
194 #define CHIPREG_WRITE32(addr,val)       writel(val, addr)
195 #define CHIPREG_PIO_WRITE32(addr,val)   outl(val, (unsigned long)addr)
196 #define CHIPREG_PIO_READ32(addr)        inl((unsigned long)addr)
197
198 static void
199 pci_disable_io_access(struct pci_dev *pdev)
200 {
201         u16 command_reg;
202
203         pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
204         command_reg &= ~1;
205         pci_write_config_word(pdev, PCI_COMMAND, command_reg);
206 }
207
208 static void
209 pci_enable_io_access(struct pci_dev *pdev)
210 {
211         u16 command_reg;
212
213         pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
214         command_reg |= 1;
215         pci_write_config_word(pdev, PCI_COMMAND, command_reg);
216 }
217
218 /*
219  *  Process turbo (context) reply...
220  */
221 static void
222 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
223 {
224         MPT_FRAME_HDR *mf = NULL;
225         MPT_FRAME_HDR *mr = NULL;
226         int req_idx = 0;
227         int cb_idx;
228
229         dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
230                                 ioc->name, pa));
231
232         switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
233         case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
234                 req_idx = pa & 0x0000FFFF;
235                 cb_idx = (pa & 0x00FF0000) >> 16;
236                 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
237                 break;
238         case MPI_CONTEXT_REPLY_TYPE_LAN:
239                 cb_idx = mpt_lan_index;
240                 /*
241                  *  Blind set of mf to NULL here was fatal
242                  *  after lan_reply says "freeme"
243                  *  Fix sort of combined with an optimization here;
244                  *  added explicit check for case where lan_reply
245                  *  was just returning 1 and doing nothing else.
246                  *  For this case skip the callback, but set up
247                  *  proper mf value first here:-)
248                  */
249                 if ((pa & 0x58000000) == 0x58000000) {
250                         req_idx = pa & 0x0000FFFF;
251                         mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
252                         mpt_free_msg_frame(ioc, mf);
253                         mb();
254                         return;
255                         break;
256                 }
257                 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
258                 break;
259         case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
260                 cb_idx = mpt_stm_index;
261                 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
262                 break;
263         default:
264                 cb_idx = 0;
265                 BUG();
266         }
267
268         /*  Check for (valid) IO callback!  */
269         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
270                         MptCallbacks[cb_idx] == NULL) {
271                 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
272                                 __FUNCTION__, ioc->name, cb_idx);
273                 goto out;
274         }
275
276         if (MptCallbacks[cb_idx](ioc, mf, mr))
277                 mpt_free_msg_frame(ioc, mf);
278  out:
279         mb();
280 }
281
282 static void
283 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
284 {
285         MPT_FRAME_HDR   *mf;
286         MPT_FRAME_HDR   *mr;
287         int              req_idx;
288         int              cb_idx;
289         int              freeme;
290
291         u32 reply_dma_low;
292         u16 ioc_stat;
293
294         /* non-TURBO reply!  Hmmm, something may be up...
295          *  Newest turbo reply mechanism; get address
296          *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
297          */
298
299         /* Map DMA address of reply header to cpu address.
300          * pa is 32 bits - but the dma address may be 32 or 64 bits
301          * get offset based only only the low addresses
302          */
303
304         reply_dma_low = (pa <<= 1);
305         mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
306                          (reply_dma_low - ioc->reply_frames_low_dma));
307
308         req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
309         cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
310         mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
311
312         dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
313                         ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
314         DBG_DUMP_REPLY_FRAME(mr)
315
316          /*  Check/log IOC log info
317          */
318         ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
319         if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
320                 u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
321                 if (ioc->bus_type == FC)
322                         mpt_fc_log_info(ioc, log_info);
323                 else if (ioc->bus_type == SPI)
324                         mpt_spi_log_info(ioc, log_info);
325                 else if (ioc->bus_type == SAS)
326                         mpt_sas_log_info(ioc, log_info);
327         }
328
329 #ifdef MPT_DEBUG_REPLY
330         if (ioc_stat & MPI_IOCSTATUS_MASK)
331                 mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
332 #endif
333
334         /*  Check for (valid) IO callback!  */
335         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
336                         MptCallbacks[cb_idx] == NULL) {
337                 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
338                                 __FUNCTION__, ioc->name, cb_idx);
339                 freeme = 0;
340                 goto out;
341         }
342
343         freeme = MptCallbacks[cb_idx](ioc, mf, mr);
344
345  out:
346         /*  Flush (non-TURBO) reply with a WRITE!  */
347         CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
348
349         if (freeme)
350                 mpt_free_msg_frame(ioc, mf);
351         mb();
352 }
353
354 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
355 /**
356  *      mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
357  *      @irq: irq number (not used)
358  *      @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
359  *
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.
366  *
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.
370  */
371 static irqreturn_t
372 mpt_interrupt(int irq, void *bus_id)
373 {
374         MPT_ADAPTER *ioc = bus_id;
375         u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
376
377         if (pa == 0xFFFFFFFF)
378                 return IRQ_NONE;
379
380         /*
381          *  Drain the reply FIFO!
382          */
383         do {
384                 if (pa & MPI_ADDRESS_REPLY_A_BIT)
385                         mpt_reply(ioc, pa);
386                 else
387                         mpt_turbo_reply(ioc, pa);
388                 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
389         } while (pa != 0xFFFFFFFF);
390
391         return IRQ_HANDLED;
392 }
393
394 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
395 /**
396  *      mpt_base_reply - MPT base driver's callback routine
397  *      @ioc: Pointer to MPT_ADAPTER structure
398  *      @mf: Pointer to original MPT request frame
399  *      @reply: Pointer to MPT reply frame (NULL if TurboReply)
400  *
401  *      MPT base driver's callback routine; all base driver
402  *      "internal" request/reply processing is routed here.
403  *      Currently used for EventNotification and EventAck handling.
404  *
405  *      Returns 1 indicating original alloc'd request frame ptr
406  *      should be freed, or 0 if it shouldn't.
407  */
408 static int
409 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
410 {
411         int freereq = 1;
412         u8 func;
413
414         dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
415
416 #if defined(MPT_DEBUG_MSG_FRAME)
417         if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
418                 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
419                 DBG_DUMP_REQUEST_FRAME_HDR(mf)
420         }
421 #endif
422
423         func = reply->u.hdr.Function;
424         dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
425                         ioc->name, func));
426
427         if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
428                 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
429                 int evHandlers = 0;
430                 int results;
431
432                 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
433                 if (results != evHandlers) {
434                         /* CHECKME! Any special handling needed here? */
435                         devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
436                                         ioc->name, evHandlers, results));
437                 }
438
439                 /*
440                  *      Hmmm...  It seems that EventNotificationReply is an exception
441                  *      to the rule of one reply per request.
442                  */
443                 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
444                         freereq = 0;
445                 } else {
446                         devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
447                                 ioc->name, pEvReply));
448                 }
449
450 #ifdef CONFIG_PROC_FS
451 //              LogEvent(ioc, pEvReply);
452 #endif
453
454         } else if (func == MPI_FUNCTION_EVENT_ACK) {
455                 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
456                                 ioc->name));
457         } else if (func == MPI_FUNCTION_CONFIG) {
458                 CONFIGPARMS *pCfg;
459                 unsigned long flags;
460
461                 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
462                                 ioc->name, mf, reply));
463
464                 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
465
466                 if (pCfg) {
467                         /* disable timer and remove from linked list */
468                         del_timer(&pCfg->timer);
469
470                         spin_lock_irqsave(&ioc->FreeQlock, flags);
471                         list_del(&pCfg->linkage);
472                         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
473
474                         /*
475                          *      If IOC Status is SUCCESS, save the header
476                          *      and set the status code to GOOD.
477                          */
478                         pCfg->status = MPT_CONFIG_ERROR;
479                         if (reply) {
480                                 ConfigReply_t   *pReply = (ConfigReply_t *)reply;
481                                 u16              status;
482
483                                 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
484                                 dcprintk((KERN_NOTICE "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",
485                                      status, le32_to_cpu(pReply->IOCLogInfo)));
486
487                                 pCfg->status = status;
488                                 if (status == MPI_IOCSTATUS_SUCCESS) {
489                                         if ((pReply->Header.PageType &
490                                             MPI_CONFIG_PAGETYPE_MASK) ==
491                                             MPI_CONFIG_PAGETYPE_EXTENDED) {
492                                                 pCfg->cfghdr.ehdr->ExtPageLength =
493                                                     le16_to_cpu(pReply->ExtPageLength);
494                                                 pCfg->cfghdr.ehdr->ExtPageType =
495                                                     pReply->ExtPageType;
496                                         }
497                                         pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
498
499                                         /* If this is a regular header, save PageLength. */
500                                         /* LMP Do this better so not using a reserved field! */
501                                         pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
502                                         pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
503                                         pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
504                                 }
505                         }
506
507                         /*
508                          *      Wake up the original calling thread
509                          */
510                         pCfg->wait_done = 1;
511                         wake_up(&mpt_waitq);
512                 }
513         } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
514                 /* we should be always getting a reply frame */
515                 memcpy(ioc->persist_reply_frame, reply,
516                     min(MPT_DEFAULT_FRAME_SIZE,
517                     4*reply->u.reply.MsgLength));
518                 del_timer(&ioc->persist_timer);
519                 ioc->persist_wait_done = 1;
520                 wake_up(&mpt_waitq);
521         } else {
522                 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
523                                 ioc->name, func);
524         }
525
526         /*
527          *      Conditionally tell caller to free the original
528          *      EventNotification/EventAck/unexpected request frame!
529          */
530         return freereq;
531 }
532
533 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
534 /**
535  *      mpt_register - Register protocol-specific main callback handler.
536  *      @cbfunc: callback function pointer
537  *      @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
538  *
539  *      This routine is called by a protocol-specific driver (SCSI host,
540  *      LAN, SCSI target) to register its reply callback routine.  Each
541  *      protocol-specific driver must do this before it will be able to
542  *      use any IOC resources, such as obtaining request frames.
543  *
544  *      NOTES: The SCSI protocol driver currently calls this routine thrice
545  *      in order to register separate callbacks; one for "normal" SCSI IO;
546  *      one for MptScsiTaskMgmt requests; one for Scan/DV requests.
547  *
548  *      Returns a positive integer valued "handle" in the
549  *      range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
550  *      Any non-positive return value (including zero!) should be considered
551  *      an error by the caller.
552  */
553 int
554 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
555 {
556         int i;
557
558         last_drv_idx = -1;
559
560         /*
561          *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}
562          *  (slot/handle 0 is reserved!)
563          */
564         for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
565                 if (MptCallbacks[i] == NULL) {
566                         MptCallbacks[i] = cbfunc;
567                         MptDriverClass[i] = dclass;
568                         MptEvHandlers[i] = NULL;
569                         last_drv_idx = i;
570                         break;
571                 }
572         }
573
574         return last_drv_idx;
575 }
576
577 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
578 /**
579  *      mpt_deregister - Deregister a protocol drivers resources.
580  *      @cb_idx: previously registered callback handle
581  *
582  *      Each protocol-specific driver should call this routine when its
583  *      module is unloaded.
584  */
585 void
586 mpt_deregister(int cb_idx)
587 {
588         if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
589                 MptCallbacks[cb_idx] = NULL;
590                 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
591                 MptEvHandlers[cb_idx] = NULL;
592
593                 last_drv_idx++;
594         }
595 }
596
597 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
598 /**
599  *      mpt_event_register - Register protocol-specific event callback
600  *      handler.
601  *      @cb_idx: previously registered (via mpt_register) callback handle
602  *      @ev_cbfunc: callback function
603  *
604  *      This routine can be called by one or more protocol-specific drivers
605  *      if/when they choose to be notified of MPT events.
606  *
607  *      Returns 0 for success.
608  */
609 int
610 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
611 {
612         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
613                 return -1;
614
615         MptEvHandlers[cb_idx] = ev_cbfunc;
616         return 0;
617 }
618
619 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
620 /**
621  *      mpt_event_deregister - Deregister protocol-specific event callback
622  *      handler.
623  *      @cb_idx: previously registered callback handle
624  *
625  *      Each protocol-specific driver should call this routine
626  *      when it does not (or can no longer) handle events,
627  *      or when its module is unloaded.
628  */
629 void
630 mpt_event_deregister(int cb_idx)
631 {
632         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
633                 return;
634
635         MptEvHandlers[cb_idx] = NULL;
636 }
637
638 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
639 /**
640  *      mpt_reset_register - Register protocol-specific IOC reset handler.
641  *      @cb_idx: previously registered (via mpt_register) callback handle
642  *      @reset_func: reset function
643  *
644  *      This routine can be called by one or more protocol-specific drivers
645  *      if/when they choose to be notified of IOC resets.
646  *
647  *      Returns 0 for success.
648  */
649 int
650 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
651 {
652         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
653                 return -1;
654
655         MptResetHandlers[cb_idx] = reset_func;
656         return 0;
657 }
658
659 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
660 /**
661  *      mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
662  *      @cb_idx: previously registered callback handle
663  *
664  *      Each protocol-specific driver should call this routine
665  *      when it does not (or can no longer) handle IOC reset handling,
666  *      or when its module is unloaded.
667  */
668 void
669 mpt_reset_deregister(int cb_idx)
670 {
671         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
672                 return;
673
674         MptResetHandlers[cb_idx] = NULL;
675 }
676
677 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
678 /**
679  *      mpt_device_driver_register - Register device driver hooks
680  *      @dd_cbfunc: driver callbacks struct
681  *      @cb_idx: MPT protocol driver index
682  */
683 int
684 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
685 {
686         MPT_ADAPTER     *ioc;
687         const struct pci_device_id *id;
688
689         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
690                 return -EINVAL;
691
692         MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
693
694         /* call per pci device probe entry point */
695         list_for_each_entry(ioc, &ioc_list, list) {
696                 id = ioc->pcidev->driver ?
697                     ioc->pcidev->driver->id_table : NULL;
698                 if (dd_cbfunc->probe)
699                         dd_cbfunc->probe(ioc->pcidev, id);
700          }
701
702         return 0;
703 }
704
705 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
706 /**
707  *      mpt_device_driver_deregister - DeRegister device driver hooks
708  *      @cb_idx: MPT protocol driver index
709  */
710 void
711 mpt_device_driver_deregister(int cb_idx)
712 {
713         struct mpt_pci_driver *dd_cbfunc;
714         MPT_ADAPTER     *ioc;
715
716         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
717                 return;
718
719         dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
720
721         list_for_each_entry(ioc, &ioc_list, list) {
722                 if (dd_cbfunc->remove)
723                         dd_cbfunc->remove(ioc->pcidev);
724         }
725
726         MptDeviceDriverHandlers[cb_idx] = NULL;
727 }
728
729
730 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
731 /**
732  *      mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
733  *      allocated per MPT adapter.
734  *      @handle: Handle of registered MPT protocol driver
735  *      @ioc: Pointer to MPT adapter structure
736  *
737  *      Returns pointer to a MPT request frame or %NULL if none are available
738  *      or IOC is not active.
739  */
740 MPT_FRAME_HDR*
741 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
742 {
743         MPT_FRAME_HDR *mf;
744         unsigned long flags;
745         u16      req_idx;       /* Request index */
746
747         /* validate handle and ioc identifier */
748
749 #ifdef MFCNT
750         if (!ioc->active)
751                 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
752 #endif
753
754         /* If interrupts are not attached, do not return a request frame */
755         if (!ioc->active)
756                 return NULL;
757
758         spin_lock_irqsave(&ioc->FreeQlock, flags);
759         if (!list_empty(&ioc->FreeQ)) {
760                 int req_offset;
761
762                 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
763                                 u.frame.linkage.list);
764                 list_del(&mf->u.frame.linkage.list);
765                 mf->u.frame.linkage.arg1 = 0;
766                 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;  /* byte */
767                 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
768                                                                 /* u16! */
769                 req_idx = req_offset / ioc->req_sz;
770                 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
771                 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
772                 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
773 #ifdef MFCNT
774                 ioc->mfcnt++;
775 #endif
776         }
777         else
778                 mf = NULL;
779         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
780
781 #ifdef MFCNT
782         if (mf == NULL)
783                 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
784         mfcounter++;
785         if (mfcounter == PRINT_MF_COUNT)
786                 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
787 #endif
788
789         dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
790                         ioc->name, handle, ioc->id, mf));
791         return mf;
792 }
793
794 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
795 /**
796  *      mpt_put_msg_frame - Send a protocol specific MPT request frame
797  *      to a IOC.
798  *      @handle: Handle of registered MPT protocol driver
799  *      @ioc: Pointer to MPT adapter structure
800  *      @mf: Pointer to MPT request frame
801  *
802  *      This routine posts a MPT request frame to the request post FIFO of a
803  *      specific MPT adapter.
804  */
805 void
806 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
807 {
808         u32 mf_dma_addr;
809         int req_offset;
810         u16      req_idx;       /* Request index */
811
812         /* ensure values are reset properly! */
813         mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;          /* byte */
814         req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
815                                                                 /* u16! */
816         req_idx = req_offset / ioc->req_sz;
817         mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
818         mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
819
820 #ifdef MPT_DEBUG_MSG_FRAME
821         {
822                 u32     *m = mf->u.frame.hwhdr.__hdr;
823                 int      ii, n;
824
825                 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
826                                 ioc->name, m);
827                 n = ioc->req_sz/4 - 1;
828                 while (m[n] == 0)
829                         n--;
830                 for (ii=0; ii<=n; ii++) {
831                         if (ii && ((ii%8)==0))
832                                 printk("\n" KERN_INFO " ");
833                         printk(" %08x", le32_to_cpu(m[ii]));
834                 }
835                 printk("\n");
836         }
837 #endif
838
839         mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
840         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]));
841         CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
842 }
843
844 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
845 /**
846  *      mpt_free_msg_frame - Place MPT request frame back on FreeQ.
847  *      @handle: Handle of registered MPT protocol driver
848  *      @ioc: Pointer to MPT adapter structure
849  *      @mf: Pointer to MPT request frame
850  *
851  *      This routine places a MPT request frame back on the MPT adapter's
852  *      FreeQ.
853  */
854 void
855 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
856 {
857         unsigned long flags;
858
859         /*  Put Request back on FreeQ!  */
860         spin_lock_irqsave(&ioc->FreeQlock, flags);
861         mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
862         list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
863 #ifdef MFCNT
864         ioc->mfcnt--;
865 #endif
866         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
867 }
868
869 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
870 /**
871  *      mpt_add_sge - Place a simple SGE at address pAddr.
872  *      @pAddr: virtual address for SGE
873  *      @flagslength: SGE flags and data transfer length
874  *      @dma_addr: Physical address
875  *
876  *      This routine places a MPT request frame back on the MPT adapter's
877  *      FreeQ.
878  */
879 void
880 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
881 {
882         if (sizeof(dma_addr_t) == sizeof(u64)) {
883                 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
884                 u32 tmp = dma_addr & 0xFFFFFFFF;
885
886                 pSge->FlagsLength = cpu_to_le32(flagslength);
887                 pSge->Address.Low = cpu_to_le32(tmp);
888                 tmp = (u32) ((u64)dma_addr >> 32);
889                 pSge->Address.High = cpu_to_le32(tmp);
890
891         } else {
892                 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
893                 pSge->FlagsLength = cpu_to_le32(flagslength);
894                 pSge->Address = cpu_to_le32(dma_addr);
895         }
896 }
897
898 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
899 /**
900  *      mpt_send_handshake_request - Send MPT request via doorbell handshake method.
901  *      @handle: Handle of registered MPT protocol driver
902  *      @ioc: Pointer to MPT adapter structure
903  *      @reqBytes: Size of the request in bytes
904  *      @req: Pointer to MPT request frame
905  *      @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
906  *
907  *      This routine is used exclusively to send MptScsiTaskMgmt
908  *      requests since they are required to be sent via doorbell handshake.
909  *
910  *      NOTE: It is the callers responsibility to byte-swap fields in the
911  *      request which are greater than 1 byte in size.
912  *
913  *      Returns 0 for success, non-zero for failure.
914  */
915 int
916 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
917 {
918         int              r = 0;
919         u8      *req_as_bytes;
920         int      ii;
921
922         /* State is known to be good upon entering
923          * this function so issue the bus reset
924          * request.
925          */
926
927         /*
928          * Emulate what mpt_put_msg_frame() does /wrt to sanity
929          * setting cb_idx/req_idx.  But ONLY if this request
930          * is in proper (pre-alloc'd) request buffer range...
931          */
932         ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
933         if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
934                 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
935                 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
936                 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
937         }
938
939         /* Make sure there are no doorbells */
940         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
941
942         CHIPREG_WRITE32(&ioc->chip->Doorbell,
943                         ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
944                          ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
945
946         /* Wait for IOC doorbell int */
947         if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
948                 return ii;
949         }
950
951         /* Read doorbell and check for active bit */
952         if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
953                 return -5;
954
955         dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
956                 ioc->name, ii));
957
958         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
959
960         if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
961                 return -2;
962         }
963
964         /* Send request via doorbell handshake */
965         req_as_bytes = (u8 *) req;
966         for (ii = 0; ii < reqBytes/4; ii++) {
967                 u32 word;
968
969                 word = ((req_as_bytes[(ii*4) + 0] <<  0) |
970                         (req_as_bytes[(ii*4) + 1] <<  8) |
971                         (req_as_bytes[(ii*4) + 2] << 16) |
972                         (req_as_bytes[(ii*4) + 3] << 24));
973                 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
974                 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
975                         r = -3;
976                         break;
977                 }
978         }
979
980         if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
981                 r = 0;
982         else
983                 r = -4;
984
985         /* Make sure there are no doorbells */
986         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
987
988         return r;
989 }
990
991 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
992 /**
993  * mpt_host_page_access_control - control the IOC's Host Page Buffer access
994  * @ioc: Pointer to MPT adapter structure
995  * @access_control_value: define bits below
996  * @sleepFlag: Specifies whether the process can sleep
997  *
998  * Provides mechanism for the host driver to control the IOC's
999  * Host Page Buffer access.
1000  *
1001  * Access Control Value - bits[15:12]
1002  * 0h Reserved
1003  * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1004  * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1005  * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1006  *
1007  * Returns 0 for success, non-zero for failure.
1008  */
1009
1010 static int
1011 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1012 {
1013         int      r = 0;
1014
1015         /* return if in use */
1016         if (CHIPREG_READ32(&ioc->chip->Doorbell)
1017             & MPI_DOORBELL_ACTIVE)
1018             return -1;
1019
1020         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1021
1022         CHIPREG_WRITE32(&ioc->chip->Doorbell,
1023                 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1024                  <<MPI_DOORBELL_FUNCTION_SHIFT) |
1025                  (access_control_value<<12)));
1026
1027         /* Wait for IOC to clear Doorbell Status bit */
1028         if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1029                 return -2;
1030         }else
1031                 return 0;
1032 }
1033
1034 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1035 /**
1036  *      mpt_host_page_alloc - allocate system memory for the fw
1037  *      @ioc: Pointer to pointer to IOC adapter
1038  *      @ioc_init: Pointer to ioc init config page
1039  *
1040  *      If we already allocated memory in past, then resend the same pointer.
1041  *      Returns 0 for success, non-zero for failure.
1042  */
1043 static int
1044 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1045 {
1046         char    *psge;
1047         int     flags_length;
1048         u32     host_page_buffer_sz=0;
1049
1050         if(!ioc->HostPageBuffer) {
1051
1052                 host_page_buffer_sz =
1053                     le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1054
1055                 if(!host_page_buffer_sz)
1056                         return 0; /* fw doesn't need any host buffers */
1057
1058                 /* spin till we get enough memory */
1059                 while(host_page_buffer_sz > 0) {
1060
1061                         if((ioc->HostPageBuffer = pci_alloc_consistent(
1062                             ioc->pcidev,
1063                             host_page_buffer_sz,
1064                             &ioc->HostPageBuffer_dma)) != NULL) {
1065
1066                                 dinitprintk((MYIOC_s_INFO_FMT
1067                                     "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1068                                     ioc->name, ioc->HostPageBuffer,
1069                                     (u32)ioc->HostPageBuffer_dma,
1070                                     host_page_buffer_sz));
1071                                 ioc->alloc_total += host_page_buffer_sz;
1072                                 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1073                                 break;
1074                         }
1075
1076                         host_page_buffer_sz -= (4*1024);
1077                 }
1078         }
1079
1080         if(!ioc->HostPageBuffer) {
1081                 printk(MYIOC_s_ERR_FMT
1082                     "Failed to alloc memory for host_page_buffer!\n",
1083                     ioc->name);
1084                 return -999;
1085         }
1086
1087         psge = (char *)&ioc_init->HostPageBufferSGE;
1088         flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1089             MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1090             MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1091             MPI_SGE_FLAGS_HOST_TO_IOC |
1092             MPI_SGE_FLAGS_END_OF_BUFFER;
1093         if (sizeof(dma_addr_t) == sizeof(u64)) {
1094             flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1095         }
1096         flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1097         flags_length |= ioc->HostPageBuffer_sz;
1098         mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1099         ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1100
1101 return 0;
1102 }
1103
1104 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1105 /**
1106  *      mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1107  *      @iocid: IOC unique identifier (integer)
1108  *      @iocpp: Pointer to pointer to IOC adapter
1109  *
1110  *      Given a unique IOC identifier, set pointer to the associated MPT
1111  *      adapter structure.
1112  *
1113  *      Returns iocid and sets iocpp if iocid is found.
1114  *      Returns -1 if iocid is not found.
1115  */
1116 int
1117 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1118 {
1119         MPT_ADAPTER *ioc;
1120
1121         list_for_each_entry(ioc,&ioc_list,list) {
1122                 if (ioc->id == iocid) {
1123                         *iocpp =ioc;
1124                         return iocid;
1125                 }
1126         }
1127
1128         *iocpp = NULL;
1129         return -1;
1130 }
1131
1132 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1133 /**
1134  *      mpt_attach - Install a PCI intelligent MPT adapter.
1135  *      @pdev: Pointer to pci_dev structure
1136  *      @id: PCI device ID information
1137  *
1138  *      This routine performs all the steps necessary to bring the IOC of
1139  *      a MPT adapter to a OPERATIONAL state.  This includes registering
1140  *      memory regions, registering the interrupt, and allocating request
1141  *      and reply memory pools.
1142  *
1143  *      This routine also pre-fetches the LAN MAC address of a Fibre Channel
1144  *      MPT adapter.
1145  *
1146  *      Returns 0 for success, non-zero for failure.
1147  *
1148  *      TODO: Add support for polled controllers
1149  */
1150 int
1151 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1152 {
1153         MPT_ADAPTER     *ioc;
1154         u8              __iomem *mem;
1155         unsigned long    mem_phys;
1156         unsigned long    port;
1157         u32              msize;
1158         u32              psize;
1159         int              ii;
1160         int              r = -ENODEV;
1161         u8               revision;
1162         u8               pcixcmd;
1163         static int       mpt_ids = 0;
1164 #ifdef CONFIG_PROC_FS
1165         struct proc_dir_entry *dent, *ent;
1166 #endif
1167
1168         if (pci_enable_device(pdev))
1169                 return r;
1170
1171         dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1172
1173         if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1174                 dprintk((KERN_INFO MYNAM
1175                         ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1176         } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1177                 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1178                 return r;
1179         }
1180
1181         if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1182                 dprintk((KERN_INFO MYNAM
1183                         ": Using 64 bit consistent mask\n"));
1184         else
1185                 dprintk((KERN_INFO MYNAM
1186                         ": Not using 64 bit consistent mask\n"));
1187
1188         ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1189         if (ioc == NULL) {
1190                 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1191                 return -ENOMEM;
1192         }
1193         ioc->alloc_total = sizeof(MPT_ADAPTER);
1194         ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;           /* avoid div by zero! */
1195         ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1196
1197         ioc->pcidev = pdev;
1198         ioc->diagPending = 0;
1199         spin_lock_init(&ioc->diagLock);
1200         spin_lock_init(&ioc->initializing_hba_lock);
1201
1202         /* Initialize the event logging.
1203          */
1204         ioc->eventTypes = 0;    /* None */
1205         ioc->eventContext = 0;
1206         ioc->eventLogSize = 0;
1207         ioc->events = NULL;
1208
1209 #ifdef MFCNT
1210         ioc->mfcnt = 0;
1211 #endif
1212
1213         ioc->cached_fw = NULL;
1214
1215         /* Initilize SCSI Config Data structure
1216          */
1217         memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1218
1219         /* Initialize the running configQ head.
1220          */
1221         INIT_LIST_HEAD(&ioc->configQ);
1222
1223         /* Initialize the fc rport list head.
1224          */
1225         INIT_LIST_HEAD(&ioc->fc_rports);
1226
1227         /* Find lookup slot. */
1228         INIT_LIST_HEAD(&ioc->list);
1229         ioc->id = mpt_ids++;
1230
1231         mem_phys = msize = 0;
1232         port = psize = 0;
1233         for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1234                 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1235                         if (psize)
1236                                 continue;
1237                         /* Get I/O space! */
1238                         port = pci_resource_start(pdev, ii);
1239                         psize = pci_resource_len(pdev,ii);
1240                 } else {
1241                         if (msize)
1242                                 continue;
1243                         /* Get memmap */
1244                         mem_phys = pci_resource_start(pdev, ii);
1245                         msize = pci_resource_len(pdev,ii);
1246                 }
1247         }
1248         ioc->mem_size = msize;
1249
1250         mem = NULL;
1251         /* Get logical ptr for PciMem0 space */
1252         /*mem = ioremap(mem_phys, msize);*/
1253         mem = ioremap(mem_phys, msize);
1254         if (mem == NULL) {
1255                 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1256                 kfree(ioc);
1257                 return -EINVAL;
1258         }
1259         ioc->memmap = mem;
1260         dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1261
1262         dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1263                         &ioc->facts, &ioc->pfacts[0]));
1264
1265         ioc->mem_phys = mem_phys;
1266         ioc->chip = (SYSIF_REGS __iomem *)mem;
1267
1268         /* Save Port IO values in case we need to do downloadboot */
1269         {
1270                 u8 *pmem = (u8*)port;
1271                 ioc->pio_mem_phys = port;
1272                 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1273         }
1274
1275         if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1276                 ioc->prod_name = "LSIFC909";
1277                 ioc->bus_type = FC;
1278         }
1279         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1280                 ioc->prod_name = "LSIFC929";
1281                 ioc->bus_type = FC;
1282         }
1283         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1284                 ioc->prod_name = "LSIFC919";
1285                 ioc->bus_type = FC;
1286         }
1287         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1288                 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1289                 ioc->bus_type = FC;
1290                 if (revision < XL_929) {
1291                         ioc->prod_name = "LSIFC929X";
1292                         /* 929X Chip Fix. Set Split transactions level
1293                         * for PCIX. Set MOST bits to zero.
1294                         */
1295                         pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1296                         pcixcmd &= 0x8F;
1297                         pci_write_config_byte(pdev, 0x6a, pcixcmd);
1298                 } else {
1299                         ioc->prod_name = "LSIFC929XL";
1300                         /* 929XL Chip Fix. Set MMRBC to 0x08.
1301                         */
1302                         pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1303                         pcixcmd |= 0x08;
1304                         pci_write_config_byte(pdev, 0x6a, pcixcmd);
1305                 }
1306         }
1307         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1308                 ioc->prod_name = "LSIFC919X";
1309                 ioc->bus_type = FC;
1310                 /* 919X Chip Fix. Set Split transactions level
1311                  * for PCIX. Set MOST bits to zero.
1312                  */
1313                 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1314                 pcixcmd &= 0x8F;
1315                 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1316         }
1317         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1318                 ioc->prod_name = "LSIFC939X";
1319                 ioc->bus_type = FC;
1320                 ioc->errata_flag_1064 = 1;
1321         }
1322         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1323                 ioc->prod_name = "LSIFC949X";
1324                 ioc->bus_type = FC;
1325                 ioc->errata_flag_1064 = 1;
1326         }
1327         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1328                 ioc->prod_name = "LSIFC949E";
1329                 ioc->bus_type = FC;
1330         }
1331         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1332                 ioc->prod_name = "LSI53C1030";
1333                 ioc->bus_type = SPI;
1334                 /* 1030 Chip Fix. Disable Split transactions
1335                  * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1336                  */
1337                 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1338                 if (revision < C0_1030) {
1339                         pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1340                         pcixcmd &= 0x8F;
1341                         pci_write_config_byte(pdev, 0x6a, pcixcmd);
1342                 }
1343         }
1344         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1345                 ioc->prod_name = "LSI53C1035";
1346                 ioc->bus_type = SPI;
1347         }
1348         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1349                 ioc->prod_name = "LSISAS1064";
1350                 ioc->bus_type = SAS;
1351                 ioc->errata_flag_1064 = 1;
1352         }
1353         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1354                 ioc->prod_name = "LSISAS1068";
1355                 ioc->bus_type = SAS;
1356                 ioc->errata_flag_1064 = 1;
1357         }
1358         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1359                 ioc->prod_name = "LSISAS1064E";
1360                 ioc->bus_type = SAS;
1361         }
1362         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1363                 ioc->prod_name = "LSISAS1068E";
1364                 ioc->bus_type = SAS;
1365         }
1366         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
1367                 ioc->prod_name = "LSISAS1078";
1368                 ioc->bus_type = SAS;
1369         }
1370
1371         if (ioc->errata_flag_1064)
1372                 pci_disable_io_access(pdev);
1373
1374         sprintf(ioc->name, "ioc%d", ioc->id);
1375
1376         spin_lock_init(&ioc->FreeQlock);
1377
1378         /* Disable all! */
1379         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1380         ioc->active = 0;
1381         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1382
1383         /* Set lookup ptr. */
1384         list_add_tail(&ioc->list, &ioc_list);
1385
1386         /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1387          */
1388         mpt_detect_bound_ports(ioc, pdev);
1389
1390         if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1391             CAN_SLEEP)) != 0){
1392                 printk(KERN_WARNING MYNAM
1393                   ": WARNING - %s did not initialize properly! (%d)\n",
1394                   ioc->name, r);
1395
1396                 list_del(&ioc->list);
1397                 if (ioc->alt_ioc)
1398                         ioc->alt_ioc->alt_ioc = NULL;
1399                 iounmap(mem);
1400                 kfree(ioc);
1401                 pci_set_drvdata(pdev, NULL);
1402                 return r;
1403         }
1404
1405         /* call per device driver probe entry point */
1406         for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1407                 if(MptDeviceDriverHandlers[ii] &&
1408                   MptDeviceDriverHandlers[ii]->probe) {
1409                         MptDeviceDriverHandlers[ii]->probe(pdev,id);
1410                 }
1411         }
1412
1413 #ifdef CONFIG_PROC_FS
1414         /*
1415          *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1416          */
1417         dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1418         if (dent) {
1419                 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1420                 if (ent) {
1421                         ent->read_proc = procmpt_iocinfo_read;
1422                         ent->data = ioc;
1423                 }
1424                 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1425                 if (ent) {
1426                         ent->read_proc = procmpt_summary_read;
1427                         ent->data = ioc;
1428                 }
1429         }
1430 #endif
1431
1432         return 0;
1433 }
1434
1435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1436 /**
1437  *      mpt_detach - Remove a PCI intelligent MPT adapter.
1438  *      @pdev: Pointer to pci_dev structure
1439  */
1440
1441 void
1442 mpt_detach(struct pci_dev *pdev)
1443 {
1444         MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
1445         char pname[32];
1446         int ii;
1447
1448         sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1449         remove_proc_entry(pname, NULL);
1450         sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1451         remove_proc_entry(pname, NULL);
1452         sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1453         remove_proc_entry(pname, NULL);
1454
1455         /* call per device driver remove entry point */
1456         for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1457                 if(MptDeviceDriverHandlers[ii] &&
1458                   MptDeviceDriverHandlers[ii]->remove) {
1459                         MptDeviceDriverHandlers[ii]->remove(pdev);
1460                 }
1461         }
1462
1463         /* Disable interrupts! */
1464         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1465
1466         ioc->active = 0;
1467         synchronize_irq(pdev->irq);
1468
1469         /* Clear any lingering interrupt */
1470         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1471
1472         CHIPREG_READ32(&ioc->chip->IntStatus);
1473
1474         mpt_adapter_dispose(ioc);
1475
1476         pci_set_drvdata(pdev, NULL);
1477 }
1478
1479 /**************************************************************************
1480  * Power Management
1481  */
1482 #ifdef CONFIG_PM
1483 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1484 /**
1485  *      mpt_suspend - Fusion MPT base driver suspend routine.
1486  *      @pdev: Pointer to pci_dev structure
1487  *      @state: new state to enter
1488  */
1489 int
1490 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1491 {
1492         u32 device_state;
1493         MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1494
1495         device_state=pci_choose_state(pdev, state);
1496
1497         printk(MYIOC_s_INFO_FMT
1498         "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1499                 ioc->name, pdev, pci_name(pdev), device_state);
1500
1501         pci_save_state(pdev);
1502
1503         /* put ioc into READY_STATE */
1504         if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1505                 printk(MYIOC_s_ERR_FMT
1506                 "pci-suspend:  IOC msg unit reset failed!\n", ioc->name);
1507         }
1508
1509         /* disable interrupts */
1510         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1511         ioc->active = 0;
1512
1513         /* Clear any lingering interrupt */
1514         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1515
1516         pci_disable_device(pdev);
1517         pci_set_power_state(pdev, device_state);
1518
1519         return 0;
1520 }
1521
1522 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1523 /**
1524  *      mpt_resume - Fusion MPT base driver resume routine.
1525  *      @pdev: Pointer to pci_dev structure
1526  */
1527 int
1528 mpt_resume(struct pci_dev *pdev)
1529 {
1530         MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1531         u32 device_state = pdev->current_state;
1532         int recovery_state;
1533
1534         printk(MYIOC_s_INFO_FMT
1535         "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1536                 ioc->name, pdev, pci_name(pdev), device_state);
1537
1538         pci_set_power_state(pdev, 0);
1539         pci_restore_state(pdev);
1540         pci_enable_device(pdev);
1541
1542         /* enable interrupts */
1543         CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1544         ioc->active = 1;
1545
1546         printk(MYIOC_s_INFO_FMT
1547                 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1548                 ioc->name,
1549                 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1550                 CHIPREG_READ32(&ioc->chip->Doorbell));
1551
1552         /* bring ioc to operational state */
1553         if ((recovery_state = mpt_do_ioc_recovery(ioc,
1554             MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1555                 printk(MYIOC_s_INFO_FMT
1556                         "pci-resume: Cannot recover, error:[%x]\n",
1557                         ioc->name, recovery_state);
1558         } else {
1559                 printk(MYIOC_s_INFO_FMT
1560                         "pci-resume: success\n", ioc->name);
1561         }
1562
1563         return 0;
1564 }
1565 #endif
1566
1567 static int
1568 mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
1569 {
1570         if ((MptDriverClass[index] == MPTSPI_DRIVER &&
1571              ioc->bus_type != SPI) ||
1572             (MptDriverClass[index] == MPTFC_DRIVER &&
1573              ioc->bus_type != FC) ||
1574             (MptDriverClass[index] == MPTSAS_DRIVER &&
1575              ioc->bus_type != SAS))
1576                 /* make sure we only call the relevant reset handler
1577                  * for the bus */
1578                 return 0;
1579         return (MptResetHandlers[index])(ioc, reset_phase);
1580 }
1581
1582 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1583 /**
1584  *      mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1585  *      @ioc: Pointer to MPT adapter structure
1586  *      @reason: Event word / reason
1587  *      @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1588  *
1589  *      This routine performs all the steps necessary to bring the IOC
1590  *      to a OPERATIONAL state.
1591  *
1592  *      This routine also pre-fetches the LAN MAC address of a Fibre Channel
1593  *      MPT adapter.
1594  *
1595  *      Returns:
1596  *               0 for success
1597  *              -1 if failed to get board READY
1598  *              -2 if READY but IOCFacts Failed
1599  *              -3 if READY but PrimeIOCFifos Failed
1600  *              -4 if READY but IOCInit Failed
1601  */
1602 static int
1603 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1604 {
1605         int      hard_reset_done = 0;
1606         int      alt_ioc_ready = 0;
1607         int      hard;
1608         int      rc=0;
1609         int      ii;
1610         int      handlers;
1611         int      ret = 0;
1612         int      reset_alt_ioc_active = 0;
1613         int      irq_allocated = 0;
1614
1615         printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1616                         ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1617
1618         /* Disable reply interrupts (also blocks FreeQ) */
1619         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1620         ioc->active = 0;
1621
1622         if (ioc->alt_ioc) {
1623                 if (ioc->alt_ioc->active)
1624                         reset_alt_ioc_active = 1;
1625
1626                 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1627                 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1628                 ioc->alt_ioc->active = 0;
1629         }
1630
1631         hard = 1;
1632         if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1633                 hard = 0;
1634
1635         if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1636                 if (hard_reset_done == -4) {
1637                         printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1638                                         ioc->name);
1639
1640                         if (reset_alt_ioc_active && ioc->alt_ioc) {
1641                                 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1642                                 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1643                                                 ioc->alt_ioc->name));
1644                                 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1645                                 ioc->alt_ioc->active = 1;
1646                         }
1647
1648                 } else {
1649                         printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1650                                         ioc->name);
1651                 }
1652                 return -1;
1653         }
1654
1655         /* hard_reset_done = 0 if a soft reset was performed
1656          * and 1 if a hard reset was performed.
1657          */
1658         if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1659                 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1660                         alt_ioc_ready = 1;
1661                 else
1662                         printk(KERN_WARNING MYNAM
1663                                         ": alt-%s: Not ready WARNING!\n",
1664                                         ioc->alt_ioc->name);
1665         }
1666
1667         for (ii=0; ii<5; ii++) {
1668                 /* Get IOC facts! Allow 5 retries */
1669                 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1670                         break;
1671         }
1672
1673
1674         if (ii == 5) {
1675                 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1676                 ret = -2;
1677         } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1678                 MptDisplayIocCapabilities(ioc);
1679         }
1680
1681         if (alt_ioc_ready) {
1682                 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1683                         dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1684                         /* Retry - alt IOC was initialized once
1685                          */
1686                         rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1687                 }
1688                 if (rc) {
1689                         dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1690                         alt_ioc_ready = 0;
1691                         reset_alt_ioc_active = 0;
1692                 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1693                         MptDisplayIocCapabilities(ioc->alt_ioc);
1694                 }
1695         }
1696
1697         /*
1698          * Device is reset now. It must have de-asserted the interrupt line
1699          * (if it was asserted) and it should be safe to register for the
1700          * interrupt now.
1701          */
1702         if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1703                 ioc->pci_irq = -1;
1704                 if (ioc->pcidev->irq) {
1705                         if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
1706                                 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
1707                                         ioc->name);
1708                         rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
1709                                         IRQF_SHARED, ioc->name, ioc);
1710                         if (rc < 0) {
1711                                 printk(MYIOC_s_ERR_FMT "Unable to allocate "
1712                                         "interrupt %d!\n", ioc->name,
1713                                         ioc->pcidev->irq);
1714                                 if (mpt_msi_enable)
1715                                         pci_disable_msi(ioc->pcidev);
1716                                 return -EBUSY;
1717                         }
1718                         irq_allocated = 1;
1719                         ioc->pci_irq = ioc->pcidev->irq;
1720                         pci_set_master(ioc->pcidev);            /* ?? */
1721                         pci_set_drvdata(ioc->pcidev, ioc);
1722                         dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
1723                                 "%d\n", ioc->name, ioc->pcidev->irq));
1724                 }
1725         }
1726
1727         /* Prime reply & request queues!
1728          * (mucho alloc's) Must be done prior to
1729          * init as upper addresses are needed for init.
1730          * If fails, continue with alt-ioc processing
1731          */
1732         if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1733                 ret = -3;
1734
1735         /* May need to check/upload firmware & data here!
1736          * If fails, continue with alt-ioc processing
1737          */
1738         if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1739                 ret = -4;
1740 // NEW!
1741         if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1742                 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1743                                 ioc->alt_ioc->name, rc);
1744                 alt_ioc_ready = 0;
1745                 reset_alt_ioc_active = 0;
1746         }
1747
1748         if (alt_ioc_ready) {
1749                 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1750                         alt_ioc_ready = 0;
1751                         reset_alt_ioc_active = 0;
1752                         printk(KERN_WARNING MYNAM
1753                                 ": alt-%s: (%d) init failure WARNING!\n",
1754                                         ioc->alt_ioc->name, rc);
1755                 }
1756         }
1757
1758         if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1759                 if (ioc->upload_fw) {
1760                         ddlprintk((MYIOC_s_INFO_FMT
1761                                 "firmware upload required!\n", ioc->name));
1762
1763                         /* Controller is not operational, cannot do upload
1764                          */
1765                         if (ret == 0) {
1766                                 rc = mpt_do_upload(ioc, sleepFlag);
1767                                 if (rc == 0) {
1768                                         if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1769                                                 /*
1770                                                  * Maintain only one pointer to FW memory
1771                                                  * so there will not be two attempt to
1772                                                  * downloadboot onboard dual function
1773                                                  * chips (mpt_adapter_disable,
1774                                                  * mpt_diag_reset)
1775                                                  */
1776                                                 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload:  alt_%s has cached_fw=%p \n",
1777                                                         ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1778                                                 ioc->alt_ioc->cached_fw = NULL;
1779                                         }
1780                                 } else {
1781                                         printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1782                                         ret = -5;
1783                                 }
1784                         }
1785                 }
1786         }
1787
1788         if (ret == 0) {
1789                 /* Enable! (reply interrupt) */
1790                 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1791                 ioc->active = 1;
1792         }
1793
1794         if (reset_alt_ioc_active && ioc->alt_ioc) {
1795                 /* (re)Enable alt-IOC! (reply interrupt) */
1796                 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1797                                 ioc->alt_ioc->name));
1798                 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1799                 ioc->alt_ioc->active = 1;
1800         }
1801
1802         /*  Enable MPT base driver management of EventNotification
1803          *  and EventAck handling.
1804          */
1805         if ((ret == 0) && (!ioc->facts.EventState))
1806                 (void) SendEventNotification(ioc, 1);   /* 1=Enable EventNotification */
1807
1808         if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1809                 (void) SendEventNotification(ioc->alt_ioc, 1);  /* 1=Enable EventNotification */
1810
1811         /*      Add additional "reason" check before call to GetLanConfigPages
1812          *      (combined with GetIoUnitPage2 call).  This prevents a somewhat
1813          *      recursive scenario; GetLanConfigPages times out, timer expired
1814          *      routine calls HardResetHandler, which calls into here again,
1815          *      and we try GetLanConfigPages again...
1816          */
1817         if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1818                 if (ioc->bus_type == SAS) {
1819
1820                         /* clear persistency table */
1821                         if(ioc->facts.IOCExceptions &
1822                             MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1823                                 ret = mptbase_sas_persist_operation(ioc,
1824                                     MPI_SAS_OP_CLEAR_NOT_PRESENT);
1825                                 if(ret != 0)
1826                                         goto out;
1827                         }
1828
1829                         /* Find IM volumes
1830                          */
1831                         mpt_findImVolumes(ioc);
1832
1833                 } else if (ioc->bus_type == FC) {
1834                         if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1835                             (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1836                                 /*
1837                                  *  Pre-fetch the ports LAN MAC address!
1838                                  *  (LANPage1_t stuff)
1839                                  */
1840                                 (void) GetLanConfigPages(ioc);
1841 #ifdef MPT_DEBUG
1842                                 {
1843                                         u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1844                                         dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1845                                                         ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1846                                 }
1847 #endif
1848                         }
1849                 } else {
1850                         /* Get NVRAM and adapter maximums from SPP 0 and 2
1851                          */
1852                         mpt_GetScsiPortSettings(ioc, 0);
1853
1854                         /* Get version and length of SDP 1
1855                          */
1856                         mpt_readScsiDevicePageHeaders(ioc, 0);
1857
1858                         /* Find IM volumes
1859                          */
1860                         if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1861                                 mpt_findImVolumes(ioc);
1862
1863                         /* Check, and possibly reset, the coalescing value
1864                          */
1865                         mpt_read_ioc_pg_1(ioc);
1866
1867                         mpt_read_ioc_pg_4(ioc);
1868                 }
1869
1870                 GetIoUnitPage2(ioc);
1871         }
1872
1873         /*
1874          * Call each currently registered protocol IOC reset handler
1875          * with post-reset indication.
1876          * NOTE: If we're doing _IOC_BRINGUP, there can be no
1877          * MptResetHandlers[] registered yet.
1878          */
1879         if (hard_reset_done) {
1880                 rc = handlers = 0;
1881                 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1882                         if ((ret == 0) && MptResetHandlers[ii]) {
1883                                 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1884                                                 ioc->name, ii));
1885                                 rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
1886                                 handlers++;
1887                         }
1888
1889                         if (alt_ioc_ready && MptResetHandlers[ii]) {
1890                                 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1891                                                 ioc->name, ioc->alt_ioc->name, ii));
1892                                 rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
1893                                 handlers++;
1894                         }
1895                 }
1896                 /* FIXME?  Examine results here? */
1897         }
1898
1899  out:
1900         if ((ret != 0) && irq_allocated) {
1901                 free_irq(ioc->pci_irq, ioc);
1902                 if (mpt_msi_enable)
1903                         pci_disable_msi(ioc->pcidev);
1904         }
1905         return ret;
1906 }
1907
1908 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1909 /**
1910  *      mpt_detect_bound_ports - Search for matching PCI bus/dev_function
1911  *      @ioc: Pointer to MPT adapter structure
1912  *      @pdev: Pointer to (struct pci_dev) structure
1913  *
1914  *      Search for PCI bus/dev_function which matches
1915  *      PCI bus/dev_function (+/-1) for newly discovered 929,
1916  *      929X, 1030 or 1035.
1917  *
1918  *      If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1919  *      using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1920  */
1921 static void
1922 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1923 {
1924         struct pci_dev *peer=NULL;
1925         unsigned int slot = PCI_SLOT(pdev->devfn);
1926         unsigned int func = PCI_FUNC(pdev->devfn);
1927         MPT_ADAPTER *ioc_srch;
1928
1929         dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1930             " searching for devfn match on %x or %x\n",
1931                 ioc->name, pci_name(pdev), pdev->bus->number,
1932                 pdev->devfn, func-1, func+1));
1933
1934         peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1935         if (!peer) {
1936                 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1937                 if (!peer)
1938                         return;
1939         }
1940
1941         list_for_each_entry(ioc_srch, &ioc_list, list) {
1942                 struct pci_dev *_pcidev = ioc_srch->pcidev;
1943                 if (_pcidev == peer) {
1944                         /* Paranoia checks */
1945                         if (ioc->alt_ioc != NULL) {
1946                                 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1947                                         ioc->name, ioc->alt_ioc->name);
1948                                 break;
1949                         } else if (ioc_srch->alt_ioc != NULL) {
1950                                 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1951                                         ioc_srch->name, ioc_srch->alt_ioc->name);
1952                                 break;
1953                         }
1954                         dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1955                                 ioc->name, ioc_srch->name));
1956                         ioc_srch->alt_ioc = ioc;
1957                         ioc->alt_ioc = ioc_srch;
1958                 }
1959         }
1960         pci_dev_put(peer);
1961 }
1962
1963 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1964 /**
1965  *      mpt_adapter_disable - Disable misbehaving MPT adapter.
1966  *      @ioc: Pointer to MPT adapter structure
1967  */
1968 static void
1969 mpt_adapter_disable(MPT_ADAPTER *ioc)
1970 {
1971         int sz;
1972         int ret;
1973
1974         if (ioc->cached_fw != NULL) {
1975                 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1976                 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1977                         printk(KERN_WARNING MYNAM
1978                                 ": firmware downloadboot failure (%d)!\n", ret);
1979                 }
1980         }
1981
1982         /* Disable adapter interrupts! */
1983         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1984         ioc->active = 0;
1985         /* Clear any lingering interrupt */
1986         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1987
1988         if (ioc->alloc != NULL) {
1989                 sz = ioc->alloc_sz;
1990                 dexitprintk((KERN_INFO MYNAM ": %s.free  @ %p, sz=%d bytes\n",
1991                         ioc->name, ioc->alloc, ioc->alloc_sz));
1992                 pci_free_consistent(ioc->pcidev, sz,
1993                                 ioc->alloc, ioc->alloc_dma);
1994                 ioc->reply_frames = NULL;
1995                 ioc->req_frames = NULL;
1996                 ioc->alloc = NULL;
1997                 ioc->alloc_total -= sz;
1998         }
1999
2000         if (ioc->sense_buf_pool != NULL) {
2001                 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2002                 pci_free_consistent(ioc->pcidev, sz,
2003                                 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2004                 ioc->sense_buf_pool = NULL;
2005                 ioc->alloc_total -= sz;
2006         }
2007
2008         if (ioc->events != NULL){
2009                 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2010                 kfree(ioc->events);
2011                 ioc->events = NULL;
2012                 ioc->alloc_total -= sz;
2013         }
2014
2015         if (ioc->cached_fw != NULL) {
2016                 sz = ioc->facts.FWImageSize;
2017                 pci_free_consistent(ioc->pcidev, sz,
2018                         ioc->cached_fw, ioc->cached_fw_dma);
2019                 ioc->cached_fw = NULL;
2020                 ioc->alloc_total -= sz;
2021         }
2022
2023         kfree(ioc->spi_data.nvram);
2024         kfree(ioc->raid_data.pIocPg3);
2025         ioc->spi_data.nvram = NULL;
2026         ioc->raid_data.pIocPg3 = NULL;
2027
2028         if (ioc->spi_data.pIocPg4 != NULL) {
2029                 sz = ioc->spi_data.IocPg4Sz;
2030                 pci_free_consistent(ioc->pcidev, sz, 
2031                         ioc->spi_data.pIocPg4,
2032                         ioc->spi_data.IocPg4_dma);
2033                 ioc->spi_data.pIocPg4 = NULL;
2034                 ioc->alloc_total -= sz;
2035         }
2036
2037         if (ioc->ReqToChain != NULL) {
2038                 kfree(ioc->ReqToChain);
2039                 kfree(ioc->RequestNB);
2040                 ioc->ReqToChain = NULL;
2041         }
2042
2043         kfree(ioc->ChainToChain);
2044         ioc->ChainToChain = NULL;
2045
2046         if (ioc->HostPageBuffer != NULL) {
2047                 if((ret = mpt_host_page_access_control(ioc,
2048                     MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2049                         printk(KERN_ERR MYNAM
2050                            ": %s: host page buffers free failed (%d)!\n",
2051                             __FUNCTION__, ret);
2052                 }
2053                 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free  @ %p, sz=%d bytes\n",
2054                         ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2055                 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2056                                 ioc->HostPageBuffer,
2057                                 ioc->HostPageBuffer_dma);
2058                 ioc->HostPageBuffer = NULL;
2059                 ioc->HostPageBuffer_sz = 0;
2060                 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2061         }
2062 }
2063
2064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2065 /**
2066  *      mpt_adapter_dispose - Free all resources associated with an MPT adapter
2067  *      @ioc: Pointer to MPT adapter structure
2068  *
2069  *      This routine unregisters h/w resources and frees all alloc'd memory
2070  *      associated with a MPT adapter structure.
2071  */
2072 static void
2073 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2074 {
2075         int sz_first, sz_last;
2076
2077         if (ioc == NULL)
2078                 return;
2079
2080         sz_first = ioc->alloc_total;
2081
2082         mpt_adapter_disable(ioc);
2083
2084         if (ioc->pci_irq != -1) {
2085                 free_irq(ioc->pci_irq, ioc);
2086                 if (mpt_msi_enable)
2087                         pci_disable_msi(ioc->pcidev);
2088                 ioc->pci_irq = -1;
2089         }
2090
2091         if (ioc->memmap != NULL) {
2092                 iounmap(ioc->memmap);
2093                 ioc->memmap = NULL;
2094         }
2095
2096 #if defined(CONFIG_MTRR) && 0
2097         if (ioc->mtrr_reg > 0) {
2098                 mtrr_del(ioc->mtrr_reg, 0, 0);
2099                 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2100         }
2101 #endif
2102
2103         /*  Zap the adapter lookup ptr!  */
2104         list_del(&ioc->list);
2105
2106         sz_last = ioc->alloc_total;
2107         dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2108                         ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2109
2110         if (ioc->alt_ioc)
2111                 ioc->alt_ioc->alt_ioc = NULL;
2112
2113         kfree(ioc);
2114 }
2115
2116 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2117 /**
2118  *      MptDisplayIocCapabilities - Disply IOC's capabilities.
2119  *      @ioc: Pointer to MPT adapter structure
2120  */
2121 static void
2122 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2123 {
2124         int i = 0;
2125
2126         printk(KERN_INFO "%s: ", ioc->name);
2127         if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2128                 printk("%s: ", ioc->prod_name+3);
2129         printk("Capabilities={");
2130
2131         if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2132                 printk("Initiator");
2133                 i++;
2134         }
2135
2136         if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2137                 printk("%sTarget", i ? "," : "");
2138                 i++;
2139         }
2140
2141         if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2142                 printk("%sLAN", i ? "," : "");
2143                 i++;
2144         }
2145
2146 #if 0
2147         /*
2148          *  This would probably evoke more questions than it's worth
2149          */
2150         if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2151                 printk("%sLogBusAddr", i ? "," : "");
2152                 i++;
2153         }
2154 #endif
2155
2156         printk("}\n");
2157 }
2158
2159 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2160 /**
2161  *      MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2162  *      @ioc: Pointer to MPT_ADAPTER structure
2163  *      @force: Force hard KickStart of IOC
2164  *      @sleepFlag: Specifies whether the process can sleep
2165  *
2166  *      Returns:
2167  *               1 - DIAG reset and READY
2168  *               0 - READY initially OR soft reset and READY
2169  *              -1 - Any failure on KickStart
2170  *              -2 - Msg Unit Reset Failed
2171  *              -3 - IO Unit Reset Failed
2172  *              -4 - IOC owned by a PEER
2173  */
2174 static int
2175 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2176 {
2177         u32      ioc_state;
2178         int      statefault = 0;
2179         int      cntdn;
2180         int      hard_reset_done = 0;
2181         int      r;
2182         int      ii;
2183         int      whoinit;
2184
2185         /* Get current [raw] IOC state  */
2186         ioc_state = mpt_GetIocState(ioc, 0);
2187         dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2188
2189         /*
2190          *      Check to see if IOC got left/stuck in doorbell handshake
2191          *      grip of death.  If so, hard reset the IOC.
2192          */
2193         if (ioc_state & MPI_DOORBELL_ACTIVE) {
2194                 statefault = 1;
2195                 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2196                                 ioc->name);
2197         }
2198
2199         /* Is it already READY? */
2200         if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2201                 return 0;
2202
2203         /*
2204          *      Check to see if IOC is in FAULT state.
2205          */
2206         if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2207                 statefault = 2;
2208                 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2209                                 ioc->name);
2210                 printk(KERN_WARNING "           FAULT code = %04xh\n",
2211                                 ioc_state & MPI_DOORBELL_DATA_MASK);
2212         }
2213
2214         /*
2215          *      Hmmm...  Did it get left operational?
2216          */
2217         if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2218                 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
2219                                 ioc->name));
2220
2221                 /* Check WhoInit.
2222                  * If PCI Peer, exit.
2223                  * Else, if no fault conditions are present, issue a MessageUnitReset
2224                  * Else, fall through to KickStart case
2225                  */
2226                 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2227                 dinitprintk((KERN_INFO MYNAM
2228                         ": whoinit 0x%x statefault %d force %d\n",
2229                         whoinit, statefault, force));
2230                 if (whoinit == MPI_WHOINIT_PCI_PEER)
2231                         return -4;
2232                 else {
2233                         if ((statefault == 0 ) && (force == 0)) {
2234                                 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2235                                         return 0;
2236                         }
2237                         statefault = 3;
2238                 }
2239         }
2240
2241         hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2242         if (hard_reset_done < 0)
2243                 return -1;
2244
2245         /*
2246          *  Loop here waiting for IOC to come READY.
2247          */
2248         ii = 0;
2249         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5;     /* 5 seconds */
2250
2251         while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2252                 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2253                         /*
2254                          *  BIOS or previous driver load left IOC in OP state.
2255                          *  Reset messaging FIFOs.
2256                          */
2257                         if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2258                                 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2259                                 return -2;
2260                         }
2261                 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2262                         /*
2263                          *  Something is wrong.  Try to get IOC back
2264                          *  to a known state.
2265                          */
2266                         if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2267                                 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2268                                 return -3;
2269                         }
2270                 }
2271
2272                 ii++; cntdn--;
2273                 if (!cntdn) {
2274                         printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2275                                         ioc->name, (int)((ii+5)/HZ));
2276                         return -ETIME;
2277                 }
2278
2279                 if (sleepFlag == CAN_SLEEP) {
2280                         msleep(1);
2281                 } else {
2282                         mdelay (1);     /* 1 msec delay */
2283                 }
2284
2285         }
2286
2287         if (statefault < 3) {
2288                 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2289                                 ioc->name,
2290                                 statefault==1 ? "stuck handshake" : "IOC FAULT");
2291         }
2292
2293         return hard_reset_done;
2294 }
2295
2296 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2297 /**
2298  *      mpt_GetIocState - Get the current state of a MPT adapter.
2299  *      @ioc: Pointer to MPT_ADAPTER structure
2300  *      @cooked: Request raw or cooked IOC state
2301  *
2302  *      Returns all IOC Doorbell register bits if cooked==0, else just the
2303  *      Doorbell bits in MPI_IOC_STATE_MASK.
2304  */
2305 u32
2306 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2307 {
2308         u32 s, sc;
2309
2310         /*  Get!  */
2311         s = CHIPREG_READ32(&ioc->chip->Doorbell);
2312 //      dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2313         sc = s & MPI_IOC_STATE_MASK;
2314
2315         /*  Save!  */
2316         ioc->last_state = sc;
2317
2318         return cooked ? sc : s;
2319 }
2320
2321 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2322 /**
2323  *      GetIocFacts - Send IOCFacts request to MPT adapter.
2324  *      @ioc: Pointer to MPT_ADAPTER structure
2325  *      @sleepFlag: Specifies whether the process can sleep
2326  *      @reason: If recovery, only update facts.
2327  *
2328  *      Returns 0 for success, non-zero for failure.
2329  */
2330 static int
2331 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2332 {
2333         IOCFacts_t               get_facts;
2334         IOCFactsReply_t         *facts;
2335         int                      r;
2336         int                      req_sz;
2337         int                      reply_sz;
2338         int                      sz;
2339         u32                      status, vv;
2340         u8                       shiftFactor=1;
2341
2342         /* IOC *must* NOT be in RESET state! */
2343         if (ioc->last_state == MPI_IOC_STATE_RESET) {
2344                 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2345                                 ioc->name,
2346                                 ioc->last_state );
2347                 return -44;
2348         }
2349
2350         facts = &ioc->facts;
2351
2352         /* Destination (reply area)... */
2353         reply_sz = sizeof(*facts);
2354         memset(facts, 0, reply_sz);
2355
2356         /* Request area (get_facts on the stack right now!) */
2357         req_sz = sizeof(get_facts);
2358         memset(&get_facts, 0, req_sz);
2359
2360         get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2361         /* Assert: All other get_facts fields are zero! */
2362
2363         dinitprintk((MYIOC_s_INFO_FMT
2364             "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2365             ioc->name, req_sz, reply_sz));
2366
2367         /* No non-zero fields in the get_facts request are greater than
2368          * 1 byte in size, so we can just fire it off as is.
2369          */
2370         r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2371                         reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2372         if (r != 0)
2373                 return r;
2374
2375         /*
2376          * Now byte swap (GRRR) the necessary fields before any further
2377          * inspection of reply contents.
2378          *
2379          * But need to do some sanity checks on MsgLength (byte) field
2380          * to make sure we don't zero IOC's req_sz!
2381          */
2382         /* Did we get a valid reply? */
2383         if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2384                 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2385                         /*
2386                          * If not been here, done that, save off first WhoInit value
2387                          */
2388                         if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2389                                 ioc->FirstWhoInit = facts->WhoInit;
2390                 }
2391
2392                 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2393                 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2394                 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2395                 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2396                 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2397                 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2398                 /* CHECKME! IOCStatus, IOCLogInfo */
2399
2400                 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2401                 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2402
2403                 /*
2404                  * FC f/w version changed between 1.1 and 1.2
2405                  *      Old: u16{Major(4),Minor(4),SubMinor(8)}
2406                  *      New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2407                  */
2408                 if (facts->MsgVersion < 0x0102) {
2409                         /*
2410                          *      Handle old FC f/w style, convert to new...
2411                          */
2412                         u16      oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2413                         facts->FWVersion.Word =
2414                                         ((oldv<<12) & 0xFF000000) |
2415                                         ((oldv<<8)  & 0x000FFF00);
2416                 } else
2417                         facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2418
2419                 facts->ProductID = le16_to_cpu(facts->ProductID);
2420                 facts->CurrentHostMfaHighAddr =
2421                                 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2422                 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2423                 facts->CurrentSenseBufferHighAddr =
2424                                 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2425                 facts->CurReplyFrameSize =
2426                                 le16_to_cpu(facts->CurReplyFrameSize);
2427                 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2428
2429                 /*
2430                  * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2431                  * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2432                  * to 14 in MPI-1.01.0x.
2433                  */
2434                 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2435                     facts->MsgVersion > 0x0100) {
2436                         facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2437                 }
2438
2439                 sz = facts->FWImageSize;
2440                 if ( sz & 0x01 )
2441                         sz += 1;
2442                 if ( sz & 0x02 )
2443                         sz += 2;
2444                 facts->FWImageSize = sz;
2445
2446                 if (!facts->RequestFrameSize) {
2447                         /*  Something is wrong!  */
2448                         printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2449                                         ioc->name);
2450                         return -55;
2451                 }
2452
2453                 r = sz = facts->BlockSize;
2454                 vv = ((63 / (sz * 4)) + 1) & 0x03;
2455                 ioc->NB_for_64_byte_frame = vv;
2456                 while ( sz )
2457                 {
2458                         shiftFactor++;
2459                         sz = sz >> 1;
2460                 }
2461                 ioc->NBShiftFactor  = shiftFactor;
2462                 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2463                                         ioc->name, vv, shiftFactor, r));
2464
2465                 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2466                         /*
2467                          * Set values for this IOC's request & reply frame sizes,
2468                          * and request & reply queue depths...
2469                          */
2470                         ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2471                         ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2472                         ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2473                         ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2474
2475                         dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2476                                 ioc->name, ioc->reply_sz, ioc->reply_depth));
2477                         dinitprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
2478                                 ioc->name, ioc->req_sz, ioc->req_depth));
2479
2480                         /* Get port facts! */
2481                         if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2482                                 return r;
2483                 }
2484         } else {
2485                 printk(MYIOC_s_ERR_FMT
2486                      "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2487                      ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2488                      RequestFrameSize)/sizeof(u32)));
2489                 return -66;
2490         }
2491
2492         return 0;
2493 }
2494
2495 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2496 /**
2497  *      GetPortFacts - Send PortFacts request to MPT adapter.
2498  *      @ioc: Pointer to MPT_ADAPTER structure
2499  *      @portnum: Port number
2500  *      @sleepFlag: Specifies whether the process can sleep
2501  *
2502  *      Returns 0 for success, non-zero for failure.
2503  */
2504 static int
2505 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2506 {
2507         PortFacts_t              get_pfacts;
2508         PortFactsReply_t        *pfacts;
2509         int                      ii;
2510         int                      req_sz;
2511         int                      reply_sz;
2512         int                      max_id;
2513
2514         /* IOC *must* NOT be in RESET state! */
2515         if (ioc->last_state == MPI_IOC_STATE_RESET) {
2516                 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2517                                 ioc->name,
2518                                 ioc->last_state );
2519                 return -4;
2520         }
2521
2522         pfacts = &ioc->pfacts[portnum];
2523
2524         /* Destination (reply area)...  */
2525         reply_sz = sizeof(*pfacts);
2526         memset(pfacts, 0, reply_sz);
2527
2528         /* Request area (get_pfacts on the stack right now!) */
2529         req_sz = sizeof(get_pfacts);
2530         memset(&get_pfacts, 0, req_sz);
2531
2532         get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2533         get_pfacts.PortNumber = portnum;
2534         /* Assert: All other get_pfacts fields are zero! */
2535
2536         dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2537                         ioc->name, portnum));
2538
2539         /* No non-zero fields in the get_pfacts request are greater than
2540          * 1 byte in size, so we can just fire it off as is.
2541          */
2542         ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2543                                 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2544         if (ii != 0)
2545                 return ii;
2546
2547         /* Did we get a valid reply? */
2548
2549         /* Now byte swap the necessary fields in the response. */
2550         pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2551         pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2552         pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2553         pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2554         pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2555         pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2556         pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2557         pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2558         pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2559
2560         max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
2561             pfacts->MaxDevices;
2562         ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
2563         ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
2564
2565         /*
2566          * Place all the devices on channels
2567          *
2568          * (for debuging)
2569          */
2570         if (mpt_channel_mapping) {
2571                 ioc->devices_per_bus = 1;
2572                 ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
2573         }
2574
2575         return 0;
2576 }
2577
2578 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2579 /**
2580  *      SendIocInit - Send IOCInit request to MPT adapter.
2581  *      @ioc: Pointer to MPT_ADAPTER structure
2582  *      @sleepFlag: Specifies whether the process can sleep
2583  *
2584  *      Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2585  *
2586  *      Returns 0 for success, non-zero for failure.
2587  */
2588 static int
2589 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2590 {
2591         IOCInit_t                ioc_init;
2592         MPIDefaultReply_t        init_reply;
2593         u32                      state;
2594         int                      r;
2595         int                      count;
2596         int                      cntdn;
2597
2598         memset(&ioc_init, 0, sizeof(ioc_init));
2599         memset(&init_reply, 0, sizeof(init_reply));
2600
2601         ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2602         ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2603
2604         /* If we are in a recovery mode and we uploaded the FW image,
2605          * then this pointer is not NULL. Skip the upload a second time.
2606          * Set this flag if cached_fw set for either IOC.
2607          */
2608         if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2609                 ioc->upload_fw = 1;
2610         else
2611                 ioc->upload_fw = 0;
2612         ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2613                    ioc->name, ioc->upload_fw, ioc->facts.Flags));
2614
2615         ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
2616         ioc_init.MaxBuses = (U8)ioc->number_of_buses;
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);
2623
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;
2628         }
2629         ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);   /* in BYTES */
2630
2631         if (sizeof(dma_addr_t) == sizeof(u64)) {
2632                 /* Save the upper 32-bits of the request
2633                  * (reply) and sense buffers.
2634                  */
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);
2641         }
2642
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;
2647
2648         dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2649                         ioc->name, &ioc_init));
2650
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;
2656         }
2657
2658         /* No need to byte swap the multibyte fields in the reply
2659          * since we don't even look at its contents.
2660          */
2661
2662         dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2663                         ioc->name, &ioc_init));
2664
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;
2668         }
2669
2670         /* YIKES!  SUPER IMPORTANT!!!
2671          *  Poll IocState until _OPERATIONAL while IOC is doing
2672          *  LoopInit and TargetDiscovery!
2673          */
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(1);
2680                 } else {
2681                         mdelay(1);
2682                 }
2683
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;
2688                 }
2689
2690                 state = mpt_GetIocState(ioc, 1);
2691                 count++;
2692         }
2693         dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2694                         ioc->name, count));
2695
2696         ioc->aen_event_read_flag=0;
2697         return r;
2698 }
2699
2700 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2701 /**
2702  *      SendPortEnable - Send PortEnable request to MPT adapter port.
2703  *      @ioc: Pointer to MPT_ADAPTER structure
2704  *      @portnum: Port number to enable
2705  *      @sleepFlag: Specifies whether the process can sleep
2706  *
2707  *      Send PortEnable to bring IOC to OPERATIONAL state.
2708  *
2709  *      Returns 0 for success, non-zero for failure.
2710  */
2711 static int
2712 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2713 {
2714         PortEnable_t             port_enable;
2715         MPIDefaultReply_t        reply_buf;
2716         int      rc;
2717         int      req_sz;
2718         int      reply_sz;
2719
2720         /*  Destination...  */
2721         reply_sz = sizeof(MPIDefaultReply_t);
2722         memset(&reply_buf, 0, reply_sz);
2723
2724         req_sz = sizeof(PortEnable_t);
2725         memset(&port_enable, 0, req_sz);
2726
2727         port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2728         port_enable.PortNumber = portnum;
2729 /*      port_enable.ChainOffset = 0;            */
2730 /*      port_enable.MsgFlags = 0;               */
2731 /*      port_enable.MsgContext = 0;             */
2732
2733         dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2734                         ioc->name, portnum, &port_enable));
2735
2736         /* RAID FW may take a long time to enable
2737          */
2738         if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2739             > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
2740             (ioc->bus_type == SAS)) {
2741                 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2742                 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2743                 300 /*seconds*/, sleepFlag);
2744         } else {
2745                 rc = mpt_handshake_req_reply_wait(ioc, req_sz,
2746                 (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
2747                 30 /*seconds*/, sleepFlag);
2748         }
2749         return rc;
2750 }
2751
2752 /**
2753  *      mpt_alloc_fw_memory - allocate firmware memory
2754  *      @ioc: Pointer to MPT_ADAPTER structure
2755  *      @size: total FW bytes
2756  *
2757  *      If memory has already been allocated, the same (cached) value
2758  *      is returned.
2759  */
2760 void
2761 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2762 {
2763         if (ioc->cached_fw)
2764                 return;  /* use already allocated memory */
2765         if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2766                 ioc->cached_fw = ioc->alt_ioc->cached_fw;  /* use alt_ioc's memory */
2767                 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2768                 ioc->alloc_total += size;
2769                 ioc->alt_ioc->alloc_total -= size;
2770         } else {
2771                 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2772                         ioc->alloc_total += size;
2773         }
2774 }
2775 /**
2776  *      mpt_free_fw_memory - free firmware memory
2777  *      @ioc: Pointer to MPT_ADAPTER structure
2778  *
2779  *      If alt_img is NULL, delete from ioc structure.
2780  *      Else, delete a secondary image in same format.
2781  */
2782 void
2783 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2784 {
2785         int sz;
2786
2787         sz = ioc->facts.FWImageSize;
2788         dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
2789                  ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2790         pci_free_consistent(ioc->pcidev, sz,
2791                         ioc->cached_fw, ioc->cached_fw_dma);
2792         ioc->cached_fw = NULL;
2793
2794         return;
2795 }
2796
2797
2798 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2799 /**
2800  *      mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2801  *      @ioc: Pointer to MPT_ADAPTER structure
2802  *      @sleepFlag: Specifies whether the process can sleep
2803  *
2804  *      Returns 0 for success, >0 for handshake failure
2805  *              <0 for fw upload failure.
2806  *
2807  *      Remark: If bound IOC and a successful FWUpload was performed
2808  *      on the bound IOC, the second image is discarded
2809  *      and memory is free'd. Both channels must upload to prevent
2810  *      IOC from running in degraded mode.
2811  */
2812 static int
2813 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2814 {
2815         u8                       request[ioc->req_sz];
2816         u8                       reply[sizeof(FWUploadReply_t)];
2817         FWUpload_t              *prequest;
2818         FWUploadReply_t         *preply;
2819         FWUploadTCSGE_t         *ptcsge;
2820         int                      sgeoffset;
2821         u32                      flagsLength;
2822         int                      ii, sz, reply_sz;
2823         int                      cmdStatus;
2824
2825         /* If the image size is 0, we are done.
2826          */
2827         if ((sz = ioc->facts.FWImageSize) == 0)
2828                 return 0;
2829
2830         mpt_alloc_fw_memory(ioc, sz);
2831
2832         dinitprintk((KERN_INFO MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
2833                  ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2834
2835         if (ioc->cached_fw == NULL) {
2836                 /* Major Failure.
2837                  */
2838                 return -ENOMEM;
2839         }
2840
2841         prequest = (FWUpload_t *)&request;
2842         preply = (FWUploadReply_t *)&reply;
2843
2844         /*  Destination...  */
2845         memset(prequest, 0, ioc->req_sz);
2846
2847         reply_sz = sizeof(reply);
2848         memset(preply, 0, reply_sz);
2849
2850         prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2851         prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2852
2853         ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2854         ptcsge->DetailsLength = 12;
2855         ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2856         ptcsge->ImageSize = cpu_to_le32(sz);
2857
2858         sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2859
2860         flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2861         mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2862
2863         sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2864         dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
2865                         prequest, sgeoffset));
2866         DBG_DUMP_FW_REQUEST_FRAME(prequest)
2867
2868         ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2869                                 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2870
2871         dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2872
2873         cmdStatus = -EFAULT;
2874         if (ii == 0) {
2875                 /* Handshake transfer was complete and successful.
2876                  * Check the Reply Frame.
2877                  */
2878                 int status, transfer_sz;
2879                 status = le16_to_cpu(preply->IOCStatus);
2880                 if (status == MPI_IOCSTATUS_SUCCESS) {
2881                         transfer_sz = le32_to_cpu(preply->ActualImageSize);
2882                         if (transfer_sz == sz)
2883                                 cmdStatus = 0;
2884                 }
2885         }
2886         dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2887                         ioc->name, cmdStatus));
2888
2889
2890         if (cmdStatus) {
2891
2892                 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2893                         ioc->name));
2894                 mpt_free_fw_memory(ioc);
2895         }
2896
2897         return cmdStatus;
2898 }
2899
2900 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2901 /**
2902  *      mpt_downloadboot - DownloadBoot code
2903  *      @ioc: Pointer to MPT_ADAPTER structure
2904  *      @pFwHeader: Pointer to firmware header info
2905  *      @sleepFlag: Specifies whether the process can sleep
2906  *
2907  *      FwDownloadBoot requires Programmed IO access.
2908  *
2909  *      Returns 0 for success
2910  *              -1 FW Image size is 0
2911  *              -2 No valid cached_fw Pointer
2912  *              <0 for fw upload failure.
2913  */
2914 static int
2915 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
2916 {
2917         MpiExtImageHeader_t     *pExtImage;
2918         u32                      fwSize;
2919         u32                      diag0val;
2920         int                      count;
2921         u32                     *ptrFw;
2922         u32                      diagRwData;
2923         u32                      nextImage;
2924         u32                      load_addr;
2925         u32                      ioc_state=0;
2926
2927         ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2928                                 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
2929
2930         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2931         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2932         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2933         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2934         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2935         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2936
2937         CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2938
2939         /* wait 1 msec */
2940         if (sleepFlag == CAN_SLEEP) {
2941                 msleep(1);
2942         } else {
2943                 mdelay (1);
2944         }
2945
2946         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2947         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2948
2949         for (count = 0; count < 30; count ++) {
2950                 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2951                 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2952                         ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2953                                 ioc->name, count));
2954                         break;
2955                 }
2956                 /* wait .1 sec */
2957                 if (sleepFlag == CAN_SLEEP) {
2958                         msleep (100);
2959                 } else {
2960                         mdelay (100);
2961                 }
2962         }
2963
2964         if ( count == 30 ) {
2965                 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2966                 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
2967                 ioc->name, diag0val));
2968                 return -3;
2969         }
2970
2971         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2972         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2973         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2974         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2975         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2976         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2977
2978         /* Set the DiagRwEn and Disable ARM bits */
2979         CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2980
2981         fwSize = (pFwHeader->ImageSize + 3)/4;
2982         ptrFw = (u32 *) pFwHeader;
2983
2984         /* Write the LoadStartAddress to the DiagRw Address Register
2985          * using Programmed IO
2986          */
2987         if (ioc->errata_flag_1064)
2988                 pci_enable_io_access(ioc->pcidev);
2989
2990         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2991         ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2992                 ioc->name, pFwHeader->LoadStartAddress));
2993
2994         ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2995                                 ioc->name, fwSize*4, ptrFw));
2996         while (fwSize--) {
2997                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2998         }
2999
3000         nextImage = pFwHeader->NextImageHeaderOffset;
3001         while (nextImage) {
3002                 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3003
3004                 load_addr = pExtImage->LoadStartAddress;
3005
3006                 fwSize = (pExtImage->ImageSize + 3) >> 2;
3007                 ptrFw = (u32 *)pExtImage;
3008
3009                 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3010                                                 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3011                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3012
3013                 while (fwSize--) {
3014                         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3015                 }
3016                 nextImage = pExtImage->NextImageHeaderOffset;
3017         }
3018
3019         /* Write the IopResetVectorRegAddr */
3020         ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name,      pFwHeader->IopResetRegAddr));
3021         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3022
3023         /* Write the IopResetVectorValue */
3024         ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3025         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3026
3027         /* Clear the internal flash bad bit - autoincrementing register,
3028          * so must do two writes.
3029          */
3030         if (ioc->bus_type == SPI) {
3031                 /*
3032                  * 1030 and 1035 H/W errata, workaround to access
3033                  * the ClearFlashBadSignatureBit
3034                  */
3035                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3036                 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3037                 diagRwData |= 0x40000000;
3038                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3039                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3040
3041         } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3042                 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3043                 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3044                     MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3045
3046                 /* wait 1 msec */
3047                 if (sleepFlag == CAN_SLEEP) {
3048                         msleep (1);
3049                 } else {
3050                         mdelay (1);
3051                 }
3052         }
3053
3054         if (ioc->errata_flag_1064)
3055                 pci_disable_io_access(ioc->pcidev);
3056
3057         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3058         ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3059                 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3060                 ioc->name, diag0val));
3061         diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3062         ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3063                 ioc->name, diag0val));
3064         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3065
3066         /* Write 0xFF to reset the sequencer */
3067         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3068
3069         if (ioc->bus_type == SAS) {
3070                 ioc_state = mpt_GetIocState(ioc, 0);
3071                 if ( (GetIocFacts(ioc, sleepFlag,
3072                                 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3073                         ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3074                                         ioc->name, ioc_state));
3075                         return -EFAULT;
3076                 }
3077         }
3078
3079         for (count=0; count<HZ*20; count++) {
3080                 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3081                         ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3082                                         ioc->name, count, ioc_state));
3083                         if (ioc->bus_type == SAS) {
3084                                 return 0;
3085                         }
3086                         if ((SendIocInit(ioc, sleepFlag)) != 0) {
3087                                 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3088                                         ioc->name));
3089                                 return -EFAULT;
3090                         }
3091                         ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3092                                         ioc->name));
3093                         return 0;
3094                 }
3095                 if (sleepFlag == CAN_SLEEP) {
3096                         msleep (10);
3097                 } else {
3098                         mdelay (10);
3099                 }
3100         }
3101         ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3102                 ioc->name, ioc_state));
3103         return -EFAULT;
3104 }
3105
3106 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3107 /**
3108  *      KickStart - Perform hard reset of MPT adapter.
3109  *      @ioc: Pointer to MPT_ADAPTER structure
3110  *      @force: Force hard reset
3111  *      @sleepFlag: Specifies whether the process can sleep
3112  *
3113  *      This routine places MPT adapter in diagnostic mode via the
3114  *      WriteSequence register, and then performs a hard reset of adapter
3115  *      via the Diagnostic register.
3116  *
3117  *      Inputs:   sleepflag - CAN_SLEEP (non-interrupt thread)
3118  *                      or NO_SLEEP (interrupt thread, use mdelay)
3119  *                force - 1 if doorbell active, board fault state
3120  *                              board operational, IOC_RECOVERY or
3121  *                              IOC_BRINGUP and there is an alt_ioc.
3122  *                        0 else
3123  *
3124  *      Returns:
3125  *               1 - hard reset, READY
3126  *               0 - no reset due to History bit, READY
3127  *              -1 - no reset due to History bit but not READY
3128  *                   OR reset but failed to come READY
3129  *              -2 - no reset, could not enter DIAG mode
3130  *              -3 - reset but bad FW bit
3131  */
3132 static int
3133 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3134 {
3135         int hard_reset_done = 0;
3136         u32 ioc_state=0;
3137         int cnt,cntdn;
3138
3139         dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3140         if (ioc->bus_type == SPI) {
3141                 /* Always issue a Msg Unit Reset first. This will clear some
3142                  * SCSI bus hang conditions.
3143                  */
3144                 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3145
3146                 if (sleepFlag == CAN_SLEEP) {
3147                         msleep (1000);
3148                 } else {
3149                         mdelay (1000);
3150                 }
3151         }
3152
3153         hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3154         if (hard_reset_done < 0)
3155                 return hard_reset_done;
3156
3157         dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3158                         ioc->name));
3159
3160         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;     /* 2 seconds */
3161         for (cnt=0; cnt<cntdn; cnt++) {
3162                 ioc_state = mpt_GetIocState(ioc, 1);
3163                 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3164                         dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3165                                         ioc->name, cnt));
3166                         return hard_reset_done;
3167                 }
3168                 if (sleepFlag == CAN_SLEEP) {
3169                         msleep (10);
3170                 } else {
3171                         mdelay (10);
3172                 }
3173         }
3174
3175         printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3176                         ioc->name, ioc_state);
3177         return -1;
3178 }
3179
3180 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3181 /**
3182  *      mpt_diag_reset - Perform hard reset of the adapter.
3183  *      @ioc: Pointer to MPT_ADAPTER structure
3184  *      @ignore: Set if to honor and clear to ignore
3185  *              the reset history bit
3186  *      @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3187  *              else set to NO_SLEEP (use mdelay instead)
3188  *
3189  *      This routine places the adapter in diagnostic mode via the
3190  *      WriteSequence register and then performs a hard reset of adapter
3191  *      via the Diagnostic register. Adapter should be in ready state
3192  *      upon successful completion.
3193  *
3194  *      Returns:  1  hard reset successful
3195  *                0  no reset performed because reset history bit set
3196  *               -2  enabling diagnostic mode failed
3197  *               -3  diagnostic reset failed
3198  */
3199 static int
3200 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3201 {
3202         MPT_ADAPTER     *iocp=NULL;
3203         u32 diag0val;
3204         u32 doorbell;
3205         int hard_reset_done = 0;
3206         int count = 0;
3207 #ifdef MPT_DEBUG
3208         u32 diag1val = 0;
3209 #endif
3210
3211         if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3212                 drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3213                         "address=%p\n",  ioc->name, __FUNCTION__,
3214                         &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3215                 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3216                 if (sleepFlag == CAN_SLEEP)
3217                         msleep(1);
3218                 else
3219                         mdelay(1);
3220
3221                 for (count = 0; count < 60; count ++) {
3222                         doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3223                         doorbell &= MPI_IOC_STATE_MASK;
3224
3225                         drsprintk((MYIOC_s_INFO_FMT
3226                                 "looking for READY STATE: doorbell=%x"
3227                                 " count=%d\n",
3228                                 ioc->name, doorbell, count));
3229                         if (doorbell == MPI_IOC_STATE_READY) {
3230                                 return 0;
3231                         }
3232
3233                         /* wait 1 sec */
3234                         if (sleepFlag == CAN_SLEEP)
3235                                 msleep(1000);
3236                         else
3237                                 mdelay(1000);
3238                 }
3239                 return -1;
3240         }
3241
3242         /* Clear any existing interrupts */
3243         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3244
3245         /* Use "Diagnostic reset" method! (only thing available!) */
3246         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3247
3248 #ifdef MPT_DEBUG
3249         if (ioc->alt_ioc)
3250                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3251         dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3252                         ioc->name, diag0val, diag1val));
3253 #endif
3254
3255         /* Do the reset if we are told to ignore the reset history
3256          * or if the reset history is 0
3257          */
3258         if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3259                 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3260                         /* Write magic sequence to WriteSequence register
3261                          * Loop until in diagnostic mode
3262                          */
3263                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3264                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3265                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3266                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3267                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3268                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3269
3270                         /* wait 100 msec */
3271                         if (sleepFlag == CAN_SLEEP) {
3272                                 msleep (100);
3273                         } else {
3274                                 mdelay (100);
3275                         }
3276
3277                         count++;
3278                         if (count > 20) {
3279                                 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3280                                                 ioc->name, diag0val);
3281                                 return -2;
3282
3283                         }
3284
3285                         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3286
3287                         dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3288                                         ioc->name, diag0val));
3289                 }
3290
3291 #ifdef MPT_DEBUG
3292                 if (ioc->alt_ioc)
3293                         diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3294                 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3295                                 ioc->name, diag0val, diag1val));
3296 #endif
3297                 /*
3298                  * Disable the ARM (Bug fix)
3299                  *
3300                  */
3301                 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3302                 mdelay(1);
3303
3304                 /*
3305                  * Now hit the reset bit in the Diagnostic register
3306                  * (THE BIG HAMMER!) (Clears DRWE bit).
3307                  */
3308                 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3309                 hard_reset_done = 1;
3310                 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3311                                 ioc->name));
3312
3313                 /*
3314                  * Call each currently registered protocol IOC reset handler
3315                  * with pre-reset indication.
3316                  * NOTE: If we're doing _IOC_BRINGUP, there can be no
3317                  * MptResetHandlers[] registered yet.
3318                  */
3319                 {
3320                         int      ii;
3321                         int      r = 0;
3322
3323                         for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3324                                 if (MptResetHandlers[ii]) {
3325                                         dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3326                                                         ioc->name, ii));
3327                                         r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
3328                                         if (ioc->alt_ioc) {
3329                                                 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3330                                                                 ioc->name, ioc->alt_ioc->name, ii));
3331                                                 r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3332                                         }
3333                                 }
3334                         }
3335                         /* FIXME?  Examine results here? */
3336                 }
3337
3338                 if (ioc->cached_fw)
3339                         iocp = ioc;
3340                 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3341                         iocp = ioc->alt_ioc;
3342                 if (iocp) {
3343                         /* If the DownloadBoot operation fails, the
3344                          * IOC will be left unusable. This is a fatal error
3345                          * case.  _diag_reset will return < 0
3346                          */
3347                         for (count = 0; count < 30; count ++) {
3348                                 diag0val = CHIPREG_READ32(&iocp->chip->Diagnostic);
3349                                 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3350                                         break;
3351                                 }
3352
3353                                 dprintk((MYIOC_s_INFO_FMT "cached_fw: diag0val=%x count=%d\n",
3354                                         iocp->name, diag0val, count));
3355                                 /* wait 1 sec */
3356                                 if (sleepFlag == CAN_SLEEP) {
3357                                         msleep (1000);
3358                                 } else {
3359                                         mdelay (1000);
3360                                 }
3361                         }
3362                         if ((count = mpt_downloadboot(ioc,
3363                                 (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
3364                                 printk(KERN_WARNING MYNAM
3365                                         ": firmware downloadboot failure (%d)!\n", count);
3366                         }
3367
3368                 } else {
3369                         /* Wait for FW to reload and for board
3370                          * to go to the READY state.
3371                          * Maximum wait is 60 seconds.
3372                          * If fail, no error will check again
3373                          * with calling program.
3374                          */
3375                         for (count = 0; count < 60; count ++) {
3376                                 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3377                                 doorbell &= MPI_IOC_STATE_MASK;
3378
3379                                 if (doorbell == MPI_IOC_STATE_READY) {
3380                                         break;
3381                                 }
3382
3383                                 /* wait 1 sec */
3384                                 if (sleepFlag == CAN_SLEEP) {
3385                                         msleep (1000);
3386                                 } else {
3387                                         mdelay (1000);
3388                                 }
3389                         }
3390                 }
3391         }
3392
3393         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3394 #ifdef MPT_DEBUG
3395         if (ioc->alt_ioc)
3396                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3397         dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3398                 ioc->name, diag0val, diag1val));
3399 #endif
3400
3401         /* Clear RESET_HISTORY bit!  Place board in the
3402          * diagnostic mode to update the diag register.
3403          */
3404         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3405         count = 0;
3406         while ((diag0val & MPI_DIAG_DRWE) == 0) {
3407                 /* Write magic sequence to WriteSequence register
3408                  * Loop until in diagnostic mode
3409                  */
3410                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3411                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3412                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3413                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3414                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3415                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3416
3417                 /* wait 100 msec */
3418                 if (sleepFlag == CAN_SLEEP) {
3419                         msleep (100);
3420                 } else {
3421                         mdelay (100);
3422                 }
3423
3424                 count++;
3425                 if (count > 20) {
3426                         printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3427                                         ioc->name, diag0val);
3428                         break;
3429                 }
3430                 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3431         }
3432         diag0val &= ~MPI_DIAG_RESET_HISTORY;
3433         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3434         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3435         if (diag0val & MPI_DIAG_RESET_HISTORY) {
3436                 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3437                                 ioc->name);
3438         }
3439
3440         /* Disable Diagnostic Mode
3441          */
3442         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3443
3444         /* Check FW reload status flags.
3445          */
3446         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3447         if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3448                 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3449                                 ioc->name, diag0val);
3450                 return -3;
3451         }
3452
3453 #ifdef MPT_DEBUG
3454         if (ioc->alt_ioc)
3455                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3456         dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3457                         ioc->name, diag0val, diag1val));
3458 #endif
3459
3460         /*
3461          * Reset flag that says we've enabled event notification
3462          */
3463         ioc->facts.EventState = 0;
3464
3465         if (ioc->alt_ioc)
3466                 ioc->alt_ioc->facts.EventState = 0;
3467
3468         return hard_reset_done;
3469 }
3470
3471 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3472 /**
3473  *      SendIocReset - Send IOCReset request to MPT adapter.
3474  *      @ioc: Pointer to MPT_ADAPTER structure
3475  *      @reset_type: reset type, expected values are
3476  *      %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3477  *      @sleepFlag: Specifies whether the process can sleep
3478  *
3479  *      Send IOCReset request to the MPT adapter.
3480  *
3481  *      Returns 0 for success, non-zero for failure.
3482  */
3483 static int
3484 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3485 {
3486         int r;
3487         u32 state;
3488         int cntdn, count;
3489
3490         drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3491                         ioc->name, reset_type));
3492         CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3493         if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3494                 return r;
3495
3496         /* FW ACK'd request, wait for READY state
3497          */
3498         count = 0;
3499         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15;    /* 15 seconds */
3500
3501         while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3502                 cntdn--;
3503                 count++;
3504                 if (!cntdn) {
3505                         if (sleepFlag != CAN_SLEEP)
3506                                 count *= 10;
3507
3508                         printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3509                                         ioc->name, (int)((count+5)/HZ));
3510                         return -ETIME;
3511                 }
3512
3513                 if (sleepFlag == CAN_SLEEP) {
3514                         msleep(1);
3515                 } else {
3516                         mdelay (1);     /* 1 msec delay */
3517                 }
3518         }
3519
3520         /* TODO!
3521          *  Cleanup all event stuff for this IOC; re-issue EventNotification
3522          *  request if needed.
3523          */
3524         if (ioc->facts.Function)
3525                 ioc->facts.EventState = 0;
3526
3527         return 0;
3528 }
3529
3530 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3531 /**
3532  *      initChainBuffers - Allocate memory for and initialize chain buffers
3533  *      @ioc: Pointer to MPT_ADAPTER structure
3534  *
3535  *      Allocates memory for and initializes chain buffers,
3536  *      chain buffer control arrays and spinlock.
3537  */
3538 static int
3539 initChainBuffers(MPT_ADAPTER *ioc)
3540 {
3541         u8              *mem;
3542         int             sz, ii, num_chain;
3543         int             scale, num_sge, numSGE;
3544
3545         /* ReqToChain size must equal the req_depth
3546          * index = req_idx
3547          */
3548         if (ioc->ReqToChain == NULL) {
3549                 sz = ioc->req_depth * sizeof(int);
3550                 mem = kmalloc(sz, GFP_ATOMIC);
3551                 if (mem == NULL)
3552                         return -1;
3553
3554                 ioc->ReqToChain = (int *) mem;
3555                 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc  @ %p, sz=%d bytes\n",
3556                                 ioc->name, mem, sz));
3557                 mem = kmalloc(sz, GFP_ATOMIC);
3558                 if (mem == NULL)
3559                         return -1;
3560
3561                 ioc->RequestNB = (int *) mem;
3562                 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc  @ %p, sz=%d bytes\n",
3563                                 ioc->name, mem, sz));
3564         }
3565         for (ii = 0; ii < ioc->req_depth; ii++) {
3566                 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3567         }
3568
3569         /* ChainToChain size must equal the total number
3570          * of chain buffers to be allocated.
3571          * index = chain_idx
3572          *
3573          * Calculate the number of chain buffers needed(plus 1) per I/O
3574          * then multiply the the maximum number of simultaneous cmds
3575          *
3576          * num_sge = num sge in request frame + last chain buffer
3577          * scale = num sge per chain buffer if no chain element
3578          */
3579         scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3580         if (sizeof(dma_addr_t) == sizeof(u64))
3581                 num_sge =  scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3582         else
3583                 num_sge =  1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3584
3585         if (sizeof(dma_addr_t) == sizeof(u64)) {
3586                 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3587                         (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3588         } else {
3589                 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3590                         (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3591         }
3592         dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3593                 ioc->name, num_sge, numSGE));
3594
3595         if ( numSGE > MPT_SCSI_SG_DEPTH )
3596                 numSGE = MPT_SCSI_SG_DEPTH;
3597
3598         num_chain = 1;
3599         while (numSGE - num_sge > 0) {
3600                 num_chain++;
3601                 num_sge += (scale - 1);
3602         }
3603         num_chain++;
3604
3605         dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3606                 ioc->name, numSGE, num_sge, num_chain));
3607
3608         if (ioc->bus_type == SPI)
3609                 num_chain *= MPT_SCSI_CAN_QUEUE;
3610         else
3611                 num_chain *= MPT_FC_CAN_QUEUE;
3612
3613         ioc->num_chain = num_chain;
3614
3615         sz = num_chain * sizeof(int);
3616         if (ioc->ChainToChain == NULL) {
3617                 mem = kmalloc(sz, GFP_ATOMIC);
3618                 if (mem == NULL)
3619                         return -1;
3620
3621                 ioc->ChainToChain = (int *) mem;
3622                 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3623                                 ioc->name, mem, sz));
3624         } else {
3625                 mem = (u8 *) ioc->ChainToChain;
3626         }
3627         memset(mem, 0xFF, sz);
3628         return num_chain;
3629 }
3630
3631 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3632 /**
3633  *      PrimeIocFifos - Initialize IOC request and reply FIFOs.
3634  *      @ioc: Pointer to MPT_ADAPTER structure
3635  *
3636  *      This routine allocates memory for the MPT reply and request frame
3637  *      pools (if necessary), and primes the IOC reply FIFO with
3638  *      reply frames.
3639  *
3640  *      Returns 0 for success, non-zero for failure.
3641  */
3642 static int
3643 PrimeIocFifos(MPT_ADAPTER *ioc)
3644 {
3645         MPT_FRAME_HDR *mf;
3646         unsigned long flags;
3647         dma_addr_t alloc_dma;
3648         u8 *mem;
3649         int i, reply_sz, sz, total_size, num_chain;
3650
3651         /*  Prime reply FIFO...  */
3652
3653         if (ioc->reply_frames == NULL) {
3654                 if ( (num_chain = initChainBuffers(ioc)) < 0)
3655                         return -1;
3656
3657                 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3658                 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3659                                 ioc->name, ioc->reply_sz, ioc->reply_depth));
3660                 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3661                                 ioc->name, reply_sz, reply_sz));
3662
3663                 sz = (ioc->req_sz * ioc->req_depth);
3664                 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3665                                 ioc->name, ioc->req_sz, ioc->req_depth));
3666                 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3667                                 ioc->name, sz, sz));
3668                 total_size += sz;
3669
3670                 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3671                 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3672                                 ioc->name, ioc->req_sz, num_chain));
3673                 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3674                                 ioc->name, sz, sz, num_chain));
3675
3676                 total_size += sz;
3677                 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3678                 if (mem == NULL) {
3679                         printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3680                                 ioc->name);
3681                         goto out_fail;
3682                 }
3683
3684                 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3685                                 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3686
3687                 memset(mem, 0, total_size);
3688                 ioc->alloc_total += total_size;
3689                 ioc->alloc = mem;
3690                 ioc->alloc_dma = alloc_dma;
3691                 ioc->alloc_sz = total_size;
3692                 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3693                 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3694
3695                 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3696                         ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3697
3698                 alloc_dma += reply_sz;
3699                 mem += reply_sz;
3700
3701                 /*  Request FIFO - WE manage this!  */
3702
3703                 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3704                 ioc->req_frames_dma = alloc_dma;
3705
3706                 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3707                                 ioc->name, mem, (void *)(ulong)alloc_dma));
3708
3709                 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3710
3711 #if defined(CONFIG_MTRR) && 0
3712                 /*
3713                  *  Enable Write Combining MTRR for IOC's memory region.
3714                  *  (at least as much as we can; "size and base must be
3715                  *  multiples of 4 kiB"
3716                  */
3717                 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3718                                          sz,
3719                                          MTRR_TYPE_WRCOMB, 1);
3720                 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3721                                 ioc->name, ioc->req_frames_dma, sz));
3722 #endif
3723
3724                 for (i = 0; i < ioc->req_depth; i++) {
3725                         alloc_dma += ioc->req_sz;
3726                         mem += ioc->req_sz;
3727                 }
3728
3729                 ioc->ChainBuffer = mem;
3730                 ioc->ChainBufferDMA = alloc_dma;
3731
3732                 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3733                         ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3734
3735                 /* Initialize the free chain Q.
3736                 */
3737
3738                 INIT_LIST_HEAD(&ioc->FreeChainQ);
3739
3740                 /* Post the chain buffers to the FreeChainQ.
3741                 */
3742                 mem = (u8 *)ioc->ChainBuffer;
3743                 for (i=0; i < num_chain; i++) {
3744                         mf = (MPT_FRAME_HDR *) mem;
3745                         list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3746                         mem += ioc->req_sz;
3747                 }
3748
3749                 /* Initialize Request frames linked list
3750                  */
3751                 alloc_dma = ioc->req_frames_dma;
3752                 mem = (u8 *) ioc->req_frames;
3753
3754                 spin_lock_irqsave(&ioc->FreeQlock, flags);
3755                 INIT_LIST_HEAD(&ioc->FreeQ);
3756                 for (i = 0; i < ioc->req_depth; i++) {
3757                         mf = (MPT_FRAME_HDR *) mem;
3758
3759                         /*  Queue REQUESTs *internally*!  */
3760                         list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3761
3762                         mem += ioc->req_sz;
3763                 }
3764                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3765
3766                 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3767                 ioc->sense_buf_pool =
3768                         pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3769                 if (ioc->sense_buf_pool == NULL) {
3770                         printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3771                                 ioc->name);
3772                         goto out_fail;
3773                 }
3774
3775                 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3776                 ioc->alloc_total += sz;
3777                 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3778                         ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3779
3780         }
3781
3782         /* Post Reply frames to FIFO
3783          */
3784         alloc_dma = ioc->alloc_dma;
3785         dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3786                 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3787
3788         for (i = 0; i < ioc->reply_depth; i++) {
3789                 /*  Write each address to the IOC!  */
3790                 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3791                 alloc_dma += ioc->reply_sz;
3792         }
3793
3794         return 0;
3795
3796 out_fail:
3797         if (ioc->alloc != NULL) {
3798                 sz = ioc->alloc_sz;
3799                 pci_free_consistent(ioc->pcidev,
3800                                 sz,
3801                                 ioc->alloc, ioc->alloc_dma);
3802                 ioc->reply_frames = NULL;
3803                 ioc->req_frames = NULL;
3804                 ioc->alloc_total -= sz;
3805         }
3806         if (ioc->sense_buf_pool != NULL) {
3807                 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3808                 pci_free_consistent(ioc->pcidev,
3809                                 sz,
3810                                 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3811                 ioc->sense_buf_pool = NULL;
3812         }
3813         return -1;
3814 }
3815
3816 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3817 /**
3818  *      mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3819  *      from IOC via doorbell handshake method.
3820  *      @ioc: Pointer to MPT_ADAPTER structure
3821  *      @reqBytes: Size of the request in bytes
3822  *      @req: Pointer to MPT request frame
3823  *      @replyBytes: Expected size of the reply in bytes
3824  *      @u16reply: Pointer to area where reply should be written
3825  *      @maxwait: Max wait time for a reply (in seconds)
3826  *      @sleepFlag: Specifies whether the process can sleep
3827  *
3828  *      NOTES: It is the callers responsibility to byte-swap fields in the
3829  *      request which are greater than 1 byte in size.  It is also the
3830  *      callers responsibility to byte-swap response fields which are
3831  *      greater than 1 byte in size.
3832  *
3833  *      Returns 0 for success, non-zero for failure.
3834  */
3835 static int
3836 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3837                 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3838 {
3839         MPIDefaultReply_t *mptReply;
3840         int failcnt = 0;
3841         int t;
3842
3843         /*
3844          * Get ready to cache a handshake reply
3845          */
3846         ioc->hs_reply_idx = 0;
3847         mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3848         mptReply->MsgLength = 0;
3849
3850         /*
3851          * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3852          * then tell IOC that we want to handshake a request of N words.
3853          * (WRITE u32val to Doorbell reg).
3854          */
3855         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3856         CHIPREG_WRITE32(&ioc->chip->Doorbell,
3857                         ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3858                          ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3859
3860         /*
3861          * Wait for IOC's doorbell handshake int
3862          */
3863         if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3864                 failcnt++;
3865
3866         dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3867                         ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3868
3869         /* Read doorbell and check for active bit */
3870         if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3871                         return -1;
3872
3873         /*
3874          * Clear doorbell int (WRITE 0 to IntStatus reg),
3875          * then wait for IOC to ACKnowledge that it's ready for
3876          * our handshake request.
3877          */
3878         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3879         if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3880                 failcnt++;
3881
3882         if (!failcnt) {
3883                 int      ii;
3884                 u8      *req_as_bytes = (u8 *) req;
3885
3886                 /*
3887                  * Stuff request words via doorbell handshake,
3888                  * with ACK from IOC for each.
3889                  */
3890                 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3891                         u32 word = ((req_as_bytes[(ii*4) + 0] <<  0) |
3892                                     (req_as_bytes[(ii*4) + 1] <<  8) |
3893                                     (req_as_bytes[(ii*4) + 2] << 16) |
3894                                     (req_as_bytes[(ii*4) + 3] << 24));
3895
3896                         CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3897                         if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3898                                 failcnt++;
3899                 }
3900
3901                 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3902                 DBG_DUMP_REQUEST_FRAME_HDR(req)
3903
3904                 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3905                                 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3906
3907                 /*
3908                  * Wait for completion of doorbell handshake reply from the IOC
3909                  */
3910                 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3911                         failcnt++;
3912
3913                 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3914                                 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3915
3916                 /*
3917                  * Copy out the cached reply...
3918                  */
3919                 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3920                         u16reply[ii] = ioc->hs_reply[ii];
3921         } else {
3922                 return -99;
3923         }
3924
3925         return -failcnt;
3926 }
3927
3928 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3929 /**
3930  *      WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
3931  *      @ioc: Pointer to MPT_ADAPTER structure
3932  *      @howlong: How long to wait (in seconds)
3933  *      @sleepFlag: Specifies whether the process can sleep
3934  *
3935  *      This routine waits (up to ~2 seconds max) for IOC doorbell
3936  *      handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
3937  *      bit in its IntStatus register being clear.
3938  *
3939  *      Returns a negative value on failure, else wait loop count.
3940  */
3941 static int
3942 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3943 {
3944         int cntdn;
3945         int count = 0;
3946         u32 intstat=0;
3947
3948         cntdn = 1000 * howlong;
3949
3950         if (sleepFlag == CAN_SLEEP) {
3951                 while (--cntdn) {
3952                         msleep (1);
3953                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3954                         if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3955                                 break;
3956                         count++;
3957                 }
3958         } else {
3959                 while (--cntdn) {
3960                         mdelay (1);
3961                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3962                         if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3963                                 break;
3964                         count++;
3965                 }
3966         }
3967
3968         if (cntdn) {
3969                 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3970                                 ioc->name, count));
3971                 return count;
3972         }
3973
3974         printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3975                         ioc->name, count, intstat);
3976         return -1;
3977 }
3978
3979 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3980 /**
3981  *      WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
3982  *      @ioc: Pointer to MPT_ADAPTER structure
3983  *      @howlong: How long to wait (in seconds)
3984  *      @sleepFlag: Specifies whether the process can sleep
3985  *
3986  *      This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
3987  *      (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
3988  *
3989  *      Returns a negative value on failure, else wait loop count.
3990  */
3991 static int
3992 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3993 {
3994         int cntdn;
3995         int count = 0;
3996         u32 intstat=0;
3997
3998         cntdn = 1000 * howlong;
3999         if (sleepFlag == CAN_SLEEP) {
4000                 while (--cntdn) {
4001                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4002                         if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4003                                 break;
4004                         msleep(1);
4005                         count++;
4006                 }
4007         } else {
4008                 while (--cntdn) {
4009                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4010                         if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4011                                 break;
4012                         mdelay(1);
4013                         count++;
4014                 }
4015         }
4016
4017         if (cntdn) {
4018                 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4019                                 ioc->name, count, howlong));
4020                 return count;
4021         }
4022
4023         printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4024                         ioc->name, count, intstat);
4025         return -1;
4026 }
4027
4028 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4029 /**
4030  *      WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4031  *      @ioc: Pointer to MPT_ADAPTER structure
4032  *      @howlong: How long to wait (in seconds)
4033  *      @sleepFlag: Specifies whether the process can sleep
4034  *
4035  *      This routine polls the IOC for a handshake reply, 16 bits at a time.
4036  *      Reply is cached to IOC private area large enough to hold a maximum
4037  *      of 128 bytes of reply data.
4038  *
4039  *      Returns a negative value on failure, else size of reply in WORDS.
4040  */
4041 static int
4042 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4043 {
4044         int u16cnt = 0;
4045         int failcnt = 0;
4046         int t;
4047         u16 *hs_reply = ioc->hs_reply;
4048         volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4049         u16 hword;
4050
4051         hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4052
4053         /*
4054          * Get first two u16's so we can look at IOC's intended reply MsgLength
4055          */
4056         u16cnt=0;
4057         if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4058                 failcnt++;
4059         } else {
4060                 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4061                 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4062                 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4063                         failcnt++;
4064                 else {
4065                         hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4066                         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4067                 }
4068         }
4069
4070         dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4071                         ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4072                         failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4073
4074         /*
4075          * If no error (and IOC said MsgLength is > 0), piece together
4076          * reply 16 bits at a time.
4077          */
4078         for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4079                 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4080                         failcnt++;
4081                 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4082                 /* don't overflow our IOC hs_reply[] buffer! */
4083                 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4084                         hs_reply[u16cnt] = hword;
4085                 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4086         }
4087
4088         if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4089                 failcnt++;
4090         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4091
4092         if (failcnt) {
4093                 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4094                                 ioc->name);
4095                 return -failcnt;
4096         }
4097 #if 0
4098         else if (u16cnt != (2 * mptReply->MsgLength)) {
4099                 return -101;
4100         }
4101         else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4102                 return -102;
4103         }
4104 #endif
4105
4106         dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4107         DBG_DUMP_REPLY_FRAME(mptReply)
4108
4109         dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4110                         ioc->name, t, u16cnt/2));
4111         return u16cnt/2;
4112 }
4113
4114 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4115 /**
4116  *      GetLanConfigPages - Fetch LANConfig pages.
4117  *      @ioc: Pointer to MPT_ADAPTER structure
4118  *
4119  *      Return: 0 for success
4120  *      -ENOMEM if no memory available
4121  *              -EPERM if not allowed due to ISR context
4122  *              -EAGAIN if no msg frames currently available
4123  *              -EFAULT for non-successful reply or no reply (timeout)
4124  */
4125 static int
4126 GetLanConfigPages(MPT_ADAPTER *ioc)
4127 {
4128         ConfigPageHeader_t       hdr;
4129         CONFIGPARMS              cfg;
4130         LANPage0_t              *ppage0_alloc;
4131         dma_addr_t               page0_dma;
4132         LANPage1_t              *ppage1_alloc;
4133         dma_addr_t               page1_dma;
4134         int                      rc = 0;
4135         int                      data_sz;
4136         int                      copy_sz;
4137
4138         /* Get LAN Page 0 header */
4139         hdr.PageVersion = 0;
4140         hdr.PageLength = 0;
4141         hdr.PageNumber = 0;
4142         hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4143         cfg.cfghdr.hdr = &hdr;
4144         cfg.physAddr = -1;
4145         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4146         cfg.dir = 0;
4147         cfg.pageAddr = 0;
4148         cfg.timeout = 0;
4149
4150         if ((rc = mpt_config(ioc, &cfg)) != 0)
4151                 return rc;
4152
4153         if (hdr.PageLength > 0) {
4154                 data_sz = hdr.PageLength * 4;
4155                 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4156                 rc = -ENOMEM;
4157                 if (ppage0_alloc) {
4158                         memset((u8 *)ppage0_alloc, 0, data_sz);
4159                         cfg.physAddr = page0_dma;
4160                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4161
4162                         if ((rc = mpt_config(ioc, &cfg)) == 0) {
4163                                 /* save the data */
4164                                 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4165                                 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4166
4167                         }
4168
4169                         pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4170
4171                         /* FIXME!
4172                          *      Normalize endianness of structure data,
4173                          *      by byte-swapping all > 1 byte fields!
4174                          */
4175
4176                 }
4177
4178                 if (rc)
4179                         return rc;
4180         }
4181
4182         /* Get LAN Page 1 header */
4183         hdr.PageVersion = 0;
4184         hdr.PageLength = 0;
4185         hdr.PageNumber = 1;
4186         hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4187         cfg.cfghdr.hdr = &hdr;
4188         cfg.physAddr = -1;
4189         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4190         cfg.dir = 0;
4191         cfg.pageAddr = 0;
4192
4193         if ((rc = mpt_config(ioc, &cfg)) != 0)
4194                 return rc;
4195
4196         if (hdr.PageLength == 0)
4197                 return 0;
4198
4199         data_sz = hdr.PageLength * 4;
4200         rc = -ENOMEM;
4201         ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4202         if (ppage1_alloc) {
4203                 memset((u8 *)ppage1_alloc, 0, data_sz);
4204                 cfg.physAddr = page1_dma;
4205                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4206
4207                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4208                         /* save the data */
4209                         copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4210                         memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4211                 }
4212
4213                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4214
4215                 /* FIXME!
4216                  *      Normalize endianness of structure data,
4217                  *      by byte-swapping all > 1 byte fields!
4218                  */
4219
4220         }
4221
4222         return rc;
4223 }
4224
4225 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4226 /**
4227  *      mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
4228  *      @ioc: Pointer to MPT_ADAPTER structure
4229  *      @persist_opcode: see below
4230  *
4231  *      MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4232  *              devices not currently present.
4233  *      MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4234  *
4235  *      NOTE: Don't use not this function during interrupt time.
4236  *
4237  *      Returns 0 for success, non-zero error
4238  */
4239
4240 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4241 int
4242 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4243 {
4244         SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
4245         SasIoUnitControlReply_t         *sasIoUnitCntrReply;
4246         MPT_FRAME_HDR                   *mf = NULL;
4247         MPIHeader_t                     *mpi_hdr;
4248
4249
4250         /* insure garbage is not sent to fw */
4251         switch(persist_opcode) {
4252
4253         case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4254         case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4255                 break;
4256
4257         default:
4258                 return -1;
4259                 break;
4260         }
4261
4262         printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4263
4264         /* Get a MF for this command.
4265          */
4266         if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4267                 printk("%s: no msg frames!\n",__FUNCTION__);
4268                 return -1;
4269         }
4270
4271         mpi_hdr = (MPIHeader_t *) mf;
4272         sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4273         memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4274         sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4275         sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4276         sasIoUnitCntrReq->Operation = persist_opcode;
4277
4278         init_timer(&ioc->persist_timer);
4279         ioc->persist_timer.data = (unsigned long) ioc;
4280         ioc->persist_timer.function = mpt_timer_expired;
4281         ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4282         ioc->persist_wait_done=0;
4283         add_timer(&ioc->persist_timer);
4284         mpt_put_msg_frame(mpt_base_index, ioc, mf);
4285         wait_event(mpt_waitq, ioc->persist_wait_done);
4286
4287         sasIoUnitCntrReply =
4288             (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4289         if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4290                 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4291                     __FUNCTION__,
4292                     sasIoUnitCntrReply->IOCStatus,
4293                     sasIoUnitCntrReply->IOCLogInfo);
4294                 return -1;
4295         }
4296
4297         printk("%s: success\n",__FUNCTION__);
4298         return 0;
4299 }
4300
4301 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4302
4303 static void
4304 mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4305     MpiEventDataRaid_t * pRaidEventData)
4306 {
4307         int     volume;
4308         int     reason;
4309         int     disk;
4310         int     status;
4311         int     flags;
4312         int     state;
4313
4314         volume  = pRaidEventData->VolumeID;
4315         reason  = pRaidEventData->ReasonCode;
4316         disk    = pRaidEventData->PhysDiskNum;
4317         status  = le32_to_cpu(pRaidEventData->SettingsStatus);
4318         flags   = (status >> 0) & 0xff;
4319         state   = (status >> 8) & 0xff;
4320
4321         if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4322                 return;
4323         }
4324
4325         if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4326              reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4327             (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4328                 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
4329                         ioc->name, disk);
4330         } else {
4331                 printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4332                         ioc->name, volume);
4333         }
4334
4335         switch(reason) {
4336         case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4337                 printk(MYIOC_s_INFO_FMT "  volume has been created\n",
4338                         ioc->name);
4339                 break;
4340
4341         case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4342
4343                 printk(MYIOC_s_INFO_FMT "  volume has been deleted\n",
4344                         ioc->name);
4345                 break;
4346
4347         case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4348                 printk(MYIOC_s_INFO_FMT "  volume settings have been changed\n",
4349                         ioc->name);
4350                 break;
4351
4352         case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4353                 printk(MYIOC_s_INFO_FMT "  volume is now %s%s%s%s\n",
4354                         ioc->name,
4355                         state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4356                          ? "optimal"
4357                          : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4358                           ? "degraded"
4359                           : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4360                            ? "failed"
4361                            : "state unknown",
4362                         flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4363                          ? ", enabled" : "",
4364                         flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4365                          ? ", quiesced" : "",
4366                         flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4367                          ? ", resync in progress" : "" );
4368                 break;
4369
4370         case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4371                 printk(MYIOC_s_INFO_FMT "  volume membership of PhysDisk %d has changed\n",
4372                         ioc->name, disk);
4373                 break;
4374
4375         case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4376                 printk(MYIOC_s_INFO_FMT "  PhysDisk has been created\n",
4377                         ioc->name);
4378                 break;
4379
4380         case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4381                 printk(MYIOC_s_INFO_FMT "  PhysDisk has been deleted\n",
4382                         ioc->name);
4383                 break;
4384
4385         case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4386                 printk(MYIOC_s_INFO_FMT "  PhysDisk settings have been changed\n",
4387                         ioc->name);
4388                 break;
4389
4390         case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4391                 printk(MYIOC_s_INFO_FMT "  PhysDisk is now %s%s%s\n",
4392                         ioc->name,
4393                         state == MPI_PHYSDISK0_STATUS_ONLINE
4394                          ? "online"
4395                          : state == MPI_PHYSDISK0_STATUS_MISSING
4396                           ? "missing"
4397                           : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4398                            ? "not compatible"
4399                            : state == MPI_PHYSDISK0_STATUS_FAILED
4400                             ? "failed"
4401                             : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4402                              ? "initializing"
4403                              : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4404                               ? "offline requested"
4405                               : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4406                                ? "failed requested"
4407                                : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4408                                 ? "offline"
4409                                 : "state unknown",
4410                         flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4411                          ? ", out of sync" : "",
4412                         flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4413                          ? ", quiesced" : "" );
4414                 break;
4415
4416         case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4417                 printk(MYIOC_s_INFO_FMT "  Domain Validation needed for PhysDisk %d\n",
4418                         ioc->name, disk);
4419                 break;
4420
4421         case MPI_EVENT_RAID_RC_SMART_DATA:
4422                 printk(MYIOC_s_INFO_FMT "  SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4423                         ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4424                 break;
4425
4426         case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4427                 printk(MYIOC_s_INFO_FMT "  replacement of PhysDisk %d has started\n",
4428                         ioc->name, disk);
4429                 break;
4430         }
4431 }
4432
4433 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4434 /**
4435  *      GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4436  *      @ioc: Pointer to MPT_ADAPTER structure
4437  *
4438  *      Returns: 0 for success
4439  *      -ENOMEM if no memory available
4440  *              -EPERM if not allowed due to ISR context
4441  *              -EAGAIN if no msg frames currently available
4442  *              -EFAULT for non-successful reply or no reply (timeout)
4443  */
4444 static int
4445 GetIoUnitPage2(MPT_ADAPTER *ioc)
4446 {
4447         ConfigPageHeader_t       hdr;
4448         CONFIGPARMS              cfg;
4449         IOUnitPage2_t           *ppage_alloc;
4450         dma_addr_t               page_dma;
4451         int                      data_sz;
4452         int                      rc;
4453
4454         /* Get the page header */
4455         hdr.PageVersion = 0;
4456         hdr.PageLength = 0;
4457         hdr.PageNumber = 2;
4458         hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4459         cfg.cfghdr.hdr = &hdr;
4460         cfg.physAddr = -1;
4461         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4462         cfg.dir = 0;
4463         cfg.pageAddr = 0;
4464         cfg.timeout = 0;
4465
4466         if ((rc = mpt_config(ioc, &cfg)) != 0)
4467                 return rc;
4468
4469         if (hdr.PageLength == 0)
4470                 return 0;
4471
4472         /* Read the config page */
4473         data_sz = hdr.PageLength * 4;
4474         rc = -ENOMEM;
4475         ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4476         if (ppage_alloc) {
4477                 memset((u8 *)ppage_alloc, 0, data_sz);
4478                 cfg.physAddr = page_dma;
4479                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4480
4481                 /* If Good, save data */
4482                 if ((rc = mpt_config(ioc, &cfg)) == 0)
4483                         ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4484
4485                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4486         }
4487
4488         return rc;
4489 }
4490
4491 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4492 /**
4493  *      mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4494  *      @ioc: Pointer to a Adapter Strucutre
4495  *      @portnum: IOC port number
4496  *
4497  *      Return: -EFAULT if read of config page header fails
4498  *                      or if no nvram
4499  *      If read of SCSI Port Page 0 fails,
4500  *              NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
4501  *              Adapter settings: async, narrow
4502  *              Return 1
4503  *      If read of SCSI Port Page 2 fails,
4504  *              Adapter settings valid
4505  *              NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
4506  *              Return 1
4507  *      Else
4508  *              Both valid
4509  *              Return 0
4510  *      CHECK - what type of locking mechanisms should be used????
4511  */
4512 static int
4513 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4514 {
4515         u8                      *pbuf;
4516         dma_addr_t               buf_dma;
4517         CONFIGPARMS              cfg;
4518         ConfigPageHeader_t       header;
4519         int                      ii;
4520         int                      data, rc = 0;
4521
4522         /* Allocate memory
4523          */
4524         if (!ioc->spi_data.nvram) {
4525                 int      sz;
4526                 u8      *mem;
4527                 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4528                 mem = kmalloc(sz, GFP_ATOMIC);
4529                 if (mem == NULL)
4530                         return -EFAULT;
4531
4532                 ioc->spi_data.nvram = (int *) mem;
4533
4534                 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4535                         ioc->name, ioc->spi_data.nvram, sz));
4536         }
4537
4538         /* Invalidate NVRAM information
4539          */
4540         for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4541                 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4542         }
4543
4544         /* Read SPP0 header, allocate memory, then read page.
4545          */
4546         header.PageVersion = 0;
4547         header.PageLength = 0;
4548         header.PageNumber = 0;
4549         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4550         cfg.cfghdr.hdr = &header;
4551         cfg.physAddr = -1;
4552         cfg.pageAddr = portnum;
4553         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4554         cfg.dir = 0;
4555         cfg.timeout = 0;        /* use default */
4556         if (mpt_config(ioc, &cfg) != 0)
4557                  return -EFAULT;
4558
4559         if (header.PageLength > 0) {
4560                 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4561                 if (pbuf) {
4562                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4563                         cfg.physAddr = buf_dma;
4564                         if (mpt_config(ioc, &cfg) != 0) {
4565                                 ioc->spi_data.maxBusWidth = MPT_NARROW;
4566                                 ioc->spi_data.maxSyncOffset = 0;
4567                                 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4568                                 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4569                                 rc = 1;
4570                                 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4571                                         ioc->name, ioc->spi_data.minSyncFactor));
4572                         } else {
4573                                 /* Save the Port Page 0 data
4574                                  */
4575                                 SCSIPortPage0_t  *pPP0 = (SCSIPortPage0_t  *) pbuf;
4576                                 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4577                                 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4578
4579                                 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4580                                         ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4581                                         ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4582                                                 ioc->name, pPP0->Capabilities));
4583                                 }
4584                                 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4585                                 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4586                                 if (data) {
4587                                         ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4588                                         data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4589                                         ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4590                                         ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4591                                                 ioc->name, ioc->spi_data.minSyncFactor));
4592                                 } else {
4593                                         ioc->spi_data.maxSyncOffset = 0;
4594                                         ioc->spi_data.minSyncFactor = MPT_ASYNC;
4595                                 }
4596
4597                                 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4598
4599                                 /* Update the minSyncFactor based on bus type.
4600                                  */
4601                                 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4602                                         (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE))  {
4603
4604                                         if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
4605                                                 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4606                                                 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4607                                                         ioc->name, ioc->spi_data.minSyncFactor));
4608                                         }
4609                                 }
4610                         }
4611                         if (pbuf) {
4612                                 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4613                         }
4614                 }
4615         }
4616
4617         /* SCSI Port Page 2 - Read the header then the page.
4618          */
4619         header.PageVersion = 0;
4620         header.PageLength = 0;
4621         header.PageNumber = 2;
4622         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4623         cfg.cfghdr.hdr = &header;
4624         cfg.physAddr = -1;
4625         cfg.pageAddr = portnum;
4626         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4627         cfg.dir = 0;
4628         if (mpt_config(ioc, &cfg) != 0)
4629                 return -EFAULT;
4630
4631         if (header.PageLength > 0) {
4632                 /* Allocate memory and read SCSI Port Page 2
4633                  */
4634                 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4635                 if (pbuf) {
4636                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4637                         cfg.physAddr = buf_dma;
4638                         if (mpt_config(ioc, &cfg) != 0) {
4639                                 /* Nvram data is left with INVALID mark
4640                                  */
4641                                 rc = 1;
4642                         } else {
4643                                 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
4644                                 MpiDeviceInfo_t *pdevice = NULL;
4645
4646                                 /*
4647                                  * Save "Set to Avoid SCSI Bus Resets" flag
4648                                  */
4649                                 ioc->spi_data.bus_reset =
4650                                     (le32_to_cpu(pPP2->PortFlags) &
4651                                 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4652                                     0 : 1 ;
4653
4654                                 /* Save the Port Page 2 data
4655                                  * (reformat into a 32bit quantity)
4656                                  */
4657                                 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4658                                 ioc->spi_data.PortFlags = data;
4659                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4660                                         pdevice = &pPP2->DeviceSettings[ii];
4661                                         data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4662                                                 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4663                                         ioc->spi_data.nvram[ii] = data;
4664                                 }
4665                         }
4666
4667                         pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4668                 }
4669         }
4670
4671         /* Update Adapter limits with those from NVRAM
4672          * Comment: Don't need to do this. Target performance
4673          * parameters will never exceed the adapters limits.
4674          */
4675
4676         return rc;
4677 }
4678
4679 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4680 /**
4681  *      mpt_readScsiDevicePageHeaders - save version and length of SDP1
4682  *      @ioc: Pointer to a Adapter Strucutre
4683  *      @portnum: IOC port number
4684  *
4685  *      Return: -EFAULT if read of config page header fails
4686  *              or 0 if success.
4687  */
4688 static int
4689 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4690 {
4691         CONFIGPARMS              cfg;
4692         ConfigPageHeader_t       header;
4693
4694         /* Read the SCSI Device Page 1 header
4695          */
4696         header.PageVersion = 0;
4697         header.PageLength = 0;
4698         header.PageNumber = 1;
4699         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4700         cfg.cfghdr.hdr = &header;
4701         cfg.physAddr = -1;
4702         cfg.pageAddr = portnum;
4703         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4704         cfg.dir = 0;
4705         cfg.timeout = 0;
4706         if (mpt_config(ioc, &cfg) != 0)
4707                  return -EFAULT;
4708
4709         ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4710         ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
4711
4712         header.PageVersion = 0;
4713         header.PageLength = 0;
4714         header.PageNumber = 0;
4715         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4716         if (mpt_config(ioc, &cfg) != 0)
4717                  return -EFAULT;
4718
4719         ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4720         ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4721
4722         dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4723                         ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4724
4725         dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4726                         ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4727         return 0;
4728 }
4729
4730 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4731 /**
4732  *      mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4733  *      @ioc: Pointer to a Adapter Strucutre
4734  *      @portnum: IOC port number
4735  *
4736  *      Return:
4737  *      0 on success
4738  *      -EFAULT if read of config page header fails or data pointer not NULL
4739  *      -ENOMEM if pci_alloc failed
4740  */
4741 int
4742 mpt_findImVolumes(MPT_ADAPTER *ioc)
4743 {
4744         IOCPage2_t              *pIoc2;
4745         u8                      *mem;
4746         ConfigPageIoc2RaidVol_t *pIocRv;
4747         dma_addr_t               ioc2_dma;
4748         CONFIGPARMS              cfg;
4749         ConfigPageHeader_t       header;
4750         int                      jj;
4751         int                      rc = 0;
4752         int                      iocpage2sz;
4753         u8                       nVols, nPhys;
4754         u8                       vid, vbus, vioc;
4755
4756         /* Read IOCP2 header then the page.
4757          */
4758         header.PageVersion = 0;
4759         header.PageLength = 0;
4760         header.PageNumber = 2;
4761         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4762         cfg.cfghdr.hdr = &header;
4763         cfg.physAddr = -1;
4764         cfg.pageAddr = 0;
4765         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4766         cfg.dir = 0;
4767         cfg.timeout = 0;
4768         if (mpt_config(ioc, &cfg) != 0)
4769                  return -EFAULT;
4770
4771         if (header.PageLength == 0)
4772                 return -EFAULT;
4773
4774         iocpage2sz = header.PageLength * 4;
4775         pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4776         if (!pIoc2)
4777                 return -ENOMEM;
4778
4779         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4780         cfg.physAddr = ioc2_dma;
4781         if (mpt_config(ioc, &cfg) != 0)
4782                 goto done_and_free;
4783
4784         if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
4785                 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4786                 if (mem) {
4787                         ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
4788                 } else {
4789                         goto done_and_free;
4790                 }
4791         }
4792         memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4793
4794         /* Identify RAID Volume Id's */
4795         nVols = pIoc2->NumActiveVolumes;
4796         if ( nVols == 0) {
4797                 /* No RAID Volume.
4798                  */
4799                 goto done_and_free;
4800         } else {
4801                 /* At least 1 RAID Volume
4802                  */
4803                 pIocRv = pIoc2->RaidVolume;
4804                 ioc->raid_data.isRaid = 0;
4805                 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4806                         vid = pIocRv->VolumeID;
4807                         vbus = pIocRv->VolumeBus;
4808                         vioc = pIocRv->VolumeIOC;
4809
4810                         /* find the match
4811                          */
4812                         if (vbus == 0) {
4813                                 ioc->raid_data.isRaid |= (1 << vid);
4814                         } else {
4815                                 /* Error! Always bus 0
4816                                  */
4817                         }
4818                 }
4819         }
4820
4821         /* Identify Hidden Physical Disk Id's */
4822         nPhys = pIoc2->NumActivePhysDisks;
4823         if (nPhys == 0) {
4824                 /* No physical disks.
4825                  */
4826         } else {
4827                 mpt_read_ioc_pg_3(ioc);
4828         }
4829
4830 done_and_free:
4831         pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4832
4833         return rc;
4834 }
4835
4836 static int
4837 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4838 {
4839         IOCPage3_t              *pIoc3;
4840         u8                      *mem;
4841         CONFIGPARMS              cfg;
4842         ConfigPageHeader_t       header;
4843         dma_addr_t               ioc3_dma;
4844         int                      iocpage3sz = 0;
4845
4846         /* Free the old page
4847          */
4848         kfree(ioc->raid_data.pIocPg3);
4849         ioc->raid_data.pIocPg3 = NULL;
4850
4851         /* There is at least one physical disk.
4852          * Read and save IOC Page 3
4853          */
4854         header.PageVersion = 0;
4855         header.PageLength = 0;
4856         header.PageNumber = 3;
4857         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4858         cfg.cfghdr.hdr = &header;
4859         cfg.physAddr = -1;
4860         cfg.pageAddr = 0;
4861         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4862         cfg.dir = 0;
4863         cfg.timeout = 0;
4864         if (mpt_config(ioc, &cfg) != 0)
4865                 return 0;
4866
4867         if (header.PageLength == 0)
4868                 return 0;
4869
4870         /* Read Header good, alloc memory
4871          */
4872         iocpage3sz = header.PageLength * 4;
4873         pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4874         if (!pIoc3)
4875                 return 0;
4876
4877         /* Read the Page and save the data
4878          * into malloc'd memory.
4879          */
4880         cfg.physAddr = ioc3_dma;
4881         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4882         if (mpt_config(ioc, &cfg) == 0) {
4883                 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4884                 if (mem) {
4885                         memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4886                         ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
4887                 }
4888         }
4889
4890         pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4891
4892         return 0;
4893 }
4894
4895 static void
4896 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4897 {
4898         IOCPage4_t              *pIoc4;
4899         CONFIGPARMS              cfg;
4900         ConfigPageHeader_t       header;
4901         dma_addr_t               ioc4_dma;
4902         int                      iocpage4sz;
4903
4904         /* Read and save IOC Page 4
4905          */
4906         header.PageVersion = 0;
4907         header.PageLength = 0;
4908         header.PageNumber = 4;
4909         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4910         cfg.cfghdr.hdr = &header;
4911         cfg.physAddr = -1;
4912         cfg.pageAddr = 0;
4913         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4914         cfg.dir = 0;
4915         cfg.timeout = 0;
4916         if (mpt_config(ioc, &cfg) != 0)
4917                 return;
4918
4919         if (header.PageLength == 0)
4920                 return;
4921
4922         if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4923                 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4924                 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4925                 if (!pIoc4)
4926                         return;
4927                 ioc->alloc_total += iocpage4sz;
4928         } else {
4929                 ioc4_dma = ioc->spi_data.IocPg4_dma;
4930                 iocpage4sz = ioc->spi_data.IocPg4Sz;
4931         }
4932
4933         /* Read the Page into dma memory.
4934          */
4935         cfg.physAddr = ioc4_dma;
4936         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4937         if (mpt_config(ioc, &cfg) == 0) {
4938                 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4939                 ioc->spi_data.IocPg4_dma = ioc4_dma;
4940                 ioc->spi_data.IocPg4Sz = iocpage4sz;
4941         } else {
4942                 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4943                 ioc->spi_data.pIocPg4 = NULL;
4944                 ioc->alloc_total -= iocpage4sz;
4945         }
4946 }
4947
4948 static void
4949 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4950 {
4951         IOCPage1_t              *pIoc1;
4952         CONFIGPARMS              cfg;
4953         ConfigPageHeader_t       header;
4954         dma_addr_t               ioc1_dma;
4955         int                      iocpage1sz = 0;
4956         u32                      tmp;
4957
4958         /* Check the Coalescing Timeout in IOC Page 1
4959          */
4960         header.PageVersion = 0;
4961         header.PageLength = 0;
4962         header.PageNumber = 1;
4963         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4964         cfg.cfghdr.hdr = &header;
4965         cfg.physAddr = -1;
4966         cfg.pageAddr = 0;
4967         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4968         cfg.dir = 0;
4969         cfg.timeout = 0;
4970         if (mpt_config(ioc, &cfg) != 0)
4971                 return;
4972
4973         if (header.PageLength == 0)
4974                 return;
4975
4976         /* Read Header good, alloc memory
4977          */
4978         iocpage1sz = header.PageLength * 4;
4979         pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4980         if (!pIoc1)
4981                 return;
4982
4983         /* Read the Page and check coalescing timeout
4984          */
4985         cfg.physAddr = ioc1_dma;
4986         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4987         if (mpt_config(ioc, &cfg) == 0) {
4988                 
4989                 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4990                 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4991                         tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4992
4993                         dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4994                                         ioc->name, tmp));
4995
4996                         if (tmp > MPT_COALESCING_TIMEOUT) {
4997                                 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4998
4999                                 /* Write NVRAM and current
5000                                  */
5001                                 cfg.dir = 1;
5002                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5003                                 if (mpt_config(ioc, &cfg) == 0) {
5004                                         dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
5005                                                         ioc->name, MPT_COALESCING_TIMEOUT));
5006
5007                                         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5008                                         if (mpt_config(ioc, &cfg) == 0) {
5009                                                 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
5010                                                                 ioc->name, MPT_COALESCING_TIMEOUT));
5011                                         } else {
5012                                                 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
5013                                                                         ioc->name));
5014                                         }
5015
5016                                 } else {
5017                                         dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
5018                                                                 ioc->name));
5019                                 }
5020                         }
5021
5022                 } else {
5023                         dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5024                 }
5025         }
5026
5027         pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5028
5029         return;
5030 }
5031
5032 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5033 /**
5034  *      SendEventNotification - Send EventNotification (on or off) request to adapter
5035  *      @ioc: Pointer to MPT_ADAPTER structure
5036  *      @EvSwitch: Event switch flags
5037  */
5038 static int
5039 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5040 {
5041         EventNotification_t     *evnp;
5042
5043         evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5044         if (evnp == NULL) {
5045                 devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5046                                 ioc->name));
5047                 return 0;
5048         }
5049         memset(evnp, 0, sizeof(*evnp));
5050
5051         devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5052
5053         evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5054         evnp->ChainOffset = 0;
5055         evnp->MsgFlags = 0;
5056         evnp->Switch = EvSwitch;
5057
5058         mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5059
5060         return 0;
5061 }
5062
5063 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5064 /**
5065  *      SendEventAck - Send EventAck request to MPT adapter.
5066  *      @ioc: Pointer to MPT_ADAPTER structure
5067  *      @evnp: Pointer to original EventNotification request
5068  */
5069 static int
5070 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5071 {
5072         EventAck_t      *pAck;
5073
5074         if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5075                 dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
5076                     ioc->name,__FUNCTION__));
5077                 return -1;
5078         }
5079
5080         devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5081
5082         pAck->Function     = MPI_FUNCTION_EVENT_ACK;
5083         pAck->ChainOffset  = 0;
5084         pAck->Reserved[0]  = pAck->Reserved[1] = 0;
5085         pAck->MsgFlags     = 0;
5086         pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
5087         pAck->Event        = evnp->Event;
5088         pAck->EventContext = evnp->EventContext;
5089
5090         mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5091
5092         return 0;
5093 }
5094
5095 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5096 /**
5097  *      mpt_config - Generic function to issue config message
5098  *      @ioc:   Pointer to an adapter structure
5099  *      @pCfg:  Pointer to a configuration structure. Struct contains
5100  *              action, page address, direction, physical address
5101  *              and pointer to a configuration page header
5102  *              Page header is updated.
5103  *
5104  *      Returns 0 for success
5105  *      -EPERM if not allowed due to ISR context
5106  *      -EAGAIN if no msg frames currently available
5107  *      -EFAULT for non-successful reply or no reply (timeout)
5108  */
5109 int
5110 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5111 {
5112         Config_t        *pReq;
5113         ConfigExtendedPageHeader_t  *pExtHdr = NULL;
5114         MPT_FRAME_HDR   *mf;
5115         unsigned long    flags;
5116         int              ii, rc;
5117         int              flagsLength;
5118         int              in_isr;
5119
5120         /*      Prevent calling wait_event() (below), if caller happens
5121          *      to be in ISR context, because that is fatal!
5122          */
5123         in_isr = in_interrupt();
5124         if (in_isr) {
5125                 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5126                                 ioc->name));
5127                 return -EPERM;
5128         }
5129
5130         /* Get and Populate a free Frame
5131          */
5132         if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5133                 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5134                                 ioc->name));
5135                 return -EAGAIN;
5136         }
5137         pReq = (Config_t *)mf;
5138         pReq->Action = pCfg->action;
5139         pReq->Reserved = 0;
5140         pReq->ChainOffset = 0;
5141         pReq->Function = MPI_FUNCTION_CONFIG;
5142
5143         /* Assume page type is not extended and clear "reserved" fields. */
5144         pReq->ExtPageLength = 0;
5145         pReq->ExtPageType = 0;
5146         pReq->MsgFlags = 0;
5147
5148         for (ii=0; ii < 8; ii++)
5149                 pReq->Reserved2[ii] = 0;
5150
5151         pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5152         pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5153         pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5154         pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5155
5156         if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5157                 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5158                 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5159                 pReq->ExtPageType = pExtHdr->ExtPageType;
5160                 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5161
5162                 /* Page Length must be treated as a reserved field for the extended header. */
5163                 pReq->Header.PageLength = 0;
5164         }
5165
5166         pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5167
5168         /* Add a SGE to the config request.
5169          */
5170         if (pCfg->dir)
5171                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5172         else
5173                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5174
5175         if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5176                 flagsLength |= pExtHdr->ExtPageLength * 4;
5177
5178                 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5179                         ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5180         }
5181         else {
5182                 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5183
5184                 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5185                         ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5186         }
5187
5188         mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5189
5190         /* Append pCfg pointer to end of mf
5191          */
5192         *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
5193
5194         /* Initalize the timer
5195          */
5196         init_timer(&pCfg->timer);
5197         pCfg->timer.data = (unsigned long) ioc;
5198         pCfg->timer.function = mpt_timer_expired;
5199         pCfg->wait_done = 0;
5200
5201         /* Set the timer; ensure 10 second minimum */
5202         if (pCfg->timeout < 10)
5203                 pCfg->timer.expires = jiffies + HZ*10;
5204         else
5205                 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5206
5207         /* Add to end of Q, set timer and then issue this command */
5208         spin_lock_irqsave(&ioc->FreeQlock, flags);
5209         list_add_tail(&pCfg->linkage, &ioc->configQ);
5210         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5211
5212         add_timer(&pCfg->timer);
5213         mpt_put_msg_frame(mpt_base_index, ioc, mf);
5214         wait_event(mpt_waitq, pCfg->wait_done);
5215
5216         /* mf has been freed - do not access */
5217
5218         rc = pCfg->status;
5219
5220         return rc;
5221 }
5222
5223 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5224 /**
5225  *      mpt_timer_expired - Callback for timer process.
5226  *      Used only internal config functionality.
5227  *      @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5228  */
5229 static void
5230 mpt_timer_expired(unsigned long data)
5231 {
5232         MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5233
5234         dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5235
5236         /* Perform a FW reload */
5237         if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5238                 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5239
5240         /* No more processing.
5241          * Hard reset clean-up will wake up
5242          * process and free all resources.
5243          */
5244         dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5245
5246         return;
5247 }
5248
5249 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5250 /**
5251  *      mpt_ioc_reset - Base cleanup for hard reset
5252  *      @ioc: Pointer to the adapter structure
5253  *      @reset_phase: Indicates pre- or post-reset functionality
5254  *
5255  *      Remark: Frees resources with internally generated commands.
5256  */
5257 static int
5258 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5259 {
5260         CONFIGPARMS *pCfg;
5261         unsigned long flags;
5262
5263         dprintk((KERN_WARNING MYNAM
5264                         ": IOC %s_reset routed to MPT base driver!\n",
5265                         reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5266                         reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5267
5268         if (reset_phase == MPT_IOC_SETUP_RESET) {
5269                 ;
5270         } else if (reset_phase == MPT_IOC_PRE_RESET) {
5271                 /* If the internal config Q is not empty -
5272                  * delete timer. MF resources will be freed when
5273                  * the FIFO's are primed.
5274                  */
5275                 spin_lock_irqsave(&ioc->FreeQlock, flags);
5276                 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5277                         del_timer(&pCfg->timer);
5278                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5279
5280         } else {
5281                 CONFIGPARMS *pNext;
5282
5283                 /* Search the configQ for internal commands.
5284                  * Flush the Q, and wake up all suspended threads.
5285                  */
5286                 spin_lock_irqsave(&ioc->FreeQlock, flags);
5287                 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5288                         list_del(&pCfg->linkage);
5289
5290                         pCfg->status = MPT_CONFIG_ERROR;
5291                         pCfg->wait_done = 1;
5292                         wake_up(&mpt_waitq);
5293                 }
5294                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5295         }
5296
5297         return 1;               /* currently means nothing really */
5298 }
5299
5300
5301 #ifdef CONFIG_PROC_FS           /* { */
5302 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5303 /*
5304  *      procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5305  */
5306 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5307 /**
5308  *      procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5309  *
5310  *      Returns 0 for success, non-zero for failure.
5311  */
5312 static int
5313 procmpt_create(void)
5314 {
5315         struct proc_dir_entry   *ent;
5316
5317         mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5318         if (mpt_proc_root_dir == NULL)
5319                 return -ENOTDIR;
5320
5321         ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5322         if (ent)
5323                 ent->read_proc = procmpt_summary_read;
5324
5325         ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5326         if (ent)
5327                 ent->read_proc = procmpt_version_read;
5328
5329         return 0;
5330 }
5331
5332 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5333 /**
5334  *      procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5335  *
5336  *      Returns 0 for success, non-zero for failure.
5337  */
5338 static void
5339 procmpt_destroy(void)
5340 {
5341         remove_proc_entry("version", mpt_proc_root_dir);
5342         remove_proc_entry("summary", mpt_proc_root_dir);
5343         remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5344 }
5345
5346 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5347 /**
5348  *      procmpt_summary_read - Handle read request of a summary file
5349  *      @buf: Pointer to area to write information
5350  *      @start: Pointer to start pointer
5351  *      @offset: Offset to start writing
5352  *      @request: Amount of read data requested
5353  *      @eof: Pointer to EOF integer
5354  *      @data: Pointer
5355  *
5356  *      Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
5357  *      Returns number of characters written to process performing the read.
5358  */
5359 static int
5360 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5361 {
5362         MPT_ADAPTER *ioc;
5363         char *out = buf;
5364         int len;
5365
5366         if (data) {
5367                 int more = 0;
5368
5369                 ioc = data;
5370                 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5371
5372                 out += more;
5373         } else {
5374                 list_for_each_entry(ioc, &ioc_list, list) {
5375                         int     more = 0;
5376
5377                         mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5378
5379                         out += more;
5380                         if ((out-buf) >= request)
5381                                 break;
5382                 }
5383         }
5384
5385         len = out - buf;
5386
5387         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5388 }
5389
5390 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5391 /**
5392  *      procmpt_version_read - Handle read request from /proc/mpt/version.
5393  *      @buf: Pointer to area to write information
5394  *      @start: Pointer to start pointer
5395  *      @offset: Offset to start writing
5396  *      @request: Amount of read data requested
5397  *      @eof: Pointer to EOF integer
5398  *      @data: Pointer
5399  *
5400  *      Returns number of characters written to process performing the read.
5401  */
5402 static int
5403 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5404 {
5405         int      ii;
5406         int      scsi, fc, sas, lan, ctl, targ, dmp;
5407         char    *drvname;
5408         int      len;
5409
5410         len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5411         len += sprintf(buf+len, "  Fusion MPT base driver\n");
5412
5413         scsi = fc = sas = lan = ctl = targ = dmp = 0;
5414         for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5415                 drvname = NULL;
5416                 if (MptCallbacks[ii]) {
5417                         switch (MptDriverClass[ii]) {
5418                         case MPTSPI_DRIVER:
5419                                 if (!scsi++) drvname = "SPI host";
5420                                 break;
5421                         case MPTFC_DRIVER:
5422                                 if (!fc++) drvname = "FC host";
5423                                 break;
5424                         case MPTSAS_DRIVER:
5425                                 if (!sas++) drvname = "SAS host";
5426                                 break;
5427                         case MPTLAN_DRIVER:
5428                                 if (!lan++) drvname = "LAN";
5429                                 break;
5430                         case MPTSTM_DRIVER:
5431                                 if (!targ++) drvname = "SCSI target";
5432                                 break;
5433                         case MPTCTL_DRIVER:
5434                                 if (!ctl++) drvname = "ioctl";
5435                                 break;
5436                         }
5437
5438                         if (drvname)
5439                                 len += sprintf(buf+len, "  Fusion MPT %s driver\n", drvname);
5440                 }
5441         }
5442
5443         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5444 }
5445
5446 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5447 /**
5448  *      procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5449  *      @buf: Pointer to area to write information
5450  *      @start: Pointer to start pointer
5451  *      @offset: Offset to start writing
5452  *      @request: Amount of read data requested
5453  *      @eof: Pointer to EOF integer
5454  *      @data: Pointer
5455  *
5456  *      Returns number of characters written to process performing the read.
5457  */
5458 static int
5459 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5460 {
5461         MPT_ADAPTER     *ioc = data;
5462         int              len;
5463         char             expVer[32];
5464         int              sz;
5465         int              p;
5466
5467         mpt_get_fw_exp_ver(expVer, ioc);
5468
5469         len = sprintf(buf, "%s:", ioc->name);
5470         if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5471                 len += sprintf(buf+len, "  (f/w download boot flag set)");
5472 //      if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5473 //              len += sprintf(buf+len, "  CONFIG_CHECKSUM_FAIL!");
5474
5475         len += sprintf(buf+len, "\n  ProductID = 0x%04x (%s)\n",
5476                         ioc->facts.ProductID,
5477                         ioc->prod_name);
5478         len += sprintf(buf+len, "  FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5479         if (ioc->facts.FWImageSize)
5480                 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5481         len += sprintf(buf+len, "\n  MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5482         len += sprintf(buf+len, "  FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5483         len += sprintf(buf+len, "  EventState = 0x%02x\n", ioc->facts.EventState);
5484
5485         len += sprintf(buf+len, "  CurrentHostMfaHighAddr = 0x%08x\n",
5486                         ioc->facts.CurrentHostMfaHighAddr);
5487         len += sprintf(buf+len, "  CurrentSenseBufferHighAddr = 0x%08x\n",
5488                         ioc->facts.CurrentSenseBufferHighAddr);
5489
5490         len += sprintf(buf+len, "  MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5491         len += sprintf(buf+len, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5492
5493         len += sprintf(buf+len, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5494                                         (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5495         /*
5496          *  Rounding UP to nearest 4-kB boundary here...
5497          */
5498         sz = (ioc->req_sz * ioc->req_depth) + 128;
5499         sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5500         len += sprintf(buf+len, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5501                                         ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5502         len += sprintf(buf+len, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
5503                                         4*ioc->facts.RequestFrameSize,
5504                                         ioc->facts.GlobalCredits);
5505
5506         len += sprintf(buf+len, "  Frames   @ 0x%p (Dma @ 0x%p)\n",
5507                                         (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5508         sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5509         len += sprintf(buf+len, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5510                                         ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5511         len += sprintf(buf+len, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
5512                                         ioc->facts.CurReplyFrameSize,
5513                                         ioc->facts.ReplyQueueDepth);
5514
5515         len += sprintf(buf+len, "  MaxDevices = %d\n",
5516                         (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5517         len += sprintf(buf+len, "  MaxBuses = %d\n", ioc->facts.MaxBuses);
5518
5519         /* per-port info */
5520         for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5521                 len += sprintf(buf+len, "  PortNumber = %d (of %d)\n",
5522                                 p+1,
5523                                 ioc->facts.NumberOfPorts);
5524                 if (ioc->bus_type == FC) {
5525                         if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5526                                 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5527                                 len += sprintf(buf+len, "    LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5528                                                 a[5], a[4], a[3], a[2], a[1], a[0]);
5529                         }
5530                         len += sprintf(buf+len, "    WWN = %08X%08X:%08X%08X\n",
5531                                         ioc->fc_port_page0[p].WWNN.High,
5532                                         ioc->fc_port_page0[p].WWNN.Low,
5533                                         ioc->fc_port_page0[p].WWPN.High,
5534                                         ioc->fc_port_page0[p].WWPN.Low);
5535                 }
5536         }
5537
5538         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5539 }
5540
5541 #endif          /* CONFIG_PROC_FS } */
5542
5543 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5544 static void
5545 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5546 {
5547         buf[0] ='\0';
5548         if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5549                 sprintf(buf, " (Exp %02d%02d)",
5550                         (ioc->facts.FWVersion.Word >> 16) & 0x00FF,     /* Month */
5551                         (ioc->facts.FWVersion.Word >> 8) & 0x1F);       /* Day */
5552
5553                 /* insider hack! */
5554                 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5555                         strcat(buf, " [MDBG]");
5556         }
5557 }
5558
5559 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5560 /**
5561  *      mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5562  *      @ioc: Pointer to MPT_ADAPTER structure
5563  *      @buffer: Pointer to buffer where IOC summary info should be written
5564  *      @size: Pointer to number of bytes we wrote (set by this routine)
5565  *      @len: Offset at which to start writing in buffer
5566  *      @showlan: Display LAN stuff?
5567  *
5568  *      This routine writes (english readable) ASCII text, which represents
5569  *      a summary of IOC information, to a buffer.
5570  */
5571 void
5572 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5573 {
5574         char expVer[32];
5575         int y;
5576
5577         mpt_get_fw_exp_ver(expVer, ioc);
5578
5579         /*
5580          *  Shorter summary of attached ioc's...
5581          */
5582         y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5583                         ioc->name,
5584                         ioc->prod_name,
5585                         MPT_FW_REV_MAGIC_ID_STRING,     /* "FwRev=" or somesuch */
5586                         ioc->facts.FWVersion.Word,
5587                         expVer,
5588                         ioc->facts.NumberOfPorts,
5589                         ioc->req_depth);
5590
5591         if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5592                 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5593                 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5594                         a[5], a[4], a[3], a[2], a[1], a[0]);
5595         }
5596
5597         y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5598
5599         if (!ioc->active)
5600                 y += sprintf(buffer+len+y, " (disabled)");
5601
5602         y += sprintf(buffer+len+y, "\n");
5603
5604         *size = y;
5605 }
5606
5607 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5608 /*
5609  *      Reset Handling
5610  */
5611 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5612 /**
5613  *      mpt_HardResetHandler - Generic reset handler
5614  *      @ioc: Pointer to MPT_ADAPTER structure
5615  *      @sleepFlag: Indicates if sleep or schedule must be called.
5616  *
5617  *      Issues SCSI Task Management call based on input arg values.
5618  *      If TaskMgmt fails, returns associated SCSI request.
5619  *
5620  *      Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5621  *      or a non-interrupt thread.  In the former, must not call schedule().
5622  *
5623  *      Note: A return of -1 is a FATAL error case, as it means a
5624  *      FW reload/initialization failed.
5625  *
5626  *      Returns 0 for SUCCESS or -1 if FAILED.
5627  */
5628 int
5629 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5630 {
5631         int              rc;
5632         unsigned long    flags;
5633
5634         dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5635 #ifdef MFCNT
5636         printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5637         printk("MF count 0x%x !\n", ioc->mfcnt);
5638 #endif
5639
5640         /* Reset the adapter. Prevent more than 1 call to
5641          * mpt_do_ioc_recovery at any instant in time.
5642          */
5643         spin_lock_irqsave(&ioc->diagLock, flags);
5644         if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5645                 spin_unlock_irqrestore(&ioc->diagLock, flags);
5646                 return 0;
5647         } else {
5648                 ioc->diagPending = 1;
5649         }
5650         spin_unlock_irqrestore(&ioc->diagLock, flags);
5651
5652         /* FIXME: If do_ioc_recovery fails, repeat....
5653          */
5654
5655         /* The SCSI driver needs to adjust timeouts on all current
5656          * commands prior to the diagnostic reset being issued.
5657          * Prevents timeouts occurring during a diagnostic reset...very bad.
5658          * For all other protocol drivers, this is a no-op.
5659          */
5660         {
5661                 int      ii;
5662                 int      r = 0;
5663
5664                 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5665                         if (MptResetHandlers[ii]) {
5666                                 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5667                                                 ioc->name, ii));
5668                                 r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
5669                                 if (ioc->alt_ioc) {
5670                                         dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5671                                                         ioc->name, ioc->alt_ioc->name, ii));
5672                                         r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5673                                 }
5674                         }
5675                 }
5676         }
5677
5678         if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5679                 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5680                         rc, ioc->name);
5681         }
5682         ioc->reload_fw = 0;
5683         if (ioc->alt_ioc)
5684                 ioc->alt_ioc->reload_fw = 0;
5685
5686         spin_lock_irqsave(&ioc->diagLock, flags);
5687         ioc->diagPending = 0;
5688         if (ioc->alt_ioc)
5689                 ioc->alt_ioc->diagPending = 0;
5690         spin_unlock_irqrestore(&ioc->diagLock, flags);
5691
5692         dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5693
5694         return rc;
5695 }
5696
5697 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5698 static void
5699 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5700 {
5701         char *ds = NULL;
5702
5703         switch(event) {
5704         case MPI_EVENT_NONE:
5705                 ds = "None";
5706                 break;
5707         case MPI_EVENT_LOG_DATA:
5708                 ds = "Log Data";
5709                 break;
5710         case MPI_EVENT_STATE_CHANGE:
5711                 ds = "State Change";
5712                 break;
5713         case MPI_EVENT_UNIT_ATTENTION:
5714                 ds = "Unit Attention";
5715                 break;
5716         case MPI_EVENT_IOC_BUS_RESET:
5717                 ds = "IOC Bus Reset";
5718                 break;
5719         case MPI_EVENT_EXT_BUS_RESET:
5720                 ds = "External Bus Reset";
5721                 break;
5722         case MPI_EVENT_RESCAN:
5723                 ds = "Bus Rescan Event";
5724                 break;
5725         case MPI_EVENT_LINK_STATUS_CHANGE:
5726                 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5727                         ds = "Link Status(FAILURE) Change";
5728                 else
5729                         ds = "Link Status(ACTIVE) Change";
5730                 break;
5731         case MPI_EVENT_LOOP_STATE_CHANGE:
5732                 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5733                         ds = "Loop State(LIP) Change";
5734                 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5735                         ds = "Loop State(LPE) Change";          /* ??? */
5736                 else
5737                         ds = "Loop State(LPB) Change";          /* ??? */
5738                 break;
5739         case MPI_EVENT_LOGOUT:
5740                 ds = "Logout";
5741                 break;
5742         case MPI_EVENT_EVENT_CHANGE:
5743                 if (evData0)
5744                         ds = "Events ON";
5745                 else
5746                         ds = "Events OFF";
5747                 break;
5748         case MPI_EVENT_INTEGRATED_RAID:
5749         {
5750                 u8 ReasonCode = (u8)(evData0 >> 16);
5751                 switch (ReasonCode) {
5752                 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5753                         ds = "Integrated Raid: Volume Created";
5754                         break;
5755                 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5756                         ds = "Integrated Raid: Volume Deleted";
5757                         break;
5758                 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5759                         ds = "Integrated Raid: Volume Settings Changed";
5760                         break;
5761                 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5762                         ds = "Integrated Raid: Volume Status Changed";
5763                         break;
5764                 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5765                         ds = "Integrated Raid: Volume Physdisk Changed";
5766                         break;
5767                 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5768                         ds = "Integrated Raid: Physdisk Created";
5769                         break;
5770                 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5771                         ds = "Integrated Raid: Physdisk Deleted";
5772                         break;
5773                 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5774                         ds = "Integrated Raid: Physdisk Settings Changed";
5775                         break;
5776                 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5777                         ds = "Integrated Raid: Physdisk Status Changed";
5778                         break;
5779                 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5780                         ds = "Integrated Raid: Domain Validation Needed";
5781                         break;
5782                 case MPI_EVENT_RAID_RC_SMART_DATA :
5783                         ds = "Integrated Raid; Smart Data";
5784                         break;
5785                 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5786                         ds = "Integrated Raid: Replace Action Started";
5787                         break;
5788                 default:
5789                         ds = "Integrated Raid";
5790                 break;
5791                 }
5792                 break;
5793         }
5794         case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5795                 ds = "SCSI Device Status Change";
5796                 break;
5797         case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5798         {
5799                 u8 id = (u8)(evData0);
5800                 u8 channel = (u8)(evData0 >> 8);
5801                 u8 ReasonCode = (u8)(evData0 >> 16);
5802                 switch (ReasonCode) {
5803                 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5804                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5805                             "SAS Device Status Change: Added: "
5806                             "id=%d channel=%d", id, channel);
5807                         break;
5808                 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5809                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5810                             "SAS Device Status Change: Deleted: "
5811                             "id=%d channel=%d", id, channel);
5812                         break;
5813                 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5814                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5815                             "SAS Device Status Change: SMART Data: "
5816                             "id=%d channel=%d", id, channel);
5817                         break;
5818                 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5819                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5820                             "SAS Device Status Change: No Persistancy: "
5821                             "id=%d channel=%d", id, channel);
5822                         break;
5823                 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
5824                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5825                             "SAS Device Status Change: Unsupported Device "
5826                             "Discovered : id=%d channel=%d", id, channel);
5827                         break;
5828                 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5829                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5830                             "SAS Device Status Change: Internal Device "
5831                             "Reset : id=%d channel=%d", id, channel);
5832                         break;
5833                 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5834                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5835                             "SAS Device Status Change: Internal Task "
5836                             "Abort : id=%d channel=%d", id, channel);
5837                         break;
5838                 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5839                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5840                             "SAS Device Status Change: Internal Abort "
5841                             "Task Set : id=%d channel=%d", id, channel);
5842                         break;
5843                 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5844                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5845                             "SAS Device Status Change: Internal Clear "
5846                             "Task Set : id=%d channel=%d", id, channel);
5847                         break;
5848                 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5849                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5850                             "SAS Device Status Change: Internal Query "
5851                             "Task : id=%d channel=%d", id, channel);
5852                         break;
5853                 default:
5854                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5855                             "SAS Device Status Change: Unknown: "
5856                             "id=%d channel=%d", id, channel);
5857                         break;
5858                 }
5859                 break;
5860         }
5861         case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5862                 ds = "Bus Timer Expired";
5863                 break;
5864         case MPI_EVENT_QUEUE_FULL:
5865         {
5866                 u16 curr_depth = (u16)(evData0 >> 16);
5867                 u8 channel = (u8)(evData0 >> 8);
5868                 u8 id = (u8)(evData0);
5869
5870                 snprintf(evStr, EVENT_DESCR_STR_SZ,
5871                    "Queue Full: channel=%d id=%d depth=%d",
5872                    channel, id, curr_depth);
5873                 break;
5874         }
5875         case MPI_EVENT_SAS_SES:
5876                 ds = "SAS SES Event";
5877                 break;
5878         case MPI_EVENT_PERSISTENT_TABLE_FULL:
5879                 ds = "Persistent Table Full";
5880                 break;
5881         case MPI_EVENT_SAS_PHY_LINK_STATUS:
5882         {
5883                 u8 LinkRates = (u8)(evData0 >> 8);
5884                 u8 PhyNumber = (u8)(evData0);
5885                 LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
5886                         MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
5887                 switch (LinkRates) {
5888                 case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
5889                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5890                            "SAS PHY Link Status: Phy=%d:"
5891                            " Rate Unknown",PhyNumber);
5892                         break;
5893                 case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
5894                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5895                            "SAS PHY Link Status: Phy=%d:"
5896                            " Phy Disabled",PhyNumber);
5897                         break;
5898                 case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
5899                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5900                            "SAS PHY Link Status: Phy=%d:"
5901                            " Failed Speed Nego",PhyNumber);
5902                         break;
5903                 case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
5904                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5905                            "SAS PHY Link Status: Phy=%d:"
5906                            " Sata OOB Completed",PhyNumber);
5907                         break;
5908                 case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
5909                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5910                            "SAS PHY Link Status: Phy=%d:"
5911                            " Rate 1.5 Gbps",PhyNumber);
5912                         break;
5913                 case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
5914                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5915                            "SAS PHY Link Status: Phy=%d:"
5916                            " Rate 3.0 Gpbs",PhyNumber);
5917                         break;
5918                 default:
5919                         snprintf(evStr, EVENT_DESCR_STR_SZ,
5920                            "SAS PHY Link Status: Phy=%d", PhyNumber);
5921                         break;
5922                 }
5923                 break;
5924         }
5925         case MPI_EVENT_SAS_DISCOVERY_ERROR:
5926                 ds = "SAS Discovery Error";
5927                 break;
5928         case MPI_EVENT_IR_RESYNC_UPDATE:
5929         {
5930                 u8 resync_complete = (u8)(evData0 >> 16);
5931                 snprintf(evStr, EVENT_DESCR_STR_SZ,
5932                     "IR Resync Update: Complete = %d:",resync_complete);
5933                 break;
5934         }
5935         case MPI_EVENT_IR2:
5936         {
5937                 u8 ReasonCode = (u8)(evData0 >> 16);
5938                 switch (ReasonCode) {
5939                 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
5940                         ds = "IR2: LD State Changed";
5941                         break;
5942                 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
5943                         ds = "IR2: PD State Changed";
5944                         break;
5945                 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
5946                         ds = "IR2: Bad Block Table Full";
5947                         break;
5948                 case MPI_EVENT_IR2_RC_PD_INSERTED:
5949                         ds = "IR2: PD Inserted";
5950                         break;
5951                 case MPI_EVENT_IR2_RC_PD_REMOVED:
5952                         ds = "IR2: PD Removed";
5953                         break;
5954                 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
5955                         ds = "IR2: Foreign CFG Detected";
5956                         break;
5957                 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
5958                         ds = "IR2: Rebuild Medium Error";
5959                         break;
5960                 default:
5961                         ds = "IR2";
5962                 break;
5963                 }
5964                 break;
5965         }
5966         case MPI_EVENT_SAS_DISCOVERY:
5967         {
5968                 if (evData0)
5969                         ds = "SAS Discovery: Start";
5970                 else
5971                         ds = "SAS Discovery: Stop";
5972                 break;
5973         }
5974         case MPI_EVENT_LOG_ENTRY_ADDED:
5975                 ds = "SAS Log Entry Added";
5976                 break;
5977
5978         case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
5979         {
5980                 u8 phy_num = (u8)(evData0);
5981                 u8 port_num = (u8)(evData0 >> 8);
5982                 u8 port_width = (u8)(evData0 >> 16);
5983                 u8 primative = (u8)(evData0 >> 24);
5984                 snprintf(evStr, EVENT_DESCR_STR_SZ,
5985                     "SAS Broadcase Primative: phy=%d port=%d "
5986                     "width=%d primative=0x%02x",
5987                     phy_num, port_num, port_width, primative);
5988                 break;
5989         }
5990
5991         case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
5992         {
5993                 u8 reason = (u8)(evData0);
5994                 u8 port_num = (u8)(evData0 >> 8);
5995                 u16 handle = le16_to_cpu(evData0 >> 16);
5996
5997                 snprintf(evStr, EVENT_DESCR_STR_SZ,
5998                     "SAS Initiator Device Status Change: reason=0x%02x "
5999                     "port=%d handle=0x%04x",
6000                     reason, port_num, handle);
6001                 break;
6002         }
6003
6004         case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
6005         {
6006                 u8 max_init = (u8)(evData0);
6007                 u8 current_init = (u8)(evData0 >> 8);
6008
6009                 snprintf(evStr, EVENT_DESCR_STR_SZ,
6010                     "SAS Initiator Device Table Overflow: max initiators=%02d "
6011                     "current initators=%02d",
6012                     max_init, current_init);
6013                 break;
6014         }
6015         case MPI_EVENT_SAS_SMP_ERROR:
6016         {
6017                 u8 status = (u8)(evData0);
6018                 u8 port_num = (u8)(evData0 >> 8);
6019                 u8 result = (u8)(evData0 >> 16);
6020
6021                 if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
6022                         snprintf(evStr, EVENT_DESCR_STR_SZ,
6023                             "SAS SMP Error: port=%d result=0x%02x",
6024                             port_num, result);
6025                 else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
6026                         snprintf(evStr, EVENT_DESCR_STR_SZ,
6027                             "SAS SMP Error: port=%d : CRC Error",
6028                             port_num);
6029                 else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
6030                         snprintf(evStr, EVENT_DESCR_STR_SZ,
6031                             "SAS SMP Error: port=%d : Timeout",
6032                             port_num);
6033                 else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
6034                         snprintf(evStr, EVENT_DESCR_STR_SZ,
6035                             "SAS SMP Error: port=%d : No Destination",
6036                             port_num);
6037                 else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
6038                         snprintf(evStr, EVENT_DESCR_STR_SZ,
6039                             "SAS SMP Error: port=%d : Bad Destination",
6040                             port_num);
6041                 else
6042                         snprintf(evStr, EVENT_DESCR_STR_SZ,
6043                             "SAS SMP Error: port=%d : status=0x%02x",
6044                             port_num, status);
6045                 break;
6046         }
6047
6048         /*
6049          *  MPT base "custom" events may be added here...
6050          */
6051         default:
6052                 ds = "Unknown";
6053                 break;
6054         }
6055         if (ds)
6056                 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6057 }
6058
6059 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6060 /**
6061  *      ProcessEventNotification - Route EventNotificationReply to all event handlers
6062  *      @ioc: Pointer to MPT_ADAPTER structure
6063  *      @pEventReply: Pointer to EventNotification reply frame
6064  *      @evHandlers: Pointer to integer, number of event handlers
6065  *
6066  *      Routes a received EventNotificationReply to all currently registered
6067  *      event handlers.
6068  *      Returns sum of event handlers return values.
6069  */
6070 static int
6071 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6072 {
6073         u16 evDataLen;
6074         u32 evData0 = 0;
6075 //      u32 evCtx;
6076         int ii;
6077         int r = 0;
6078         int handlers = 0;
6079         char evStr[EVENT_DESCR_STR_SZ];
6080         u8 event;
6081
6082         /*
6083          *  Do platform normalization of values
6084          */
6085         event = le32_to_cpu(pEventReply->Event) & 0xFF;
6086 //      evCtx = le32_to_cpu(pEventReply->EventContext);
6087         evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6088         if (evDataLen) {
6089                 evData0 = le32_to_cpu(pEventReply->Data[0]);
6090         }
6091
6092         EventDescriptionStr(event, evData0, evStr);
6093         devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
6094                         ioc->name,
6095                         event,
6096                         evStr));
6097
6098 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
6099         printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
6100         for (ii = 0; ii < evDataLen; ii++)
6101                 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
6102         printk("\n");
6103 #endif
6104
6105         /*
6106          *  Do general / base driver event processing
6107          */
6108         switch(event) {
6109         case MPI_EVENT_EVENT_CHANGE:            /* 0A */
6110                 if (evDataLen) {
6111                         u8 evState = evData0 & 0xFF;
6112
6113                         /* CHECKME! What if evState unexpectedly says OFF (0)? */
6114
6115                         /* Update EventState field in cached IocFacts */
6116                         if (ioc->facts.Function) {
6117                                 ioc->facts.EventState = evState;
6118                         }
6119                 }
6120                 break;
6121         case MPI_EVENT_INTEGRATED_RAID:
6122                 mptbase_raid_process_event_data(ioc,
6123                     (MpiEventDataRaid_t *)pEventReply->Data);
6124                 break;
6125         default:
6126                 break;
6127         }
6128
6129         /*
6130          * Should this event be logged? Events are written sequentially.
6131          * When buffer is full, start again at the top.
6132          */
6133         if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6134                 int idx;
6135
6136                 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6137
6138                 ioc->events[idx].event = event;
6139                 ioc->events[idx].eventContext = ioc->eventContext;
6140
6141                 for (ii = 0; ii < 2; ii++) {
6142                         if (ii < evDataLen)
6143                                 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6144                         else
6145                                 ioc->events[idx].data[ii] =  0;
6146                 }
6147
6148                 ioc->eventContext++;
6149         }
6150
6151
6152         /*
6153          *  Call each currently registered protocol event handler.
6154          */
6155         for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6156                 if (MptEvHandlers[ii]) {
6157                         devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6158                                         ioc->name, ii));
6159                         r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6160                         handlers++;
6161                 }
6162         }
6163         /* FIXME?  Examine results here? */
6164
6165         /*
6166          *  If needed, send (a single) EventAck.
6167          */
6168         if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6169                 devtverboseprintk((MYIOC_s_WARN_FMT
6170                         "EventAck required\n",ioc->name));
6171                 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6172                         devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6173                                         ioc->name, ii));
6174                 }
6175         }
6176
6177         *evHandlers = handlers;
6178         return r;
6179 }
6180
6181 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6182 /**
6183  *      mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6184  *      @ioc: Pointer to MPT_ADAPTER structure
6185  *      @log_info: U32 LogInfo reply word from the IOC
6186  *
6187  *      Refer to lsi/mpi_log_fc.h.
6188  */
6189 static void
6190 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6191 {
6192         static char *subcl_str[8] = {
6193                 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6194                 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6195         };
6196         u8 subcl = (log_info >> 24) & 0x7;
6197
6198         printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6199                         ioc->name, log_info, subcl_str[subcl]);
6200 }
6201
6202 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6203 /**
6204  *      mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6205  *      @ioc: Pointer to MPT_ADAPTER structure
6206  *      @mr: Pointer to MPT reply frame
6207  *      @log_info: U32 LogInfo word from the IOC
6208  *
6209  *      Refer to lsi/sp_log.h.
6210  */
6211 static void
6212 mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6213 {
6214         u32 info = log_info & 0x00FF0000;
6215         char *desc = "unknown";
6216
6217         switch (info) {
6218         case 0x00010000:
6219                 desc = "bug! MID not found";
6220                 if (ioc->reload_fw == 0)
6221                         ioc->reload_fw++;
6222                 break;
6223
6224         case 0x00020000:
6225                 desc = "Parity Error";
6226                 break;
6227
6228         case 0x00030000:
6229                 desc = "ASYNC Outbound Overrun";
6230                 break;
6231
6232         case 0x00040000:
6233                 desc = "SYNC Offset Error";
6234                 break;
6235
6236         case 0x00050000:
6237                 desc = "BM Change";
6238                 break;
6239
6240         case 0x00060000:
6241                 desc = "Msg In Overflow";
6242                 break;
6243
6244         case 0x00070000:
6245                 desc = "DMA Error";
6246                 break;
6247
6248         case 0x00080000:
6249                 desc = "Outbound DMA Overrun";
6250                 break;
6251
6252         case 0x00090000:
6253                 desc = "Task Management";
6254                 break;
6255
6256         case 0x000A0000:
6257                 desc = "Device Problem";
6258                 break;
6259
6260         case 0x000B0000:
6261                 desc = "Invalid Phase Change";
6262                 break;
6263
6264         case 0x000C0000:
6265                 desc = "Untagged Table Size";
6266                 break;
6267
6268         }
6269
6270         printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6271 }
6272
6273 /* strings for sas loginfo */
6274         static char *originator_str[] = {
6275                 "IOP",                                          /* 00h */
6276                 "PL",                                           /* 01h */
6277                 "IR"                                            /* 02h */
6278         };
6279         static char *iop_code_str[] = {
6280                 NULL,                                           /* 00h */
6281                 "Invalid SAS Address",                          /* 01h */
6282                 NULL,                                           /* 02h */
6283                 "Invalid Page",                                 /* 03h */
6284                 "Diag Message Error",                           /* 04h */
6285                 "Task Terminated",                              /* 05h */
6286                 "Enclosure Management",                         /* 06h */
6287                 "Target Mode"                                   /* 07h */
6288         };
6289         static char *pl_code_str[] = {
6290                 NULL,                                           /* 00h */
6291                 "Open Failure",                                 /* 01h */
6292                 "Invalid Scatter Gather List",                  /* 02h */
6293                 "Wrong Relative Offset or Frame Length",        /* 03h */
6294                 "Frame Transfer Error",                         /* 04h */
6295                 "Transmit Frame Connected Low",                 /* 05h */
6296                 "SATA Non-NCQ RW Error Bit Set",                /* 06h */
6297                 "SATA Read Log Receive Data Error",             /* 07h */
6298                 "SATA NCQ Fail All Commands After Error",       /* 08h */
6299                 "SATA Error in Receive Set Device Bit FIS",     /* 09h */
6300                 "Receive Frame Invalid Message",                /* 0Ah */
6301                 "Receive Context Message Valid Error",          /* 0Bh */
6302                 "Receive Frame Current Frame Error",            /* 0Ch */
6303                 "SATA Link Down",                               /* 0Dh */
6304                 "Discovery SATA Init W IOS",                    /* 0Eh */
6305                 "Config Invalid Page",                          /* 0Fh */
6306                 "Discovery SATA Init Timeout",                  /* 10h */
6307                 "Reset",                                        /* 11h */
6308                 "Abort",                                        /* 12h */
6309                 "IO Not Yet Executed",                          /* 13h */
6310                 "IO Executed",                                  /* 14h */
6311                 "Persistent Reservation Out Not Affiliation "
6312                     "Owner",                                    /* 15h */
6313                 "Open Transmit DMA Abort",                      /* 16h */
6314                 "IO Device Missing Delay Retry",                /* 17h */
6315                 "IO Cancelled Due to Recieve Error",            /* 18h */
6316                 NULL,                                           /* 19h */
6317                 NULL,                                           /* 1Ah */
6318                 NULL,                                           /* 1Bh */
6319                 NULL,                                           /* 1Ch */
6320                 NULL,                                           /* 1Dh */
6321                 NULL,                                           /* 1Eh */
6322                 NULL,                                           /* 1Fh */
6323                 "Enclosure Management"                          /* 20h */
6324         };
6325         static char *ir_code_str[] = {
6326                 "Raid Action Error",                            /* 00h */
6327                 NULL,                                           /* 00h */
6328                 NULL,                                           /* 01h */
6329                 NULL,                                           /* 02h */
6330                 NULL,                                           /* 03h */
6331                 NULL,                                           /* 04h */
6332                 NULL,                                           /* 05h */
6333                 NULL,                                           /* 06h */
6334                 NULL                                            /* 07h */
6335         };
6336         static char *raid_sub_code_str[] = {
6337                 NULL,                                           /* 00h */
6338                 "Volume Creation Failed: Data Passed too "
6339                     "Large",                                    /* 01h */
6340                 "Volume Creation Failed: Duplicate Volumes "
6341                     "Attempted",                                /* 02h */
6342                 "Volume Creation Failed: Max Number "
6343                     "Supported Volumes Exceeded",               /* 03h */
6344                 "Volume Creation Failed: DMA Error",            /* 04h */
6345                 "Volume Creation Failed: Invalid Volume Type",  /* 05h */
6346                 "Volume Creation Failed: Error Reading "
6347                     "MFG Page 4",                               /* 06h */
6348                 "Volume Creation Failed: Creating Internal "
6349                     "Structures",                               /* 07h */
6350                 NULL,                                           /* 08h */
6351                 NULL,                                           /* 09h */
6352                 NULL,                                           /* 0Ah */
6353                 NULL,                                           /* 0Bh */
6354                 NULL,                                           /* 0Ch */
6355                 NULL,                                           /* 0Dh */
6356                 NULL,                                           /* 0Eh */
6357                 NULL,                                           /* 0Fh */
6358                 "Activation failed: Already Active Volume",     /* 10h */
6359                 "Activation failed: Unsupported Volume Type",   /* 11h */
6360                 "Activation failed: Too Many Active Volumes",   /* 12h */
6361                 "Activation failed: Volume ID in Use",          /* 13h */
6362                 "Activation failed: Reported Failure",          /* 14h */
6363                 "Activation failed: Importing a Volume",        /* 15h */
6364                 NULL,                                           /* 16h */
6365                 NULL,                                           /* 17h */
6366                 NULL,                                           /* 18h */
6367                 NULL,                                           /* 19h */
6368                 NULL,                                           /* 1Ah */
6369                 NULL,                                           /* 1Bh */
6370                 NULL,                                           /* 1Ch */
6371                 NULL,                                           /* 1Dh */
6372                 NULL,                                           /* 1Eh */
6373                 NULL,                                           /* 1Fh */
6374                 "Phys Disk failed: Too Many Phys Disks",        /* 20h */
6375                 "Phys Disk failed: Data Passed too Large",      /* 21h */
6376                 "Phys Disk failed: DMA Error",                  /* 22h */
6377                 "Phys Disk failed: Invalid <channel:id>",       /* 23h */
6378                 "Phys Disk failed: Creating Phys Disk Config "
6379                     "Page",                                     /* 24h */
6380                 NULL,                                           /* 25h */
6381                 NULL,                                           /* 26h */
6382                 NULL,                                           /* 27h */
6383                 NULL,                                           /* 28h */
6384                 NULL,                                           /* 29h */
6385                 NULL,                                           /* 2Ah */
6386                 NULL,                                           /* 2Bh */
6387                 NULL,                                           /* 2Ch */
6388                 NULL,                                           /* 2Dh */
6389                 NULL,                                           /* 2Eh */
6390                 NULL,                                           /* 2Fh */
6391                 "Compatibility Error: IR Disabled",             /* 30h */
6392                 "Compatibility Error: Inquiry Comand Failed",   /* 31h */
6393                 "Compatibility Error: Device not Direct Access "
6394                     "Device ",                                  /* 32h */
6395                 "Compatibility Error: Removable Device Found",  /* 33h */
6396                 "Compatibility Error: Device SCSI Version not "
6397                     "2 or Higher",                              /* 34h */
6398                 "Compatibility Error: SATA Device, 48 BIT LBA "
6399                     "not Supported",                            /* 35h */
6400                 "Compatibility Error: Device doesn't have "
6401                     "512 Byte Block Sizes",                     /* 36h */
6402                 "Compatibility Error: Volume Type Check Failed", /* 37h */
6403                 "Compatibility Error: Volume Type is "
6404                     "Unsupported by FW",                        /* 38h */
6405                 "Compatibility Error: Disk Drive too Small for "
6406                     "use in Volume",                            /* 39h */
6407                 "Compatibility Error: Phys Disk for Create "
6408                     "Volume not Found",                         /* 3Ah */
6409                 "Compatibility Error: Too Many or too Few "
6410                     "Disks for Volume Type",                    /* 3Bh */
6411                 "Compatibility Error: Disk stripe Sizes "
6412                     "Must be 64KB",                             /* 3Ch */
6413                 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
6414         };
6415
6416 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6417 /**
6418  *      mpt_sas_log_info - Log information returned from SAS IOC.
6419  *      @ioc: Pointer to MPT_ADAPTER structure
6420  *      @log_info: U32 LogInfo reply word from the IOC
6421  *
6422  *      Refer to lsi/mpi_log_sas.h.
6423  **/
6424 static void
6425 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6426 {
6427 union loginfo_type {
6428         u32     loginfo;
6429         struct {
6430                 u32     subcode:16;
6431                 u32     code:8;
6432                 u32     originator:4;
6433                 u32     bus_type:4;
6434         }dw;
6435 };
6436         union loginfo_type sas_loginfo;
6437         char *originator_desc = NULL;
6438         char *code_desc = NULL;
6439         char *sub_code_desc = NULL;
6440
6441         sas_loginfo.loginfo = log_info;
6442         if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6443             (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6444                 return;
6445
6446         originator_desc = originator_str[sas_loginfo.dw.originator];
6447
6448         switch (sas_loginfo.dw.originator) {
6449
6450                 case 0:  /* IOP */
6451                         if (sas_loginfo.dw.code <
6452                             sizeof(iop_code_str)/sizeof(char*))
6453                                 code_desc = iop_code_str[sas_loginfo.dw.code];
6454                         break;
6455                 case 1:  /* PL */
6456                         if (sas_loginfo.dw.code <
6457                             sizeof(pl_code_str)/sizeof(char*))
6458                                 code_desc = pl_code_str[sas_loginfo.dw.code];
6459                         break;
6460                 case 2:  /* IR */
6461                         if (sas_loginfo.dw.code >=
6462                             sizeof(ir_code_str)/sizeof(char*))
6463                                 break;
6464                         code_desc = ir_code_str[sas_loginfo.dw.code];
6465                         if (sas_loginfo.dw.subcode >=
6466                             sizeof(raid_sub_code_str)/sizeof(char*))
6467                         break;
6468                         if (sas_loginfo.dw.code == 0)
6469                                 sub_code_desc =
6470                                     raid_sub_code_str[sas_loginfo.dw.subcode];
6471                         break;
6472                 default:
6473                         return;
6474         }
6475
6476         if (sub_code_desc != NULL)
6477                 printk(MYIOC_s_INFO_FMT
6478                         "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6479                         " SubCode={%s}\n",
6480                         ioc->name, log_info, originator_desc, code_desc,
6481                         sub_code_desc);
6482         else if (code_desc != NULL)
6483                 printk(MYIOC_s_INFO_FMT
6484                         "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6485                         " SubCode(0x%04x)\n",
6486                         ioc->name, log_info, originator_desc, code_desc,
6487                         sas_loginfo.dw.subcode);
6488         else
6489                 printk(MYIOC_s_INFO_FMT
6490                         "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6491                         " SubCode(0x%04x)\n",
6492                         ioc->name, log_info, originator_desc,
6493                         sas_loginfo.dw.code, sas_loginfo.dw.subcode);
6494 }
6495
6496 #ifdef MPT_DEBUG_REPLY
6497 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6498 /**
6499  *      mpt_iocstatus_info_config - IOCSTATUS information for config pages
6500  *      @ioc: Pointer to MPT_ADAPTER structure
6501  *      ioc_status: U32 IOCStatus word from IOC
6502  *      @mf: Pointer to MPT request frame
6503  *
6504  *      Refer to lsi/mpi.h.
6505  **/
6506 static void
6507 mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6508 {
6509         Config_t *pReq = (Config_t *)mf;
6510         char extend_desc[EVENT_DESCR_STR_SZ];
6511         char *desc = NULL;
6512         u32 form;
6513         u8 page_type;
6514
6515         if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
6516                 page_type = pReq->ExtPageType;
6517         else
6518                 page_type = pReq->Header.PageType;
6519
6520         /*
6521          * ignore invalid page messages for GET_NEXT_HANDLE
6522          */
6523         form = le32_to_cpu(pReq->PageAddress);
6524         if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
6525                 if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
6526                     page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
6527                     page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
6528                         if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
6529                                 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
6530                                 return;
6531                 }
6532                 if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
6533                         if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
6534                                 MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
6535                                 return;
6536         }
6537
6538         snprintf(extend_desc, EVENT_DESCR_STR_SZ,
6539             "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
6540             page_type, pReq->Header.PageNumber, pReq->Action, form);
6541
6542         switch (ioc_status) {
6543
6544         case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6545                 desc = "Config Page Invalid Action";
6546                 break;
6547
6548         case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
6549                 desc = "Config Page Invalid Type";
6550                 break;
6551
6552         case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
6553                 desc = "Config Page Invalid Page";
6554                 break;
6555
6556         case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
6557                 desc = "Config Page Invalid Data";
6558                 break;
6559
6560         case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
6561                 desc = "Config Page No Defaults";
6562                 break;
6563
6564         case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
6565                 desc = "Config Page Can't Commit";
6566                 break;
6567         }
6568
6569         if (!desc)
6570                 return;
6571
6572         printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
6573             ioc->name, ioc_status, desc, extend_desc);
6574 }
6575
6576 /**
6577  *      mpt_iocstatus_info - IOCSTATUS information returned from IOC.
6578  *      @ioc: Pointer to MPT_ADAPTER structure
6579  *      @ioc_status: U32 IOCStatus word from IOC
6580  *      @mf: Pointer to MPT request frame
6581  *
6582  *      Refer to lsi/mpi.h.
6583  **/
6584 static void
6585 mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6586 {
6587         u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6588         char *desc = NULL;
6589
6590         switch (status) {
6591
6592 /****************************************************************************/
6593 /*  Common IOCStatus values for all replies                                 */
6594 /****************************************************************************/
6595
6596         case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6597                 desc = "Invalid Function";
6598                 break;
6599
6600         case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6601                 desc = "Busy";
6602                 break;
6603
6604         case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6605                 desc = "Invalid SGL";
6606                 break;
6607
6608         case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6609                 desc = "Internal Error";
6610                 break;
6611
6612         case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6613                 desc = "Reserved";
6614                 break;
6615
6616         case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6617                 desc = "Insufficient Resources";
6618                 break;
6619
6620         case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6621                 desc = "Invalid Field";
6622                 break;
6623
6624         case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6625                 desc = "Invalid State";
6626                 break;
6627
6628 /****************************************************************************/
6629 /*  Config IOCStatus values                                                 */
6630 /****************************************************************************/
6631
6632         case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6633         case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
6634         case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
6635         case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
6636         case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
6637         case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
6638                 mpt_iocstatus_info_config(ioc, status, mf);
6639                 break;
6640
6641 /****************************************************************************/
6642 /*  SCSIIO Reply (SPI, FCP, SAS) initiator values                           */
6643 /*                                                                          */
6644 /*  Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
6645 /*                                                                          */
6646 /****************************************************************************/
6647
6648         case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6649         case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6650         case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6651         case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6652         case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6653         case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6654         case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6655         case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6656         case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6657         case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6658         case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6659         case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6660         case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6661                 break;
6662
6663 /****************************************************************************/
6664 /*  SCSI Target values                                                      */
6665 /****************************************************************************/
6666
6667         case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
6668                 desc = "Target: Priority IO";
6669                 break;
6670
6671         case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
6672                 desc = "Target: Invalid Port";
6673                 break;
6674
6675         case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
6676                 desc = "Target Invalid IO Index:";
6677                 break;
6678
6679         case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
6680                 desc = "Target: Aborted";
6681                 break;
6682
6683         case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
6684                 desc = "Target: No Conn Retryable";
6685                 break;
6686
6687         case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
6688                 desc = "Target: No Connection";
6689                 break;
6690
6691         case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
6692                 desc = "Target: Transfer Count Mismatch";
6693                 break;
6694
6695         case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
6696                 desc = "Target: STS Data not Sent";
6697                 break;
6698
6699         case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
6700                 desc = "Target: Data Offset Error";
6701                 break;
6702
6703         case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
6704                 desc = "Target: Too Much Write Data";
6705                 break;
6706
6707         case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
6708                 desc = "Target: IU Too Short";
6709                 break;
6710
6711         case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
6712                 desc = "Target: ACK NAK Timeout";
6713                 break;
6714
6715         case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
6716                 desc = "Target: Nak Received";
6717                 break;
6718
6719 /****************************************************************************/
6720 /*  Fibre Channel Direct Access values                                      */
6721 /****************************************************************************/
6722
6723         case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
6724                 desc = "FC: Aborted";
6725                 break;
6726
6727         case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
6728                 desc = "FC: RX ID Invalid";
6729                 break;
6730
6731         case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
6732                 desc = "FC: DID Invalid";
6733                 break;
6734
6735         case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
6736                 desc = "FC: Node Logged Out";
6737                 break;
6738
6739         case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
6740                 desc = "FC: Exchange Canceled";
6741                 break;
6742
6743 /****************************************************************************/
6744 /*  LAN values                                                              */
6745 /****************************************************************************/
6746
6747         case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
6748                 desc = "LAN: Device not Found";
6749                 break;
6750
6751         case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
6752                 desc = "LAN: Device Failure";
6753                 break;
6754
6755         case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
6756                 desc = "LAN: Transmit Error";
6757                 break;
6758
6759         case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
6760                 desc = "LAN: Transmit Aborted";
6761                 break;
6762
6763         case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
6764                 desc = "LAN: Receive Error";
6765                 break;
6766
6767         case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
6768                 desc = "LAN: Receive Aborted";
6769                 break;
6770
6771         case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
6772                 desc = "LAN: Partial Packet";
6773                 break;
6774
6775         case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
6776                 desc = "LAN: Canceled";
6777                 break;
6778
6779 /****************************************************************************/
6780 /*  Serial Attached SCSI values                                             */
6781 /****************************************************************************/
6782
6783         case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
6784                 desc = "SAS: SMP Request Failed";
6785                 break;
6786
6787         case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
6788                 desc = "SAS: SMP Data Overrun";
6789                 break;
6790
6791         default:
6792                 desc = "Others";
6793                 break;
6794         }
6795
6796         if (!desc)
6797                 return;
6798
6799         printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc);
6800 }
6801 #endif
6802
6803 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6804 EXPORT_SYMBOL(mpt_attach);
6805 EXPORT_SYMBOL(mpt_detach);
6806 #ifdef CONFIG_PM
6807 EXPORT_SYMBOL(mpt_resume);
6808 EXPORT_SYMBOL(mpt_suspend);
6809 #endif
6810 EXPORT_SYMBOL(ioc_list);
6811 EXPORT_SYMBOL(mpt_proc_root_dir);
6812 EXPORT_SYMBOL(mpt_register);
6813 EXPORT_SYMBOL(mpt_deregister);
6814 EXPORT_SYMBOL(mpt_event_register);
6815 EXPORT_SYMBOL(mpt_event_deregister);
6816 EXPORT_SYMBOL(mpt_reset_register);
6817 EXPORT_SYMBOL(mpt_reset_deregister);
6818 EXPORT_SYMBOL(mpt_device_driver_register);
6819 EXPORT_SYMBOL(mpt_device_driver_deregister);
6820 EXPORT_SYMBOL(mpt_get_msg_frame);
6821 EXPORT_SYMBOL(mpt_put_msg_frame);
6822 EXPORT_SYMBOL(mpt_free_msg_frame);
6823 EXPORT_SYMBOL(mpt_add_sge);
6824 EXPORT_SYMBOL(mpt_send_handshake_request);
6825 EXPORT_SYMBOL(mpt_verify_adapter);
6826 EXPORT_SYMBOL(mpt_GetIocState);
6827 EXPORT_SYMBOL(mpt_print_ioc_summary);
6828 EXPORT_SYMBOL(mpt_lan_index);
6829 EXPORT_SYMBOL(mpt_stm_index);
6830 EXPORT_SYMBOL(mpt_HardResetHandler);
6831 EXPORT_SYMBOL(mpt_config);
6832 EXPORT_SYMBOL(mpt_findImVolumes);
6833 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6834 EXPORT_SYMBOL(mpt_free_fw_memory);
6835 EXPORT_SYMBOL(mptbase_sas_persist_operation);
6836
6837 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6838 /**
6839  *      fusion_init - Fusion MPT base driver initialization routine.
6840  *
6841  *      Returns 0 for success, non-zero for failure.
6842  */
6843 static int __init
6844 fusion_init(void)
6845 {
6846         int i;
6847
6848         show_mptmod_ver(my_NAME, my_VERSION);
6849         printk(KERN_INFO COPYRIGHT "\n");
6850
6851         for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6852                 MptCallbacks[i] = NULL;
6853                 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6854                 MptEvHandlers[i] = NULL;
6855                 MptResetHandlers[i] = NULL;
6856         }
6857
6858         /*  Register ourselves (mptbase) in order to facilitate
6859          *  EventNotification handling.
6860          */
6861         mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6862
6863         /* Register for hard reset handling callbacks.
6864          */
6865         if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6866                 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6867         } else {
6868                 /* FIXME! */
6869         }
6870
6871 #ifdef CONFIG_PROC_FS
6872         (void) procmpt_create();
6873 #endif
6874         return 0;
6875 }
6876
6877 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6878 /**
6879  *      fusion_exit - Perform driver unload cleanup.
6880  *
6881  *      This routine frees all resources associated with each MPT adapter
6882  *      and removes all %MPT_PROCFS_MPTBASEDIR entries.
6883  */
6884 static void __exit
6885 fusion_exit(void)
6886 {
6887
6888         dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6889
6890         mpt_reset_deregister(mpt_base_index);
6891
6892 #ifdef CONFIG_PROC_FS
6893         procmpt_destroy();
6894 #endif
6895 }
6896
6897 module_init(fusion_init);
6898 module_exit(fusion_exit);