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