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