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