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