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