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