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