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