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