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