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