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