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