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