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