Print this page
NEX-18318 qlt needs to disable MSI-X if running passthrough under ESXi
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-14413 Bad trap in module "apix" due to a NULL pointer dereference
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-10267 BAD TRAP: type=d (#gp General protection) in qlt_msix_resp_handler()
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-5733 cleanup qlt/qlc
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5717 import QLogic 16G FC drivers
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
*** 18,33 ****
*
* CDDL HEADER END
*/
/*
! * Copyright 2009 QLogic Corporation. All rights reserved.
* Use is subject to license terms.
*/
/*
! * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/stat.h>
--- 18,33 ----
*
* CDDL HEADER END
*/
/*
! * Copyright 2009-2015 QLogic Corporation. All rights reserved.
* Use is subject to license terms.
*/
/*
! * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/stat.h>
*** 37,51 ****
#include <sys/file.h>
#include <sys/cred.h>
#include <sys/byteorder.h>
#include <sys/atomic.h>
#include <sys/scsi/scsi.h>
#include <sys/stmf_defines.h>
#include <sys/fct_defines.h>
#include <sys/stmf.h>
- #include <sys/stmf_ioctl.h>
#include <sys/portif.h>
#include <sys/fct.h>
#include "qlt.h"
#include "qlt_dma.h"
--- 37,55 ----
#include <sys/file.h>
#include <sys/cred.h>
#include <sys/byteorder.h>
#include <sys/atomic.h>
#include <sys/scsi/scsi.h>
+ #include <sys/time.h>
+ #ifdef __x86
+ #include <sys/x86_archext.h>
+ #endif
#include <sys/stmf_defines.h>
+ #include <sys/stmf_ioctl.h>
#include <sys/fct_defines.h>
#include <sys/stmf.h>
#include <sys/portif.h>
#include <sys/fct.h>
#include "qlt.h"
#include "qlt_dma.h"
*** 52,61 ****
--- 56,69 ----
#include "qlt_ioctl.h"
#include "qlt_open.h"
static int qlt_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
static int qlt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
+ static uint8_t *qlt_vpd_findtag(qlt_state_t *qlt, uint8_t *vpdbuf,
+ int8_t *opcode);
+ static int qlt_vpd_lookup(qlt_state_t *qlt, uint8_t *opcode, uint8_t *bp,
+ int32_t bplen);
static void qlt_enable_intr(qlt_state_t *);
static void qlt_disable_intr(qlt_state_t *);
static fct_status_t qlt_reset_chip(qlt_state_t *qlt);
static fct_status_t qlt_download_fw(qlt_state_t *qlt);
static fct_status_t qlt_load_risc_ram(qlt_state_t *qlt, uint32_t *host_addr,
*** 64,88 ****
static mbox_cmd_t *qlt_alloc_mailbox_command(qlt_state_t *qlt,
uint32_t dma_size);
void qlt_free_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp);
static fct_status_t qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp);
static uint_t qlt_isr(caddr_t arg, caddr_t arg2);
static fct_status_t qlt_firmware_dump(fct_local_port_t *port,
stmf_state_change_info_t *ssci);
static void qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot);
static void qlt_handle_purex(qlt_state_t *qlt, uint8_t *resp);
static void qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio);
! static void qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp);
static void qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp);
static void qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp);
static void qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp);
static void qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt,
uint8_t *rsp);
static void qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp);
! static void qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp);
! static void qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp);
static fct_status_t qlt_read_nvram(qlt_state_t *qlt);
static void qlt_verify_fw(qlt_state_t *qlt);
static void qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp);
fct_status_t qlt_port_start(caddr_t arg);
fct_status_t qlt_port_stop(caddr_t arg);
fct_status_t qlt_port_online(qlt_state_t *qlt);
--- 72,102 ----
static mbox_cmd_t *qlt_alloc_mailbox_command(qlt_state_t *qlt,
uint32_t dma_size);
void qlt_free_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp);
static fct_status_t qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp);
static uint_t qlt_isr(caddr_t arg, caddr_t arg2);
+ static uint_t qlt_msix_resp_handler(caddr_t arg, caddr_t arg2);
+ static uint_t qlt_msix_default_handler(caddr_t arg, caddr_t arg2);
static fct_status_t qlt_firmware_dump(fct_local_port_t *port,
stmf_state_change_info_t *ssci);
static void qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot);
static void qlt_handle_purex(qlt_state_t *qlt, uint8_t *resp);
static void qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio);
! static void qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp,
! uint16_t qi);
static void qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp);
static void qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp);
static void qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp);
static void qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt,
uint8_t *rsp);
static void qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp);
! static void qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp, uint16_t qi);
! static void qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp,
! uint16_t qi);
static fct_status_t qlt_read_nvram(qlt_state_t *qlt);
+ static fct_status_t qlt_read_vpd(qlt_state_t *qlt);
+ static fct_status_t qlt_read_rom_image(qlt_state_t *qlt);
static void qlt_verify_fw(qlt_state_t *qlt);
static void qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp);
fct_status_t qlt_port_start(caddr_t arg);
fct_status_t qlt_port_stop(caddr_t arg);
fct_status_t qlt_port_online(qlt_state_t *qlt);
*** 92,102 ****
static void qlt_ctl(struct fct_local_port *port, int cmd, void *arg);
static fct_status_t qlt_force_lip(qlt_state_t *);
static fct_status_t qlt_do_flogi(struct fct_local_port *port,
fct_flogi_xchg_t *fx);
void qlt_handle_atio_queue_update(qlt_state_t *qlt);
! void qlt_handle_resp_queue_update(qlt_state_t *qlt);
fct_status_t qlt_register_remote_port(fct_local_port_t *port,
fct_remote_port_t *rp, fct_cmd_t *login);
fct_status_t qlt_deregister_remote_port(fct_local_port_t *port,
fct_remote_port_t *rp);
fct_status_t qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags);
--- 106,116 ----
static void qlt_ctl(struct fct_local_port *port, int cmd, void *arg);
static fct_status_t qlt_force_lip(qlt_state_t *);
static fct_status_t qlt_do_flogi(struct fct_local_port *port,
fct_flogi_xchg_t *fx);
void qlt_handle_atio_queue_update(qlt_state_t *qlt);
! void qlt_handle_resp_queue_update(qlt_state_t *qlt, uint16_t qi);
fct_status_t qlt_register_remote_port(fct_local_port_t *port,
fct_remote_port_t *rp, fct_cmd_t *login);
fct_status_t qlt_deregister_remote_port(fct_local_port_t *port,
fct_remote_port_t *rp);
fct_status_t qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags);
*** 121,130 ****
--- 135,146 ----
static int qlt_setup_interrupts(qlt_state_t *qlt);
static void qlt_destroy_mutex(qlt_state_t *qlt);
static fct_status_t qlt_read_risc_ram(qlt_state_t *qlt, uint32_t addr,
uint32_t words);
+ static fct_status_t qlt_mbx_mpi_ram(qlt_state_t *qlt, uint32_t addr,
+ uint32_t words, uint16_t direction);
static int qlt_dump_queue(qlt_state_t *qlt, caddr_t qadr, int entries,
caddr_t buf, uint_t size_left);
static int qlt_dump_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words,
caddr_t buf, uint_t size_left);
static int qlt_fwdump_dump_regs(qlt_state_t *qlt, caddr_t buf, int startaddr,
*** 137,148 ****
static int qlt_setup_msi(qlt_state_t *qlt);
static int qlt_setup_msix(qlt_state_t *qlt);
static int qlt_el_trace_desc_ctor(qlt_state_t *qlt);
static int qlt_el_trace_desc_dtor(qlt_state_t *qlt);
- static int qlt_validate_trace_desc(qlt_state_t *qlt);
- static char *qlt_find_trace_start(qlt_state_t *qlt);
static int qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval);
static int qlt_read_string_prop(qlt_state_t *qlt, char *prop, char **prop_val);
static int qlt_read_string_instance_prop(qlt_state_t *qlt, char *prop,
char **prop_val);
--- 153,162 ----
*** 149,170 ****
static int qlt_read_int_instance_prop(qlt_state_t *, char *, int);
static int qlt_convert_string_to_ull(char *prop, int radix,
u_longlong_t *result);
static boolean_t qlt_wwn_overload_prop(qlt_state_t *qlt);
static int qlt_quiesce(dev_info_t *dip);
static fct_status_t qlt_raw_wrt_risc_ram_word(qlt_state_t *qlt, uint32_t,
uint32_t);
static fct_status_t qlt_raw_rd_risc_ram_word(qlt_state_t *qlt, uint32_t,
uint32_t *);
static void qlt_mps_reset(qlt_state_t *qlt);
static void qlt_properties(qlt_state_t *qlt);
#define SETELSBIT(bmp, els) (bmp)[((els) >> 3) & 0x1F] = \
(uint8_t)((bmp)[((els) >> 3) & 0x1F] | ((uint8_t)1) << ((els) & 7))
! int qlt_enable_msix = 0;
int qlt_enable_msi = 1;
string_table_t prop_status_tbl[] = DDI_PROP_STATUS();
--- 163,193 ----
static int qlt_read_int_instance_prop(qlt_state_t *, char *, int);
static int qlt_convert_string_to_ull(char *prop, int radix,
u_longlong_t *result);
static boolean_t qlt_wwn_overload_prop(qlt_state_t *qlt);
static int qlt_quiesce(dev_info_t *dip);
+ static void qlt_disable_intr(qlt_state_t *qlt);
static fct_status_t qlt_raw_wrt_risc_ram_word(qlt_state_t *qlt, uint32_t,
uint32_t);
static fct_status_t qlt_raw_rd_risc_ram_word(qlt_state_t *qlt, uint32_t,
uint32_t *);
static void qlt_mps_reset(qlt_state_t *qlt);
static void qlt_properties(qlt_state_t *qlt);
+ static fct_status_t qlt_mq_create(qlt_state_t *qlt, int idx);
+ static fct_status_t qlt_mq_destroy(qlt_state_t *qlt);
+ static fct_status_t qlt_27xx_get_dmp_template(qlt_state_t *);
+ static uint32_t qlt_27xx_dmp_parse_template(qlt_state_t *, qlt_dt_hdr_t *,
+ uint8_t *, uint32_t);
+ static int qlt_27xx_dump_ram(qlt_state_t *, uint16_t, uint32_t,
+ uint32_t, uint8_t *);
+
#define SETELSBIT(bmp, els) (bmp)[((els) >> 3) & 0x1F] = \
(uint8_t)((bmp)[((els) >> 3) & 0x1F] | ((uint8_t)1) << ((els) & 7))
! int qlt_enable_msix = 1;
int qlt_enable_msi = 1;
string_table_t prop_status_tbl[] = DDI_PROP_STATUS();
*** 204,217 ****
NULL,
ddi_power,
qlt_quiesce
};
! #ifndef PORT_SPEED_10G
! #define PORT_SPEED_10G 16
#endif
static struct modldrv modldrv = {
&mod_driverops,
QLT_NAME" "QLT_VERSION,
&qlt_ops,
};
--- 227,248 ----
NULL,
ddi_power,
qlt_quiesce
};
! #ifndef PORT_SPEED_16G
! #define PORT_SPEED_16G 32
#endif
+ #ifndef PORT_SPEED_32G
+ #define PORT_SPEED_32G 64
+ #endif
+
+ #ifndef QL_NAME
+ #define QL_NAME "qlt"
+ #endif
+
static struct modldrv modldrv = {
&mod_driverops,
QLT_NAME" "QLT_VERSION,
&qlt_ops,
};
*** 221,230 ****
--- 252,263 ----
};
void *qlt_state = NULL;
kmutex_t qlt_global_lock;
static uint32_t qlt_loaded_counter = 0;
+ uint8_t qlt_reprocess_attempt_cnt = 5;
+ uint32_t qlt_reprocess_delay = 75; /* default 75 microseconds */
static char *pci_speeds[] = { " 33", "-X Mode 1 66", "-X Mode 1 100",
"-X Mode 1 133", "--Invalid--",
"-X Mode 2 66", "-X Mode 2 100",
"-X Mode 2 133", " 66" };
*** 243,255 ****
1, /* s/g list length */
1, /* granularity of device */
0 /* DMA transfer flags */
};
/* qlogic logging */
int enable_extended_logging = 0;
-
static char qlt_provider_name[] = "qlt";
static struct stmf_port_provider *qlt_pp;
int
_init(void)
--- 276,321 ----
1, /* s/g list length */
1, /* granularity of device */
0 /* DMA transfer flags */
};
+
+ /* Always use 64 bit DMA. */
+ static ddi_dma_attr_t qlt_queue_dma_attr_mq_req1 = {
+ DMA_ATTR_V0, /* dma_attr_version */
+ 0, /* low DMA address range */
+ 0xffffffffffffffff, /* high DMA address range */
+ 0xffffffff, /* DMA counter register */
+ 64, /* DMA address alignment */
+ 0xff, /* DMA burstsizes */
+ 1, /* min effective DMA size */
+ 0xffffffff, /* max DMA xfer size */
+ 0xffffffff, /* segment boundary */
+ 1, /* s/g list length */
+ 1, /* granularity of device */
+ 0 /* DMA transfer flags */
+ };
+
+ /* Always use 64 bit DMA. */
+ static ddi_dma_attr_t qlt_queue_dma_attr_mq_rsp1 = {
+ DMA_ATTR_V0, /* dma_attr_version */
+ 0, /* low DMA address range */
+ 0xffffffffffffffff, /* high DMA address range */
+ 0xffffffff, /* DMA counter register */
+ 64, /* DMA address alignment */
+ 0xff, /* DMA burstsizes */
+ 1, /* min effective DMA size */
+ 0xffffffff, /* max DMA xfer size */
+ 0xffffffff, /* segment boundary */
+ 1, /* s/g list length */
+ 1, /* granularity of device */
+ 0 /* DMA transfer flags */
+ };
+
+
/* qlogic logging */
int enable_extended_logging = 0;
static char qlt_provider_name[] = "qlt";
static struct stmf_port_provider *qlt_pp;
int
_init(void)
*** 301,311 ****
_info(struct modinfo *modinfop)
{
return (mod_info(&modlinkage, modinfop));
}
-
static int
qlt_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
int instance;
qlt_state_t *qlt;
--- 367,376 ----
*** 322,376 ****
/* No support for suspend resume yet */
if (cmd != DDI_ATTACH)
return (DDI_FAILURE);
instance = ddi_get_instance(dip);
if (ddi_soft_state_zalloc(qlt_state, instance) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
if ((qlt = (qlt_state_t *)ddi_get_soft_state(qlt_state, instance)) ==
NULL) {
goto attach_fail_1;
}
qlt->instance = instance;
qlt->nvram = (qlt_nvram_t *)kmem_zalloc(sizeof (qlt_nvram_t), KM_SLEEP);
qlt->dip = dip;
if (qlt_el_trace_desc_ctor(qlt) != DDI_SUCCESS) {
cmn_err(CE_WARN, "qlt(%d): can't setup el tracing", instance);
! goto attach_fail_1;
}
EL(qlt, "instance=%d, ptr=%p\n", instance, (void *)qlt);
if (pci_config_setup(dip, &qlt->pcicfg_acc_handle) != DDI_SUCCESS) {
! goto attach_fail_2;
}
did = PCICFG_RD16(qlt, PCI_CONF_DEVID);
if ((did != 0x2422) && (did != 0x2432) &&
(did != 0x8432) && (did != 0x2532) &&
! (did != 0x8001)) {
cmn_err(CE_WARN, "qlt(%d): unknown devid(%x), failing attach",
instance, did);
goto attach_fail_4;
}
! if ((did & 0xFF00) == 0x8000)
qlt->qlt_81xx_chip = 1;
! else if ((did & 0xFF00) == 0x2500)
qlt->qlt_25xx_chip = 1;
dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
if (ddi_regs_map_setup(dip, 2, &qlt->regs, 0, 0x100,
&dev_acc_attr, &qlt->regs_acc_handle) != DDI_SUCCESS) {
goto attach_fail_4;
}
if (did == 0x2422) {
uint32_t pci_bits = REG_RD32(qlt, REG_CTRL_STATUS);
uint32_t slot = pci_bits & PCI_64_BIT_SLOT;
pci_bits >>= 8;
pci_bits &= 0xf;
--- 387,689 ----
/* No support for suspend resume yet */
if (cmd != DDI_ATTACH)
return (DDI_FAILURE);
instance = ddi_get_instance(dip);
+ cmn_err(CE_CONT, "!Qlogic %s(%d) FCA Driver v%s\n",
+ QLT_NAME, instance, QLT_VERSION);
+
if (ddi_soft_state_zalloc(qlt_state, instance) != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "qlt(%d): soft state alloc failed", instance);
return (DDI_FAILURE);
}
if ((qlt = (qlt_state_t *)ddi_get_soft_state(qlt_state, instance)) ==
NULL) {
+ cmn_err(CE_WARN, "qlt(%d): can't get soft state", instance);
goto attach_fail_1;
}
qlt->instance = instance;
qlt->nvram = (qlt_nvram_t *)kmem_zalloc(sizeof (qlt_nvram_t), KM_SLEEP);
+ qlt->vpd = (uint32_t *)kmem_zalloc(QL_24XX_VPD_SIZE, KM_SLEEP);
qlt->dip = dip;
if (qlt_el_trace_desc_ctor(qlt) != DDI_SUCCESS) {
cmn_err(CE_WARN, "qlt(%d): can't setup el tracing", instance);
! goto attach_fail_2;
}
EL(qlt, "instance=%d, ptr=%p\n", instance, (void *)qlt);
if (pci_config_setup(dip, &qlt->pcicfg_acc_handle) != DDI_SUCCESS) {
! cmn_err(CE_WARN, "qlt(%d): pci_config_setup failed", instance);
! goto attach_fail_3;
}
+
did = PCICFG_RD16(qlt, PCI_CONF_DEVID);
if ((did != 0x2422) && (did != 0x2432) &&
(did != 0x8432) && (did != 0x2532) &&
! (did != 0x8001) && (did != 0x2031) &&
! (did != 0x2071) && (did != 0x2261)) {
cmn_err(CE_WARN, "qlt(%d): unknown devid(%x), failing attach",
instance, did);
goto attach_fail_4;
}
! if ((did & 0xFFFF) == 0x2071) {
! qlt->qlt_27xx_chip = 1;
! qlt->qlt_fcoe_enabled = 0;
! } else if ((did & 0xFFFF) == 0x2261) {
! qlt->qlt_27xx_chip = 1;
! qlt->qlt_fcoe_enabled = 0;
! } else if ((did & 0xFFFF) == 0x2031) {
! qlt->qlt_83xx_chip = 1;
! qlt->qlt_fcoe_enabled = 0;
! } else if ((did & 0xFFF0) == 0x8000) {
qlt->qlt_81xx_chip = 1;
! qlt->qlt_fcoe_enabled = 1;
! } else if ((did & 0xFF00) == 0x2500)
qlt->qlt_25xx_chip = 1;
dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
+
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ int stat_1;
+ off_t regsize_1;
+
+ stat_1 = ddi_dev_regsize(dip, 1, ®size_1);
+ if (stat_1 != DDI_SUCCESS) {
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, reg 1 regsize failed,"
+ " stat %x", instance, stat_1);
+ goto attach_fail_4;
+ }
+
+ if (ddi_regs_map_setup(dip, 1, &qlt->regs, 0, regsize_1,
+ &dev_acc_attr, &qlt->regs_acc_handle) != DDI_SUCCESS) {
+ cmn_err(CE_NOTE, "qlt(%d) ddi_regs_map_setup failed\n",
+ instance);
+ goto attach_fail_4;
+ }
+ } else {
+ /*
+ * 24xx and 25xx: rnumber 0 is config space
+ * rnumber 1 is for IO space
+ * rnumber 2 is for MBAR0: ISP, MSIX, PBA
+ */
if (ddi_regs_map_setup(dip, 2, &qlt->regs, 0, 0x100,
&dev_acc_attr, &qlt->regs_acc_handle) != DDI_SUCCESS) {
goto attach_fail_4;
}
+ }
+
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+
+ uint32_t w32h;
+ uint32_t w32l;
+ int stat;
+ off_t regsize;
+
+ w32l = PCICFG_RD32(qlt, PCI_CONF_BASE2);
+ w32h = PCICFG_RD32(qlt, PCI_CONF_BASE3);
+
+ if ((w32h > 0) || w32l > 0) {
+ stat = ddi_dev_regsize(dip, 2, ®size);
+ if (stat != DDI_SUCCESS) {
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, MSI-X regsize failed,"
+ " stat %x", instance, stat);
+ }
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, MSI-X MEM Bar size %x",
+ instance, regsize);
+
+ stat = ddi_regs_map_setup(dip, 2, &qlt->msix_base, 0,
+ /* ((MQ_MAX_QUEUES * 2) +1) << 2, */
+ regsize,
+ &dev_acc_attr, &qlt->msix_acc_handle);
+
+ if (stat != DDI_SUCCESS || qlt->msix_base == NULL ||
+ qlt->msix_acc_handle == NULL) {
+
+ cmn_err(CE_WARN,
+ "qlt(%d): can't map MBar for MSI-X",
+ instance);
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, MSI-X MEM Bar map fail",
+ instance);
+
+ if (qlt->msix_acc_handle != NULL) {
+ ddi_regs_map_free(
+ &qlt->msix_acc_handle);
+ }
+ goto attach_fail_5;
+ }
+ } else {
+ cmn_err(CE_WARN, "qlt(%d): can't setup MBar for MSI-X",
+ instance);
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, No MSI-X MEM Bar", instance);
+ goto attach_fail_5;
+ }
+
+ w32l = PCICFG_RD32(qlt, PCI_CONF_BASE4);
+ w32h = PCICFG_RD32(qlt, PCI_CONF_BASE5);
+
+ if ((w32h > 0) || w32l > 0) {
+ stat = ddi_dev_regsize(dip, 3, ®size);
+ if (stat != DDI_SUCCESS) {
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, MQ regsize failed, stat %x",
+ instance, stat);
+ }
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, MQ MEM Bar size %x",
+ instance, regsize);
+
+ /* for 83xx the QP pointers are in the 3rd MBar */
+ stat = ddi_regs_map_setup(dip, 3, &qlt->mq_reg_base, 0,
+ (MQ_MAX_QUEUES * MQBAR_REG_OFFSET),
+ &dev_acc_attr, &qlt->mq_reg_acc_handle);
+
+ if (stat != DDI_SUCCESS || qlt->mq_reg_base == NULL ||
+ qlt->mq_reg_acc_handle == NULL) {
+
+ cmn_err(CE_WARN, "qlt(%d): can't map QP MBar",
+ instance);
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, QP MEM Bar map fail st:%x",
+ instance, stat);
+
+ if (qlt->msix_acc_handle != NULL) {
+ ddi_regs_map_free(
+ &qlt->msix_acc_handle);
+ }
+ if (qlt->mq_reg_acc_handle != NULL) {
+ ddi_regs_map_free(
+ &qlt->mq_reg_acc_handle);
+ }
+ goto attach_fail_5;
+ } else {
+ qlt->qlt_mq_enabled = 1;
+ }
+ } else {
+ cmn_err(CE_WARN, "qlt(%d): can't setup MBar for QPs",
+ instance);
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, No QPs MEM Bar", instance);
+
+ if (qlt->msix_acc_handle != NULL) {
+ ddi_regs_map_free(
+ &qlt->msix_acc_handle);
+ }
+ goto attach_fail_5;
+ }
+ } else if (qlt->qlt_81xx_chip) {
+
+ uint32_t w32;
+ int stat;
+
+ w32 = PCICFG_RD32(qlt, PCI_CONF_BASE3);
+ if (w32 == 0) {
+
+ cmn_err(CE_WARN, "qlt(%d): can't setup MBar2",
+ instance);
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, No MEM Bar2", instance);
+ goto attach_fail_5;
+ }
+
+ stat = ddi_regs_map_setup(dip, 3, &qlt->mq_reg_base, 0,
+ (MQ_MAX_QUEUES * MQBAR_REG_OFFSET),
+ &dev_acc_attr, &qlt->mq_reg_acc_handle);
+
+ if (stat != DDI_SUCCESS || qlt->mq_reg_base == NULL ||
+ qlt->mq_reg_acc_handle == NULL) {
+
+ cmn_err(CE_WARN, "qlt(%d): can't map MBar2",
+ instance);
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, MEM Bar2 map fail", instance);
+
+ if (qlt->mq_reg_acc_handle != NULL) {
+ ddi_regs_map_free(&qlt->mq_reg_acc_handle);
+ }
+ goto attach_fail_5;
+ } else {
+ qlt->qlt_mq_enabled = 1;
+ }
+ } else if (qlt->qlt_25xx_chip) {
+ uint32_t w32h;
+ uint32_t w32l;
+ int stat;
+ off_t regsize;
+
+ /* MBAR2 rnumber 3 */
+ w32l = PCICFG_RD32(qlt, PCI_CONF_BASE3);
+ w32h = PCICFG_RD32(qlt, PCI_CONF_BASE4);
+
+ if ((w32h > 0) || (w32l > 0)) {
+ stat = ddi_dev_regsize(dip, 3, ®size);
+ if (stat != DDI_SUCCESS) {
+ stmf_trace(qlt->qlt_port_alias,
+ "ISP25xx inst=%d, MQ regsize failed, stat %x",
+ instance, stat);
+ EL(qlt, "ISP25xx MQ regsize failed, stat %x\n",
+ stat);
+
+ }
+ stmf_trace(qlt->qlt_port_alias,
+ "ISP25xx instance=%d, MQ MEM Bar size %lx",
+ instance, regsize);
+ EL(qlt, "ISP25xx MQ MEM Bar (MBAR2) size: %x\n",
+ regsize);
+
+ stat = ddi_regs_map_setup(dip, 3, &qlt->mq_reg_base, 0,
+ (MQ_MAX_QUEUES * MQBAR_REG_OFFSET),
+ &dev_acc_attr, &qlt->mq_reg_acc_handle);
+ if (stat != DDI_SUCCESS || qlt->mq_reg_base == NULL ||
+ qlt->mq_reg_acc_handle == NULL) {
+ cmn_err(CE_WARN,
+ "qlt(%d): ISP25xx can't map QP MBar",
+ instance);
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, QP MEM Bar map fail st:%x",
+ instance, stat);
+ if (qlt->mq_reg_acc_handle != NULL) {
+ ddi_regs_map_free(
+ &qlt->mq_reg_acc_handle);
+ }
+ } else {
+ qlt->qlt_mq_enabled = 1;
+ }
+ } else {
+ stmf_trace(qlt->qlt_port_alias,
+ "instance=%d, No QPs MEM Bar", instance);
+ EL(qlt,
+ "ISP25xx can't setup MBar QPs, use baseq\n");
+ }
+ }
+
+ if (qlt->qlt_mq_enabled) {
+ qlt->mq_req = kmem_zalloc(
+ ((sizeof (qlt_mq_req_ptr_blk_t)) * MQ_MAX_QUEUES),
+ KM_SLEEP);
+ qlt->mq_resp = kmem_zalloc(
+ ((sizeof (qlt_mq_rsp_ptr_blk_t)) * MQ_MAX_QUEUES),
+ KM_SLEEP);
+ } else {
+ qlt->mq_req = kmem_zalloc(
+ (sizeof (qlt_mq_req_ptr_blk_t)), KM_SLEEP);
+ qlt->mq_resp = kmem_zalloc(
+ (sizeof (qlt_mq_rsp_ptr_blk_t)), KM_SLEEP);
+ }
+
if (did == 0x2422) {
uint32_t pci_bits = REG_RD32(qlt, REG_CTRL_STATUS);
uint32_t slot = pci_bits & PCI_64_BIT_SLOT;
pci_bits >>= 8;
pci_bits &= 0xf;
*** 390,399 ****
--- 703,722 ----
if ((ret = qlt_read_nvram(qlt)) != QLT_SUCCESS) {
cmn_err(CE_WARN, "qlt(%d): read nvram failure %llx", instance,
(unsigned long long)ret);
goto attach_fail_5;
}
+ if ((ret = qlt_read_vpd(qlt)) != QLT_SUCCESS) {
+ cmn_err(CE_WARN, "qlt(%d): read vpd failure %llx", instance,
+ (unsigned long long)ret);
+ goto attach_fail_5;
+ }
+ if ((ret = qlt_read_rom_image(qlt)) != QLT_SUCCESS) {
+ cmn_err(CE_WARN, "qlt(%d): read rom image failure %llx",
+ instance, (unsigned long long)ret);
+ goto attach_fail_5;
+ }
qlt_properties(qlt);
if (ddi_dma_alloc_handle(dip, &qlt_queue_dma_attr, DDI_DMA_SLEEP,
0, &qlt->queue_mem_dma_handle) != DDI_SUCCESS) {
*** 411,429 ****
&qlt->queue_mem_cookie, &ncookies) != DDI_SUCCESS) {
goto attach_fail_7;
}
if (ncookies != 1)
goto attach_fail_8;
! qlt->req_ptr = qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET;
! qlt->resp_ptr = qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET;
qlt->preq_ptr = qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET;
qlt->atio_ptr = qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET;
/* mutex are inited in this function */
if (qlt_setup_interrupts(qlt) != DDI_SUCCESS)
goto attach_fail_8;
(void) snprintf(qlt->qlt_minor_name, sizeof (qlt->qlt_minor_name),
"qlt%d", instance);
(void) snprintf(qlt->qlt_port_alias, sizeof (qlt->qlt_port_alias),
"%s,0", qlt->qlt_minor_name);
--- 734,778 ----
&qlt->queue_mem_cookie, &ncookies) != DDI_SUCCESS) {
goto attach_fail_7;
}
if (ncookies != 1)
goto attach_fail_8;
!
! /*
! * Base queue (0), alwasy available
! */
! qlt->mq_req[0].queue_mem_mq_base_addr =
! qlt->mq_req[0].mq_ptr =
! qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET;
! qlt->mq_resp[0].queue_mem_mq_base_addr =
! qlt->mq_resp[0].mq_ptr =
! qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET;
!
qlt->preq_ptr = qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET;
qlt->atio_ptr = qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET;
/* mutex are inited in this function */
if (qlt_setup_interrupts(qlt) != DDI_SUCCESS)
goto attach_fail_8;
+ qlt->qlt_queue_cnt = 1;
+ if ((qlt->qlt_mq_enabled) && (qlt->intr_cnt > 1)) {
+ int i;
+
+ for (i = 1; i < qlt->intr_cnt; i++) {
+ if (qlt_mq_create(qlt, i) != QLT_SUCCESS) {
+ cmn_err(CE_WARN, "qlt(%d) mq create (%d) "
+ "failed\n", qlt->instance, i);
+ break;
+ }
+ qlt->qlt_queue_cnt++;
+ if (qlt->qlt_queue_cnt >= MQ_MAX_QUEUES)
+ break;
+ }
+ }
+ EL(qlt, "Queue count = %d\n", qlt->qlt_queue_cnt);
+
(void) snprintf(qlt->qlt_minor_name, sizeof (qlt->qlt_minor_name),
"qlt%d", instance);
(void) snprintf(qlt->qlt_port_alias, sizeof (qlt->qlt_port_alias),
"%s,0", qlt->qlt_minor_name);
*** 458,468 ****
mr = (uint16_t)PCICFG_RD16(qlt, 0x4E);
mr = (uint16_t)(mr & 0xfff3);
mr = (uint16_t)(mr | (val << 2));
PCICFG_WR16(qlt, 0x4E, mr);
} else if ((did == 0x2432) || (did == 0x8432) ||
! (did == 0x2532) || (did == 0x8001)) {
if (max_read_size == 128)
val = 0;
else if (max_read_size == 256)
val = 1;
else if (max_read_size == 512)
--- 807,819 ----
mr = (uint16_t)PCICFG_RD16(qlt, 0x4E);
mr = (uint16_t)(mr & 0xfff3);
mr = (uint16_t)(mr | (val << 2));
PCICFG_WR16(qlt, 0x4E, mr);
} else if ((did == 0x2432) || (did == 0x8432) ||
! (did == 0x2532) || (did == 0x8001) ||
! (did == 0x2031) || (did == 0x2071) ||
! (did == 0x2261)) {
if (max_read_size == 128)
val = 0;
else if (max_read_size == 256)
val = 1;
else if (max_read_size == 512)
*** 493,503 ****
max_payload_size = qlt_read_int_prop(qlt, "pcie-max-payload-size", 11);
if (max_payload_size == 11)
goto over_max_payload_setting;
if ((did == 0x2432) || (did == 0x8432) ||
! (did == 0x2532) || (did == 0x8001)) {
if (max_payload_size == 128)
val = 0;
else if (max_payload_size == 256)
val = 1;
else if (max_payload_size == 512)
--- 844,856 ----
max_payload_size = qlt_read_int_prop(qlt, "pcie-max-payload-size", 11);
if (max_payload_size == 11)
goto over_max_payload_setting;
if ((did == 0x2432) || (did == 0x8432) ||
! (did == 0x2532) || (did == 0x8001) ||
! (did == 0x2031) || (did == 0x2071) ||
! (did == 0x2261)) {
if (max_payload_size == 128)
val = 0;
else if (max_payload_size == 256)
val = 1;
else if (max_payload_size == 512)
*** 523,534 ****
over_max_payload_setting:;
qlt_enable_intr(qlt);
! if (qlt_port_start((caddr_t)qlt) != QLT_SUCCESS)
goto attach_fail_10;
ddi_report_dev(dip);
return (DDI_SUCCESS);
attach_fail_10:;
--- 876,890 ----
over_max_payload_setting:;
qlt_enable_intr(qlt);
! if (qlt_port_start((caddr_t)qlt) != QLT_SUCCESS) {
! EL(qlt, "qlt_port_start failed, tear down\n");
! qlt_disable_intr(qlt);
goto attach_fail_10;
+ }
ddi_report_dev(dip);
return (DDI_SUCCESS);
attach_fail_10:;
*** 537,559 ****
cv_destroy(&qlt->rp_dereg_cv);
ddi_remove_minor_node(dip, qlt->qlt_minor_name);
attach_fail_9:;
qlt_destroy_mutex(qlt);
qlt_release_intr(qlt);
attach_fail_8:;
(void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle);
attach_fail_7:;
ddi_dma_mem_free(&qlt->queue_mem_acc_handle);
attach_fail_6:;
ddi_dma_free_handle(&qlt->queue_mem_dma_handle);
attach_fail_5:;
ddi_regs_map_free(&qlt->regs_acc_handle);
attach_fail_4:;
pci_config_teardown(&qlt->pcicfg_acc_handle);
! kmem_free(qlt->nvram, sizeof (qlt_nvram_t));
(void) qlt_el_trace_desc_dtor(qlt);
attach_fail_2:;
attach_fail_1:;
ddi_soft_state_free(qlt_state, instance);
return (DDI_FAILURE);
}
--- 893,934 ----
cv_destroy(&qlt->rp_dereg_cv);
ddi_remove_minor_node(dip, qlt->qlt_minor_name);
attach_fail_9:;
qlt_destroy_mutex(qlt);
qlt_release_intr(qlt);
+ (void) qlt_mq_destroy(qlt);
+
attach_fail_8:;
(void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle);
attach_fail_7:;
ddi_dma_mem_free(&qlt->queue_mem_acc_handle);
attach_fail_6:;
ddi_dma_free_handle(&qlt->queue_mem_dma_handle);
attach_fail_5:;
+ if (qlt->mq_resp) {
+ kmem_free(qlt->mq_resp,
+ (qlt->qlt_mq_enabled ?
+ (sizeof (qlt_mq_rsp_ptr_blk_t) * MQ_MAX_QUEUES) :
+ (sizeof (qlt_mq_rsp_ptr_blk_t))));
+ }
+ qlt->mq_resp = NULL;
+ if (qlt->mq_req) {
+ kmem_free(qlt->mq_req,
+ (qlt->qlt_mq_enabled ?
+ (sizeof (qlt_mq_req_ptr_blk_t) * MQ_MAX_QUEUES) :
+ (sizeof (qlt_mq_req_ptr_blk_t))));
+ }
+ qlt->mq_req = NULL;
+
ddi_regs_map_free(&qlt->regs_acc_handle);
attach_fail_4:;
pci_config_teardown(&qlt->pcicfg_acc_handle);
! attach_fail_3:;
(void) qlt_el_trace_desc_dtor(qlt);
attach_fail_2:;
+ kmem_free(qlt->vpd, QL_24XX_VPD_SIZE);
+ kmem_free(qlt->nvram, sizeof (qlt_nvram_t));
attach_fail_1:;
ddi_soft_state_free(qlt_state, instance);
return (DDI_FAILURE);
}
*** 585,601 ****
--- 960,1022 ----
return (DDI_FAILURE);
}
qlt_disable_intr(qlt);
+ if (qlt->dmp_template_addr != NULL) {
+ (void) ddi_dma_unbind_handle(qlt->dmp_template_dma_handle);
+ ddi_dma_mem_free(&qlt->dmp_template_acc_handle);
+ ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
+ }
+
+ if (qlt->fw_bin_dump_buf != NULL) {
+ kmem_free(qlt->fw_bin_dump_buf, qlt->fw_bin_dump_size);
+ qlt->fw_bin_dump_buf = NULL;
+ qlt->fw_bin_dump_size = 0;
+ qlt->fw_ascii_dump_size = 0;
+ }
+
+ if (qlt->qlt_fwdump_buf) {
+ kmem_free(qlt->qlt_fwdump_buf, qlt->fw_dump_size);
+ qlt->qlt_fwdump_buf = NULL;
+ }
+
ddi_remove_minor_node(dip, qlt->qlt_minor_name);
qlt_destroy_mutex(qlt);
qlt_release_intr(qlt);
+ if (qlt->qlt_mq_enabled == 1) {
+ (void) qlt_mq_destroy(qlt);
+ }
+
(void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle);
ddi_dma_mem_free(&qlt->queue_mem_acc_handle);
ddi_dma_free_handle(&qlt->queue_mem_dma_handle);
ddi_regs_map_free(&qlt->regs_acc_handle);
+
+ if (qlt->mq_resp) {
+ kmem_free(qlt->mq_resp,
+ (qlt->qlt_mq_enabled ?
+ (sizeof (qlt_mq_rsp_ptr_blk_t) * MQ_MAX_QUEUES) :
+ (sizeof (qlt_mq_rsp_ptr_blk_t))));
+ }
+ qlt->mq_resp = NULL;
+ if (qlt->mq_req) {
+ kmem_free(qlt->mq_req,
+ (qlt->qlt_mq_enabled ?
+ (sizeof (qlt_mq_req_ptr_blk_t) * MQ_MAX_QUEUES) :
+ (sizeof (qlt_mq_req_ptr_blk_t))));
+ }
+ qlt->mq_req = NULL;
+
+ if (qlt->qlt_mq_enabled == 1) {
+ if ((qlt->msix_acc_handle != NULL) &&
+ ((qlt->qlt_83xx_chip == 1) ||
+ (qlt->qlt_27xx_chip == 1))) {
+ ddi_regs_map_free(&qlt->msix_acc_handle);
+ }
+ ddi_regs_map_free(&qlt->mq_reg_acc_handle);
+ }
pci_config_teardown(&qlt->pcicfg_acc_handle);
kmem_free(qlt->nvram, sizeof (qlt_nvram_t));
cv_destroy(&qlt->mbox_cv);
cv_destroy(&qlt->rp_dereg_cv);
(void) qlt_el_trace_desc_dtor(qlt);
*** 620,669 ****
return (DDI_SUCCESS);
}
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_HOST_TO_RISC_INTR));
REG_WR16(qlt, REG_MBOX0, MBC_STOP_FIRMWARE);
REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
for (timer = 0; timer < 30000; timer++) {
stat = REG_RD32(qlt, REG_RISC_STATUS);
if (stat & RISC_HOST_INTR_REQUEST) {
if ((stat & FW_INTR_STATUS_MASK) < 0x12) {
REG_WR32(qlt, REG_HCCR,
! HCCR_CMD(CLEAR_RISC_PAUSE));
break;
}
REG_WR32(qlt, REG_HCCR,
! HCCR_CMD(CLEAR_HOST_TO_RISC_INTR));
}
drv_usecwait(100);
}
/* Reset the chip. */
REG_WR32(qlt, REG_CTRL_STATUS, CHIP_SOFT_RESET | DMA_SHUTDOWN_CTRL |
PCI_X_XFER_CTRL);
drv_usecwait(100);
qlt_disable_intr(qlt);
return (DDI_SUCCESS);
}
static void
qlt_enable_intr(qlt_state_t *qlt)
{
if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) {
! (void) ddi_intr_block_enable(qlt->htable, qlt->intr_cnt);
} else {
int i;
! for (i = 0; i < qlt->intr_cnt; i++)
! (void) ddi_intr_enable(qlt->htable[i]);
}
! qlt->qlt_intr_enabled = 1;
}
static void
qlt_disable_intr(qlt_state_t *qlt)
{
if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) {
(void) ddi_intr_block_disable(qlt->htable, qlt->intr_cnt);
} else {
int i;
for (i = 0; i < qlt->intr_cnt; i++)
--- 1041,1199 ----
return (DDI_SUCCESS);
}
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_HOST_TO_RISC_INTR));
REG_WR16(qlt, REG_MBOX0, MBC_STOP_FIRMWARE);
+ REG_WR16(qlt, REG_MBOX(1), 0);
+ REG_WR16(qlt, REG_MBOX(2), 0);
+ REG_WR16(qlt, REG_MBOX(3), 0);
+ REG_WR16(qlt, REG_MBOX(4), 0);
+ REG_WR16(qlt, REG_MBOX(5), 0);
+ REG_WR16(qlt, REG_MBOX(6), 0);
+ REG_WR16(qlt, REG_MBOX(7), 0);
+ REG_WR16(qlt, REG_MBOX(8), 0);
REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
for (timer = 0; timer < 30000; timer++) {
stat = REG_RD32(qlt, REG_RISC_STATUS);
if (stat & RISC_HOST_INTR_REQUEST) {
if ((stat & FW_INTR_STATUS_MASK) < 0x12) {
REG_WR32(qlt, REG_HCCR,
! HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
break;
}
REG_WR32(qlt, REG_HCCR,
! HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
}
drv_usecwait(100);
}
+
+
+ /* need to ensure no one accesses the hw during the reset 100us */
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ REG_WR32(qlt, REG_INTR_CTRL, 0);
+ mutex_enter(&qlt->mbox_lock);
+ if (qlt->qlt_mq_enabled == 1) {
+ int i;
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ mutex_enter(&qlt->mq_req[i].mq_lock);
+ }
+ }
+ mutex_enter(&qlt->mq_req[0].mq_lock);
+ drv_usecwait(40);
+ }
+
/* Reset the chip. */
REG_WR32(qlt, REG_CTRL_STATUS, CHIP_SOFT_RESET | DMA_SHUTDOWN_CTRL |
PCI_X_XFER_CTRL);
drv_usecwait(100);
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ mutex_exit(&qlt->mq_req[0].mq_lock);
+ if (qlt->qlt_mq_enabled == 1) {
+ int i;
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ mutex_exit(&qlt->mq_req[i].mq_lock);
+ }
+ }
+ mutex_exit(&qlt->mbox_lock);
+ }
+
qlt_disable_intr(qlt);
return (DDI_SUCCESS);
}
static void
qlt_enable_intr(qlt_state_t *qlt)
{
if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) {
! int stat;
!
! stat = ddi_intr_block_enable(qlt->htable, qlt->intr_cnt);
! if (stat != DDI_SUCCESS) {
! stmf_trace(qlt->qlt_port_alias,
! "qlt_enable_intr: ddi_intr_block_enable failed:%x",
! stat);
!
! cmn_err(CE_WARN, "!qlt(%d): qlt_enable_intr: "
! "ddi_intr_block_enable failed:%x",
! qlt->instance, stat);
! }
!
! #ifndef __sparc
! else {
! /* Please see CR6840537, MSI isn't re-enabled x86 */
! off_t offset;
! uint8_t val8;
! ddi_intr_handle_impl_t *hdlp;
!
! if (qlt->qlt_81xx_chip || qlt->qlt_25xx_chip) {
! offset = (off_t)0x8a;
} else {
+ offset = (off_t)0x66;
+ }
+
+ hdlp = (ddi_intr_handle_impl_t *)qlt->htable[0];
+ if ((hdlp->ih_state == DDI_IHDL_STATE_ENABLE) &&
+ (hdlp->ih_type == DDI_INTR_TYPE_MSI)) {
+
+ /* get MSI control */
+ val8 = pci_config_get8(qlt->pcicfg_acc_handle,
+ offset);
+
+ if ((val8 & 1) == 0) {
+ stmf_trace(qlt->qlt_port_alias,
+ "qlt(%d): qlt_enable_intr: "
+ "MSI enable failed (%x)",
+ qlt->instance, val8);
+
+ /* write enable to MSI control */
+ val8 = (uint8_t)(val8 | 1);
+ pci_config_put8(qlt->pcicfg_acc_handle,
+ offset, val8);
+
+ /* read back to veriy */
+ val8 = pci_config_get8
+ (qlt->pcicfg_acc_handle, offset);
+
+ if (val8 & 1) {
+ stmf_trace(qlt->qlt_port_alias,
+ "qlt(%d): qlt_enable_intr: "
+ "MSI enabled kludge!(%x)",
+ qlt->instance, val8);
+ }
+ }
+ }
+ }
+ #endif /* x86 specific hack */
+ } else {
int i;
! int stat = DDI_SUCCESS;
!
! for (i = 0;
! ((i < qlt->intr_cnt) && (stat == DDI_SUCCESS)); i++) {
! stat = ddi_intr_enable(qlt->htable[i]);
}
! if (stat != DDI_SUCCESS) {
! stmf_trace(qlt->qlt_port_alias,
! "qlt_enable_intr: ddi_intr_enable failed:%x",
! stat);
!
! cmn_err(CE_WARN, "!qlt(%d): qlt_enable_intr: "
! "ddi_intr_enable failed:%x", qlt->instance, stat);
! }
! }
}
static void
qlt_disable_intr(qlt_state_t *qlt)
{
+ if (qlt->qlt_intr_enabled == 0) {
+ /* ---- If we've disabled it once, just return ---- */
+ return;
+ }
+
if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) {
(void) ddi_intr_block_disable(qlt->htable, qlt->intr_cnt);
} else {
int i;
for (i = 0; i < qlt->intr_cnt; i++)
*** 688,703 ****
qlt->intr_cnt = 0;
qlt->intr_size = 0;
qlt->intr_cap = 0;
}
-
static void
qlt_init_mutex(qlt_state_t *qlt)
{
! mutex_init(&qlt->req_lock, 0, MUTEX_DRIVER,
INT2PTR(qlt->intr_pri, void *));
mutex_init(&qlt->preq_lock, 0, MUTEX_DRIVER,
INT2PTR(qlt->intr_pri, void *));
mutex_init(&qlt->mbox_lock, NULL, MUTEX_DRIVER,
INT2PTR(qlt->intr_pri, void *));
mutex_init(&qlt->intr_lock, NULL, MUTEX_DRIVER,
--- 1218,1242 ----
qlt->intr_cnt = 0;
qlt->intr_size = 0;
qlt->intr_cap = 0;
}
static void
qlt_init_mutex(qlt_state_t *qlt)
{
! if (qlt->qlt_mq_enabled == 1) {
! int i;
!
! for (i = 1; i < MQ_MAX_QUEUES; i++) {
! mutex_init(&qlt->mq_req[i].mq_lock, 0, MUTEX_DRIVER,
INT2PTR(qlt->intr_pri, void *));
+ mutex_init(&qlt->mq_resp[i].mq_lock, 0, MUTEX_DRIVER,
+ INT2PTR(qlt->intr_pri, void *));
+ }
+ }
+ mutex_init(&qlt->mq_req[0].mq_lock, 0, MUTEX_DRIVER,
+ INT2PTR(qlt->intr_pri, void *));
mutex_init(&qlt->preq_lock, 0, MUTEX_DRIVER,
INT2PTR(qlt->intr_pri, void *));
mutex_init(&qlt->mbox_lock, NULL, MUTEX_DRIVER,
INT2PTR(qlt->intr_pri, void *));
mutex_init(&qlt->intr_lock, NULL, MUTEX_DRIVER,
*** 705,729 ****
}
static void
qlt_destroy_mutex(qlt_state_t *qlt)
{
! mutex_destroy(&qlt->req_lock);
mutex_destroy(&qlt->preq_lock);
mutex_destroy(&qlt->mbox_lock);
mutex_destroy(&qlt->intr_lock);
}
-
static int
qlt_setup_msix(qlt_state_t *qlt)
{
int count, avail, actual;
int ret;
int itype = DDI_INTR_TYPE_MSIX;
int i;
ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
if (ret != DDI_SUCCESS || count == 0) {
EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
count);
return (DDI_FAILURE);
--- 1244,1293 ----
}
static void
qlt_destroy_mutex(qlt_state_t *qlt)
{
! if (qlt->qlt_mq_enabled == 1) {
! int i;
!
! for (i = 1; i < MQ_MAX_QUEUES; i++) {
! mutex_destroy(&qlt->mq_req[i].mq_lock);
! mutex_destroy(&qlt->mq_resp[i].mq_lock);
! }
! }
! mutex_destroy(&qlt->mq_req[0].mq_lock);
mutex_destroy(&qlt->preq_lock);
mutex_destroy(&qlt->mbox_lock);
mutex_destroy(&qlt->intr_lock);
}
static int
qlt_setup_msix(qlt_state_t *qlt)
{
int count, avail, actual;
int ret;
int itype = DDI_INTR_TYPE_MSIX;
int i;
+ #ifdef __x86
+ if (get_hwenv() == HW_VMWARE) {
+ EL(qlt, "running under hypervisor, disabling MSI-X\n");
+ return (DDI_FAILURE);
+ }
+ #endif
+
+ /* check 24xx revision */
+ if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip) &&
+ (!qlt->qlt_83xx_chip) && (!qlt->qlt_27xx_chip)) {
+ uint8_t rev_id;
+ rev_id = (uint8_t)
+ pci_config_get8(qlt->pcicfg_acc_handle, PCI_CONF_REVID);
+ if (rev_id < 3) {
+ return (DDI_FAILURE);
+ }
+ }
+
ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
if (ret != DDI_SUCCESS || count == 0) {
EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
count);
return (DDI_FAILURE);
*** 737,756 ****
if (avail < count) {
stmf_trace(qlt->qlt_port_alias,
"qlt_setup_msix: nintrs=%d,avail=%d", count, avail);
}
qlt->intr_size = (int)(count * (int)sizeof (ddi_intr_handle_t));
qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP);
ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype,
DDI_INTR_ALLOC_NORMAL, count, &actual, 0);
/* we need at least 2 interrupt vectors */
! if (ret != DDI_SUCCESS || actual < 2) {
EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
actual);
ret = DDI_FAILURE;
goto release_intr;
}
if (actual < count) {
EL(qlt, "requested: %d, received: %d\n", count, actual);
}
--- 1301,1339 ----
if (avail < count) {
stmf_trace(qlt->qlt_port_alias,
"qlt_setup_msix: nintrs=%d,avail=%d", count, avail);
}
+ if ((qlt->qlt_25xx_chip) && (qlt->qlt_mq_enabled == 0)) {
+ count = 2;
+ }
+
qlt->intr_size = (int)(count * (int)sizeof (ddi_intr_handle_t));
qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP);
ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype,
DDI_INTR_ALLOC_NORMAL, count, &actual, 0);
+
+ EL(qlt, "qlt_setup_msix: count=%d,avail=%d,actual=%d\n", count,
+ avail, actual);
+
/* we need at least 2 interrupt vectors */
! if (((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) &&
! (ret != DDI_SUCCESS || actual < 2)) {
EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
actual);
ret = DDI_FAILURE;
goto release_intr;
+ } else if ((qlt->qlt_81xx_chip) && (ret != DDI_SUCCESS || actual < 3)) {
+ EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
+ actual);
+ ret = DDI_FAILURE;
+ goto release_intr;
+ } else if (ret != DDI_SUCCESS || actual < 2) {
+ EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
+ actual);
+ ret = DDI_FAILURE;
+ goto release_intr;
}
if (actual < count) {
EL(qlt, "requested: %d, received: %d\n", count, actual);
}
*** 760,771 ****
EL(qlt, "ddi_intr_get_pri status=%xh\n", ret);
ret = DDI_FAILURE;
goto release_intr;
}
qlt_init_mutex(qlt);
! for (i = 0; i < actual; i++) {
! ret = ddi_intr_add_handler(qlt->htable[i], qlt_isr,
qlt, INT2PTR((uint_t)i, void *));
if (ret != DDI_SUCCESS) {
EL(qlt, "ddi_intr_add_handler status=%xh\n", ret);
goto release_mutex;
}
--- 1343,1356 ----
EL(qlt, "ddi_intr_get_pri status=%xh\n", ret);
ret = DDI_FAILURE;
goto release_intr;
}
qlt_init_mutex(qlt);
! for (i = 0; i < qlt->intr_cnt; i++) {
! ret = ddi_intr_add_handler(qlt->htable[i],
! (i != 0) ? qlt_msix_resp_handler :
! qlt_msix_default_handler,
qlt, INT2PTR((uint_t)i, void *));
if (ret != DDI_SUCCESS) {
EL(qlt, "ddi_intr_add_handler status=%xh\n", ret);
goto release_mutex;
}
*** 778,805 ****
release_mutex:
qlt_destroy_mutex(qlt);
release_intr:
for (i = 0; i < actual; i++)
(void) ddi_intr_free(qlt->htable[i]);
! #if 0
! free_mem:
! #endif
kmem_free(qlt->htable, (uint_t)qlt->intr_size);
qlt->htable = NULL;
qlt_release_intr(qlt);
return (ret);
}
-
static int
qlt_setup_msi(qlt_state_t *qlt)
{
int count, avail, actual;
int itype = DDI_INTR_TYPE_MSI;
int ret;
int i;
/* get the # of interrupts */
ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
if (ret != DDI_SUCCESS || count == 0) {
EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
count);
--- 1363,1392 ----
release_mutex:
qlt_destroy_mutex(qlt);
release_intr:
for (i = 0; i < actual; i++)
(void) ddi_intr_free(qlt->htable[i]);
!
kmem_free(qlt->htable, (uint_t)qlt->intr_size);
qlt->htable = NULL;
qlt_release_intr(qlt);
return (ret);
}
static int
qlt_setup_msi(qlt_state_t *qlt)
{
int count, avail, actual;
int itype = DDI_INTR_TYPE_MSI;
int ret;
int i;
+ /* 83xx and 27xx doesn't do MSI - don't even bother? */
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ return (DDI_FAILURE);
+ }
+
/* get the # of interrupts */
ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
if (ret != DDI_SUCCESS || count == 0) {
EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
count);
*** 932,1020 ****
/*
* x86 has a bug in the ddi_intr_block_enable/disable area (6562198).
*/
#ifndef __sparc
! if (qlt_enable_msi != 0) {
#endif
if (ddi_intr_get_supported_types(qlt->dip, &itypes) != DDI_SUCCESS) {
itypes = DDI_INTR_TYPE_FIXED;
}
-
if (qlt_enable_msix && (itypes & DDI_INTR_TYPE_MSIX)) {
if (qlt_setup_msix(qlt) == DDI_SUCCESS)
return (DDI_SUCCESS);
}
!
! if (itypes & DDI_INTR_TYPE_MSI) {
if (qlt_setup_msi(qlt) == DDI_SUCCESS)
return (DDI_SUCCESS);
}
#ifndef __sparc
}
#endif
return (qlt_setup_fixed(qlt));
}
/*
* Filling the hba attributes
*/
void
qlt_populate_hba_fru_details(struct fct_local_port *port,
struct fct_port_attrs *port_attrs)
{
- caddr_t bufp;
int len;
qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
(void) snprintf(port_attrs->manufacturer, FCHBA_MANUFACTURER_LEN,
"QLogic Corp.");
(void) snprintf(port_attrs->driver_name, FCHBA_DRIVER_NAME_LEN,
"%s", QLT_NAME);
(void) snprintf(port_attrs->driver_version, FCHBA_DRIVER_VERSION_LEN,
"%s", QLT_VERSION);
port_attrs->serial_number[0] = '\0';
port_attrs->hardware_version[0] = '\0';
(void) snprintf(port_attrs->firmware_version,
FCHBA_FIRMWARE_VERSION_LEN, "%d.%d.%d", qlt->fw_major,
qlt->fw_minor, qlt->fw_subminor);
/* Get FCode version */
! if (ddi_getlongprop(DDI_DEV_T_ANY, qlt->dip, PROP_LEN_AND_VAL_ALLOC |
! DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&bufp,
! (int *)&len) == DDI_PROP_SUCCESS) {
! (void) snprintf(port_attrs->option_rom_version,
! FCHBA_OPTION_ROM_VERSION_LEN, "%s", bufp);
! kmem_free(bufp, (uint_t)len);
! bufp = NULL;
! } else {
! #ifdef __sparc
! (void) snprintf(port_attrs->option_rom_version,
! FCHBA_OPTION_ROM_VERSION_LEN, "No Fcode found");
! #else
! (void) snprintf(port_attrs->option_rom_version,
! FCHBA_OPTION_ROM_VERSION_LEN, "N/A");
! #endif
! }
port_attrs->vendor_specific_id = qlt->nvram->subsystem_vendor_id[0] |
qlt->nvram->subsystem_vendor_id[1] << 8;
port_attrs->max_frame_size = qlt->nvram->max_frame_length[1] << 8 |
qlt->nvram->max_frame_length[0];
port_attrs->supported_cos = 0x10000000;
! port_attrs->supported_speed = PORT_SPEED_1G |
! PORT_SPEED_2G | PORT_SPEED_4G;
! if (qlt->qlt_25xx_chip)
port_attrs->supported_speed = PORT_SPEED_2G | PORT_SPEED_4G |
PORT_SPEED_8G;
! if (qlt->qlt_81xx_chip)
! port_attrs->supported_speed = PORT_SPEED_10G;
/* limit string length to nvr model_name length */
! len = (qlt->qlt_81xx_chip) ? 16 : 8;
(void) snprintf(port_attrs->model,
(uint_t)(len < FCHBA_MODEL_LEN ? len : FCHBA_MODEL_LEN),
"%s", qlt->nvram->model_name);
(void) snprintf(port_attrs->model_description,
--- 1519,1828 ----
/*
* x86 has a bug in the ddi_intr_block_enable/disable area (6562198).
*/
#ifndef __sparc
! if ((qlt_enable_msi != 0) || (qlt_enable_msix != 0)) {
#endif
if (ddi_intr_get_supported_types(qlt->dip, &itypes) != DDI_SUCCESS) {
itypes = DDI_INTR_TYPE_FIXED;
}
if (qlt_enable_msix && (itypes & DDI_INTR_TYPE_MSIX)) {
if (qlt_setup_msix(qlt) == DDI_SUCCESS)
return (DDI_SUCCESS);
}
! if (qlt_enable_msi && (itypes & DDI_INTR_TYPE_MSI)) {
if (qlt_setup_msi(qlt) == DDI_SUCCESS)
return (DDI_SUCCESS);
}
#ifndef __sparc
}
#endif
return (qlt_setup_fixed(qlt));
}
+ static uint8_t *
+ qlt_vpd_findtag(qlt_state_t *qlt, uint8_t *vpdbuf, int8_t *opcode)
+ {
+ uint8_t *vpd = vpdbuf;
+ uint8_t *end = vpdbuf + QL_24XX_VPD_SIZE;
+ uint32_t found = 0;
+
+ if (vpdbuf == NULL || opcode == NULL) {
+ EL(qlt, "null parameter passed!\n");
+ return (NULL);
+ }
+
+ while (vpd < end) {
+ if (vpd[0] == VPD_TAG_END) {
+ if (opcode[0] == VPD_TAG_END) {
+ found = 1;
+ } else {
+ found = 0;
+ }
+ break;
+ }
+
+ if (bcmp(opcode, vpd, strlen(opcode)) == 0) {
+ found = 1;
+ break;
+ }
+
+ if (!(strncmp((char *)vpd, (char *)VPD_TAG_PRODID, 1))) {
+ vpd += (vpd[2] << 8) + vpd[1] + 3;
+ } else if (*vpd == VPD_TAG_LRT || *vpd == VPD_TAG_LRTC) {
+ vpd += 3;
+ } else {
+ vpd += vpd[2] +3;
+ }
+ }
+ return (found == 1 ? vpd : NULL);
+ }
+
/*
+ * qlt_vpd_lookup
+ * Return the VPD data for the request VPD tag
+ *
+ * Input:
+ * qlt = adapter state pointer.
+ * opcode = VPD opcode to find (must be NULL terminated).
+ * bp = Pointer to returned data buffer.
+ * bplen = Length of returned data buffer.
+ *
+ * Returns:
+ * Length of data copied into returned data buffer.
+ * >0 = VPD data field (NULL terminated)
+ * 0 = no data.
+ * -1 = Could not find opcode in vpd buffer / error.
+ *
+ * Context:
+ * Kernel context.
+ *
+ * NB: The opcode buffer and the bp buffer *could* be the same buffer!
+ *
+ */
+ static int
+ qlt_vpd_lookup(qlt_state_t *qlt, uint8_t *opcode, uint8_t *bp,
+ int32_t bplen)
+ {
+ uint8_t *vpd = NULL;
+ uint8_t *vpdbuf = NULL;
+ int32_t len = -1;
+
+ if (opcode == NULL || bp == NULL || bplen < 1) {
+ EL(qlt, "invalid parameter passed: opcode=%ph, "
+ "bp=%ph, bplen=%xh\n", opcode, bp, bplen);
+ return (len);
+ }
+
+ vpdbuf = (uint8_t *)qlt->vpd;
+ if ((vpd = qlt_vpd_findtag(qlt, vpdbuf, (int8_t *)opcode)) != NULL) {
+ /*
+ * Found the tag
+ */
+ if (*opcode == VPD_TAG_END || *opcode == VPD_TAG_LRT ||
+ *opcode == VPD_TAG_LRTC) {
+ /*
+ * We found it, but the tag doesn't have a data
+ * field.
+ */
+ len = 0;
+ } else if (!(strncmp((char *)vpd, (char *)
+ VPD_TAG_PRODID, 1))) {
+ len = vpd[2] << 8;
+ len += vpd[1];
+ } else {
+ len = vpd[2];
+ }
+
+ /*
+ * Make sure that the vpd len does not exceed the
+ * vpd end
+ */
+ if (vpd+len > vpdbuf + QL_24XX_VPD_SIZE) {
+ EL(qlt, "vpd tag len (%xh) exceeds vpd buffer "
+ "length\n", len);
+ len = -1;
+ }
+ } else {
+ EL(qlt, "Cna't find vpd tag \n");
+ return (-1);
+ }
+
+ if (len >= 0) {
+ /*
+ * make sure we don't exceed callers buffer space len
+ */
+ if (len > bplen) {
+ len = bplen - 1;
+ }
+ /* copy the data back */
+ (void) strncpy((int8_t *)bp, (int8_t *)(vpd+3), (int64_t)len);
+ bp[len] = NULL;
+ } else {
+ /* error -- couldn't find tag */
+ bp[0] = NULL;
+ if (opcode[1] != NULL) {
+ EL(qlt, "unable to find tag '%s'\n", opcode);
+ } else {
+ EL(qlt, "unable to find tag '%xh'\n", opcode[0]);
+ }
+ }
+ return (len);
+ }
+
+ void
+ qlt_get_rom_version(qlt_state_t *qlt, caddr_t orv)
+ {
+ int i;
+ char bios0_str[32];
+ char fcode_str[32];
+ char efi_str[32];
+ char hppa_str[32];
+ char tmp[80];
+ uint32_t bios_cnt = 0;
+ uint32_t fcode_cnt = 0;
+ boolean_t last_image = FALSE;
+
+ /* collect right rom_version from image[] */
+ i = 0;
+ do {
+ if (qlt->rimage[0].header.signature[0] != PCI_HEADER0) {
+ break;
+ }
+
+ if (qlt->rimage[i].data.codetype == PCI_CODE_X86PC) {
+ /* BIOS */
+ if (bios_cnt == 0) {
+ (void) snprintf(bios0_str,
+ 32,
+ "%d.%02d",
+ qlt->rimage[i].data.
+ revisionlevel[1],
+ qlt->rimage[i].data.
+ revisionlevel[0]);
+ (void) snprintf(tmp, 80,
+ " BIOS: %s;", bios0_str);
+ (void) strcat(orv, tmp);
+ }
+ bios_cnt++;
+ } else if (qlt->rimage[i].data.codetype == PCI_CODE_FCODE) {
+ /* FCode */
+ if (fcode_cnt == 0) {
+ (void) snprintf(fcode_str,
+ 32,
+ "%d.%02d",
+ qlt->rimage[i].data.revisionlevel[1],
+ qlt->rimage[i].data.revisionlevel[0]);
+ (void) snprintf(tmp, 80,
+ " FCode: %s;", fcode_str);
+ (void) strcat(orv, tmp);
+ }
+ fcode_cnt++;
+ } else if (qlt->rimage[i].data.codetype == PCI_CODE_EFI) {
+ /* EFI */
+ (void) snprintf(efi_str,
+ 32,
+ "%d.%02d",
+ qlt->rimage[i].data.revisionlevel[1],
+ qlt->rimage[i].data.revisionlevel[0]);
+ (void) snprintf(tmp, 80, " EFI: %s;", efi_str);
+ (void) strcat(orv, tmp);
+ } else if (qlt->rimage[i].data.codetype == PCI_CODE_HPPA) {
+ /* HPPA */
+ (void) snprintf(hppa_str,
+ 32,
+ "%d.%02d",
+ qlt->rimage[i].data.revisionlevel[1],
+ qlt->rimage[i].data.revisionlevel[0]);
+ (void) snprintf(orv, 80, " HPPA: %s;", hppa_str);
+ (void) strcat(orv, tmp);
+ } else if (qlt->rimage[i].data.codetype == PCI_CODE_FW) {
+ EL(qlt, "fw infor skip\n");
+ } else {
+ /* Unknown */
+ EL(qlt, "unknown image\n");
+ break;
+ }
+
+ if (qlt->rimage[i].data.indicator == PCI_IND_LAST_IMAGE) {
+ last_image = TRUE;
+ break;
+ }
+
+ i ++;
+ } while ((last_image != TRUE) && (i < 6));
+
+ if (last_image != TRUE) {
+ /* No boot image detected */
+ (void) snprintf(orv, FCHBA_OPTION_ROM_VERSION_LEN, "%s",
+ "No boot image detected");
+ }
+ }
+
+ /*
* Filling the hba attributes
*/
void
qlt_populate_hba_fru_details(struct fct_local_port *port,
struct fct_port_attrs *port_attrs)
{
int len;
qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
(void) snprintf(port_attrs->manufacturer, FCHBA_MANUFACTURER_LEN,
"QLogic Corp.");
(void) snprintf(port_attrs->driver_name, FCHBA_DRIVER_NAME_LEN,
"%s", QLT_NAME);
(void) snprintf(port_attrs->driver_version, FCHBA_DRIVER_VERSION_LEN,
"%s", QLT_VERSION);
+ /* get serial_number from vpd data */
+ if (qlt_vpd_lookup(qlt, (uint8_t *)VPD_TAG_SN, (uint8_t *)
+ port_attrs->serial_number, FCHBA_SERIAL_NUMBER_LEN) == -1) {
port_attrs->serial_number[0] = '\0';
+ }
port_attrs->hardware_version[0] = '\0';
(void) snprintf(port_attrs->firmware_version,
FCHBA_FIRMWARE_VERSION_LEN, "%d.%d.%d", qlt->fw_major,
qlt->fw_minor, qlt->fw_subminor);
/* Get FCode version */
! qlt_get_rom_version(qlt, (caddr_t)&port_attrs->option_rom_version[0]);
!
port_attrs->vendor_specific_id = qlt->nvram->subsystem_vendor_id[0] |
qlt->nvram->subsystem_vendor_id[1] << 8;
port_attrs->max_frame_size = qlt->nvram->max_frame_length[1] << 8 |
qlt->nvram->max_frame_length[0];
port_attrs->supported_cos = 0x10000000;
!
! if (qlt->qlt_fcoe_enabled) {
! port_attrs->supported_speed = PORT_SPEED_10G;
! } else if (qlt->qlt_27xx_chip) {
! if ((qlt->qlt_27xx_speed & MAX_SPEED_MASK) == MAX_SPEED_32G) {
! port_attrs->supported_speed = PORT_SPEED_8G |
! PORT_SPEED_16G | PORT_SPEED_32G;
! } else {
! port_attrs->supported_speed = PORT_SPEED_4G |
! PORT_SPEED_8G | PORT_SPEED_16G;
! }
! } else if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
! port_attrs->supported_speed = PORT_SPEED_4G |
! PORT_SPEED_8G | PORT_SPEED_16G;
! } else if (qlt->qlt_25xx_chip) {
port_attrs->supported_speed = PORT_SPEED_2G | PORT_SPEED_4G |
PORT_SPEED_8G;
! } else {
! port_attrs->supported_speed = PORT_SPEED_1G |
! PORT_SPEED_2G | PORT_SPEED_4G;
! }
/* limit string length to nvr model_name length */
! len = ((qlt->qlt_81xx_chip) || (qlt->qlt_83xx_chip) ||
! (qlt->qlt_27xx_chip)) ? 16 : 8;
(void) snprintf(port_attrs->model,
(uint_t)(len < FCHBA_MODEL_LEN ? len : FCHBA_MODEL_LEN),
"%s", qlt->nvram->model_name);
(void) snprintf(port_attrs->model_description,
*** 1034,1043 ****
--- 1842,1854 ----
uint8_t *p;
fct_port_link_status_t *link_status;
switch (cmd) {
case FC_TGT_PORT_RLS:
+ if (qlt->qlt_state != FCT_STATE_ONLINE) {
+ break;
+ }
if ((*bufsizep) < sizeof (fct_port_link_status_t)) {
EL(qlt, "FC_TGT_PORT_RLS bufsizep=%xh < "
"fct_port_link_status_t=%xh\n", *bufsizep,
sizeof (fct_port_link_status_t));
ret = FCT_FAILURE;
*** 1057,1067 ****
mcp->to_fw_mask |= BIT_1 | BIT_8;
mcp->from_fw_mask |= BIT_1 | BIT_2;
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mailbox_command=6dh status=%llxh\n", ret);
qlt_free_mailbox_command(qlt, mcp);
break;
}
qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
--- 1868,1878 ----
mcp->to_fw_mask |= BIT_1 | BIT_8;
mcp->from_fw_mask |= BIT_1 | BIT_2;
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mbox_command=6dh status=%llxh\n", ret);
qlt_free_mailbox_command(qlt, mcp);
break;
}
qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
*** 1096,1105 ****
--- 1907,1917 ----
fct_status_t ret;
if (qlt_dmem_init(qlt) != QLT_SUCCESS) {
return (FCT_FAILURE);
}
+
/* Initialize the ddi_dma_handle free pool */
qlt_dma_handle_pool_init(qlt);
port = (fct_local_port_t *)fct_alloc(FCT_STRUCT_LOCAL_PORT, 0, 0);
if (port == NULL) {
*** 1113,1123 ****
fds->fds_alloc_data_buf = qlt_dmem_alloc;
fds->fds_free_data_buf = qlt_dmem_free;
fds->fds_setup_dbuf = qlt_dma_setup_dbuf;
fds->fds_teardown_dbuf = qlt_dma_teardown_dbuf;
fds->fds_max_sgl_xfer_len = QLT_DMA_SG_LIST_LENGTH * MMU_PAGESIZE;
! fds->fds_copy_threshold = MMU_PAGESIZE;
fds->fds_fca_private = (void *)qlt;
/*
* Since we keep everything in the state struct and dont allocate any
* port private area, just use that pointer to point to the
* state struct.
--- 1925,1935 ----
fds->fds_alloc_data_buf = qlt_dmem_alloc;
fds->fds_free_data_buf = qlt_dmem_free;
fds->fds_setup_dbuf = qlt_dma_setup_dbuf;
fds->fds_teardown_dbuf = qlt_dma_teardown_dbuf;
fds->fds_max_sgl_xfer_len = QLT_DMA_SG_LIST_LENGTH * MMU_PAGESIZE;
! fds->fds_copy_threshold = (uint32_t)MMU_PAGESIZE;
fds->fds_fca_private = (void *)qlt;
/*
* Since we keep everything in the state struct and dont allocate any
* port private area, just use that pointer to point to the
* state struct.
*** 1153,1162 ****
--- 1965,1995 ----
if ((ret = fct_register_local_port(port)) != FCT_SUCCESS) {
EL(qlt, "fct_register_local_port status=%llxh\n", ret);
goto qlt_pstart_fail_2_5;
}
+ EL(qlt, "Qlogic qlt(%d) "
+ "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x:"
+ "WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ qlt->instance,
+ qlt->nvram->port_name[0],
+ qlt->nvram->port_name[1],
+ qlt->nvram->port_name[2],
+ qlt->nvram->port_name[3],
+ qlt->nvram->port_name[4],
+ qlt->nvram->port_name[5],
+ qlt->nvram->port_name[6],
+ qlt->nvram->port_name[7],
+ qlt->nvram->node_name[0],
+ qlt->nvram->node_name[1],
+ qlt->nvram->node_name[2],
+ qlt->nvram->node_name[3],
+ qlt->nvram->node_name[4],
+ qlt->nvram->node_name[5],
+ qlt->nvram->node_name[6],
+ qlt->nvram->node_name[7]);
+
return (QLT_SUCCESS);
#if 0
qlt_pstart_fail_3:
(void) fct_deregister_local_port(port);
#endif
*** 1181,1192 ****
EL(qlt, "fct_register_local_port status=%llxh\n", ret);
return (QLT_FAILURE);
}
fct_free(qlt->qlt_port->port_fds);
fct_free(qlt->qlt_port);
- qlt->qlt_port = NULL;
qlt_dma_handle_pool_fini(qlt);
qlt_dmem_fini(qlt);
return (QLT_SUCCESS);
}
/*
--- 2014,2025 ----
EL(qlt, "fct_register_local_port status=%llxh\n", ret);
return (QLT_FAILURE);
}
fct_free(qlt->qlt_port->port_fds);
fct_free(qlt->qlt_port);
qlt_dma_handle_pool_fini(qlt);
+ qlt->qlt_port = NULL;
qlt_dmem_fini(qlt);
return (QLT_SUCCESS);
}
/*
*** 1196,1206 ****
*/
fct_status_t
qlt_port_online(qlt_state_t *qlt)
{
uint64_t da;
! int instance, i;
fct_status_t ret;
uint16_t rcount;
caddr_t icb;
mbox_cmd_t *mcp;
uint8_t *elsbmp;
--- 2029,2039 ----
*/
fct_status_t
qlt_port_online(qlt_state_t *qlt)
{
uint64_t da;
! int instance, i, j;
fct_status_t ret;
uint16_t rcount;
caddr_t icb;
mbox_cmd_t *mcp;
uint8_t *elsbmp;
*** 1208,1218 ****
instance = ddi_get_instance(qlt->dip);
/* XXX Make sure a sane state */
if ((ret = qlt_download_fw(qlt)) != QLT_SUCCESS) {
! cmn_err(CE_NOTE, "reset chip failed %llx", (long long)ret);
return (ret);
}
bzero(qlt->queue_mem_ptr, TOTAL_DMA_MEM_SIZE);
--- 2041,2052 ----
instance = ddi_get_instance(qlt->dip);
/* XXX Make sure a sane state */
if ((ret = qlt_download_fw(qlt)) != QLT_SUCCESS) {
! cmn_err(CE_NOTE, "qlt(%d): reset chip failed %llx",
! qlt->instance, (long long)ret);
return (ret);
}
bzero(qlt->queue_mem_ptr, TOTAL_DMA_MEM_SIZE);
*** 1251,1261 ****
REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
SETELSBIT(elsbmp, ELS_OP_PLOGI);
SETELSBIT(elsbmp, ELS_OP_LOGO);
SETELSBIT(elsbmp, ELS_OP_ABTX);
! SETELSBIT(elsbmp, ELS_OP_ECHO);
SETELSBIT(elsbmp, ELS_OP_PRLI);
SETELSBIT(elsbmp, ELS_OP_PRLO);
SETELSBIT(elsbmp, ELS_OP_SCN);
SETELSBIT(elsbmp, ELS_OP_TPRLO);
SETELSBIT(elsbmp, ELS_OP_PDISC);
--- 2085,2095 ----
REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
SETELSBIT(elsbmp, ELS_OP_PLOGI);
SETELSBIT(elsbmp, ELS_OP_LOGO);
SETELSBIT(elsbmp, ELS_OP_ABTX);
! /* SETELSBIT(elsbmp, ELS_OP_ECHO); till fct handles it */
SETELSBIT(elsbmp, ELS_OP_PRLI);
SETELSBIT(elsbmp, ELS_OP_PRLO);
SETELSBIT(elsbmp, ELS_OP_SCN);
SETELSBIT(elsbmp, ELS_OP_TPRLO);
SETELSBIT(elsbmp, ELS_OP_PDISC);
*** 1273,1312 ****
elsbmp[1]);
return (ret);
}
/* Init queue pointers */
REG_WR32(qlt, REG_REQ_IN_PTR, 0);
REG_WR32(qlt, REG_REQ_OUT_PTR, 0);
REG_WR32(qlt, REG_RESP_IN_PTR, 0);
REG_WR32(qlt, REG_RESP_OUT_PTR, 0);
REG_WR32(qlt, REG_PREQ_IN_PTR, 0);
REG_WR32(qlt, REG_PREQ_OUT_PTR, 0);
REG_WR32(qlt, REG_ATIO_IN_PTR, 0);
REG_WR32(qlt, REG_ATIO_OUT_PTR, 0);
! qlt->req_ndx_to_fw = qlt->req_ndx_from_fw = 0;
! qlt->req_available = REQUEST_QUEUE_ENTRIES - 1;
! qlt->resp_ndx_to_fw = qlt->resp_ndx_from_fw = 0;
qlt->preq_ndx_to_fw = qlt->preq_ndx_from_fw = 0;
qlt->atio_ndx_to_fw = qlt->atio_ndx_from_fw = 0;
/*
* XXX support for tunables. Also should we cache icb ?
*/
! if (qlt->qlt_81xx_chip) {
! /* allocate extra 64 bytes for Extended init control block */
! mcp = qlt_alloc_mailbox_command(qlt, 0xC0);
} else {
mcp = qlt_alloc_mailbox_command(qlt, 0x80);
}
if (mcp == NULL) {
EL(qlt, "qlt_alloc_mailbox_command mcp=null\n");
return (STMF_ALLOC_FAILURE);
}
icb = (caddr_t)mcp->dbuf->db_sglist[0].seg_addr;
! if (qlt->qlt_81xx_chip) {
! bzero(icb, 0xC0);
} else {
bzero(icb, 0x80);
}
da = qlt->queue_mem_cookie.dmac_laddress;
DMEM_WR16(qlt, icb, 1); /* Version */
--- 2107,2202 ----
elsbmp[1]);
return (ret);
}
/* Init queue pointers */
+ if (qlt->qlt_mq_enabled == 1) {
+ uint16_t qi;
+
+ for (qi = 0; qi < MQ_MAX_QUEUES; qi++) {
+ MQBAR_WR32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_IN, 0);
+ MQBAR_WR32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT, 0);
+ MQBAR_WR32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN, 0);
+ MQBAR_WR32(qlt,
+ (qi * MQBAR_REG_OFFSET) +
+ MQBAR_RESP_OUT, 0);
+ }
+ } else {
REG_WR32(qlt, REG_REQ_IN_PTR, 0);
REG_WR32(qlt, REG_REQ_OUT_PTR, 0);
REG_WR32(qlt, REG_RESP_IN_PTR, 0);
REG_WR32(qlt, REG_RESP_OUT_PTR, 0);
+ }
+
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
REG_WR32(qlt, REG_PREQ_IN_PTR, 0);
REG_WR32(qlt, REG_PREQ_OUT_PTR, 0);
REG_WR32(qlt, REG_ATIO_IN_PTR, 0);
REG_WR32(qlt, REG_ATIO_OUT_PTR, 0);
! }
! qlt->mq_req[0].mq_ndx_to_fw = qlt->mq_req[0].mq_ndx_from_fw = 0;
! qlt->mq_req[0].mq_available = REQUEST_QUEUE_ENTRIES - 1;
!
! if (qlt->qlt_mq_enabled == 1) {
! for (i = 1; i < qlt->qlt_queue_cnt; i++) {
! qlt->mq_req[i].mq_ndx_to_fw = 0;
! qlt->mq_req[i].mq_ndx_from_fw = 0;
! qlt->mq_req[i].mq_available =
! REQUEST_QUEUE_MQ_ENTRIES - 1;
! }
! }
! qlt->mq_resp[0].mq_ndx_to_fw = qlt->mq_resp[0].mq_ndx_from_fw = 0;
!
! if (qlt->qlt_mq_enabled == 1) {
! caddr_t resp;
!
! for (i = 1; i < qlt->qlt_queue_cnt; i++) {
! qlt->mq_resp[i].mq_ndx_to_fw = 0;
! qlt->mq_resp[i].mq_ndx_from_fw = 0;
! for (j = 0; j < RESPONSE_QUEUE_MQ_ENTRIES; j++) {
! resp = &qlt->mq_resp[i].mq_ptr[j << 6];
! QMEM_WR32_RSPQ(qlt, i, resp+0x3c, 0xdeadbeef);
! }
! }
! }
!
! for (i = 0; i < ATIO_QUEUE_ENTRIES; i++) {
! caddr_t atio;
!
! atio = &qlt->atio_ptr[i << 6];
! QMEM_WR32(qlt, atio+0x3c, 0xdeadbeef);
! }
!
qlt->preq_ndx_to_fw = qlt->preq_ndx_from_fw = 0;
qlt->atio_ndx_to_fw = qlt->atio_ndx_from_fw = 0;
/*
* XXX support for tunables. Also should we cache icb ?
*/
! if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_27xx_chip) || ((qlt->qlt_25xx_chip) &&
! (qlt->qlt_mq_enabled))) {
! /*
! * allocate extra 64 bytes for Extended init control block,
! * with separation to allow for a minimal MID section.
! */
! mcp = qlt_alloc_mailbox_command(qlt, 0xE0);
} else {
mcp = qlt_alloc_mailbox_command(qlt, 0x80);
}
if (mcp == NULL) {
EL(qlt, "qlt_alloc_mailbox_command mcp=null\n");
return (STMF_ALLOC_FAILURE);
}
icb = (caddr_t)mcp->dbuf->db_sglist[0].seg_addr;
! if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_27xx_chip) || ((qlt->qlt_25xx_chip) &&
! (qlt->qlt_mq_enabled))) {
! bzero(icb, 0xE0);
} else {
bzero(icb, 0x80);
}
da = qlt->queue_mem_cookie.dmac_laddress;
DMEM_WR16(qlt, icb, 1); /* Version */
*** 1317,1342 ****
bcopy(qlt->qlt_port->port_pwwn, icb+0x0c, 8);
bcopy(qlt->qlt_port->port_nwwn, icb+0x14, 8);
DMEM_WR16(qlt, icb+0x20, 3); /* Login retry count */
DMEM_WR16(qlt, icb+0x24, RESPONSE_QUEUE_ENTRIES);
DMEM_WR16(qlt, icb+0x26, REQUEST_QUEUE_ENTRIES);
! if (!qlt->qlt_81xx_chip) {
DMEM_WR16(qlt, icb+0x28, 100); /* ms of NOS/OLS for Link down */
}
DMEM_WR16(qlt, icb+0x2a, PRIORITY_QUEUE_ENTRIES);
DMEM_WR64(qlt, icb+0x2c, (da+REQUEST_QUEUE_OFFSET));
DMEM_WR64(qlt, icb+0x34, (da+RESPONSE_QUEUE_OFFSET));
DMEM_WR64(qlt, icb+0x3c, (da+PRIORITY_QUEUE_OFFSET));
DMEM_WR16(qlt, icb+0x4e, ATIO_QUEUE_ENTRIES);
DMEM_WR64(qlt, icb+0x50, (da+ATIO_QUEUE_OFFSET));
DMEM_WR16(qlt, icb+0x58, 2); /* Interrupt delay Timer */
DMEM_WR16(qlt, icb+0x5a, 4); /* Login timeout (secs) */
! if (qlt->qlt_81xx_chip) {
qlt_nvram_81xx_t *qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram;
! DMEM_WR32(qlt, icb+0x5c, BIT_5 | BIT_4); /* fw options 1 */
! DMEM_WR32(qlt, icb+0x64, BIT_20 | BIT_4); /* fw options 3 */
DMEM_WR32(qlt, icb+0x70,
qlt81nvr->enode_mac[0] |
(qlt81nvr->enode_mac[1] << 8) |
(qlt81nvr->enode_mac[2] << 16) |
(qlt81nvr->enode_mac[3] << 24));
--- 2207,2273 ----
bcopy(qlt->qlt_port->port_pwwn, icb+0x0c, 8);
bcopy(qlt->qlt_port->port_nwwn, icb+0x14, 8);
DMEM_WR16(qlt, icb+0x20, 3); /* Login retry count */
DMEM_WR16(qlt, icb+0x24, RESPONSE_QUEUE_ENTRIES);
DMEM_WR16(qlt, icb+0x26, REQUEST_QUEUE_ENTRIES);
! if ((!qlt->qlt_83xx_chip) && (!qlt->qlt_81xx_chip) &&
! (!qlt->qlt_27xx_chip)) {
DMEM_WR16(qlt, icb+0x28, 100); /* ms of NOS/OLS for Link down */
}
+ if ((!qlt->qlt_83xx_chip) || (!qlt->qlt_27xx_chip)) {
DMEM_WR16(qlt, icb+0x2a, PRIORITY_QUEUE_ENTRIES);
+ }
DMEM_WR64(qlt, icb+0x2c, (da+REQUEST_QUEUE_OFFSET));
DMEM_WR64(qlt, icb+0x34, (da+RESPONSE_QUEUE_OFFSET));
+ if ((!qlt->qlt_83xx_chip) || (!qlt->qlt_27xx_chip)) {
DMEM_WR64(qlt, icb+0x3c, (da+PRIORITY_QUEUE_OFFSET));
+ }
+ /* XXX: all hba model atio/resp 0 use vector 0 */
DMEM_WR16(qlt, icb+0x4e, ATIO_QUEUE_ENTRIES);
DMEM_WR64(qlt, icb+0x50, (da+ATIO_QUEUE_OFFSET));
DMEM_WR16(qlt, icb+0x58, 2); /* Interrupt delay Timer */
DMEM_WR16(qlt, icb+0x5a, 4); /* Login timeout (secs) */
! if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_27xx_chip) || ((qlt->qlt_25xx_chip) &&
! (qlt->qlt_mq_enabled))) {
qlt_nvram_81xx_t *qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram;
! /* fw options 1 */
! if (qlt->qlt_fcoe_enabled) {
! DMEM_WR32(qlt, icb+0x5c, BIT_5 | BIT_4);
! } else {
! DMEM_WR32(qlt, icb+0x5c,
! BIT_11 | BIT_5 | BIT_4 | BIT_2 | BIT_1 | BIT_0);
! }
! /* fw options 2 */
! if (qlt->qlt_mq_enabled) {
! if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
! if (qlt->qlt_fcoe_enabled) {
! DMEM_WR32(qlt, icb+0x60,
! BIT_26 | BIT_23 | BIT_22);
! } else {
! DMEM_WR32(qlt, icb+0x60,
! BIT_26 | BIT_23 | BIT_22 | BIT_5);
! }
! } else {
! DMEM_WR32(qlt,
! icb+0x60, BIT_26 | BIT_23 | BIT_22 | BIT_5);
! }
! }
!
! /* fw options 3 */
! if (qlt->qlt_fcoe_enabled) {
! DMEM_WR32(qlt, icb+0x64, BIT_4);
! } else {
! DMEM_WR32(qlt, icb+0x64,
! BIT_14 | BIT_8 | BIT_7 | BIT_4);
! }
!
! if (qlt->qlt_mq_enabled) {
! DMEM_WR16(qlt, icb+0x68, 5); /* QoS priority = 5 */
! }
!
DMEM_WR32(qlt, icb+0x70,
qlt81nvr->enode_mac[0] |
(qlt81nvr->enode_mac[1] << 8) |
(qlt81nvr->enode_mac[2] << 16) |
(qlt81nvr->enode_mac[3] << 24));
*** 1347,1375 ****
DMEM_WR32(qlt, icb+0x5c, BIT_11 | BIT_5 | BIT_4 |
BIT_2 | BIT_1 | BIT_0);
DMEM_WR32(qlt, icb+0x60, BIT_5);
DMEM_WR32(qlt, icb+0x64, BIT_14 | BIT_8 | BIT_7 |
BIT_4);
}
! if (qlt->qlt_81xx_chip) {
qlt_dmem_bctl_t *bctl;
uint32_t index;
caddr_t src;
caddr_t dst;
qlt_nvram_81xx_t *qlt81nvr;
! dst = icb+0x80;
qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram;
src = (caddr_t)&qlt81nvr->ext_blk;
index = sizeof (qlt_ext_icb_81xx_t);
/* Use defaults for cases where we find nothing in NVR */
if (*src == 0) {
EL(qlt, "nvram eicb=null\n");
cmn_err(CE_NOTE, "qlt(%d) NVR eicb is zeroed",
instance);
qlt81nvr->ext_blk.version[0] = 1;
/*
* not yet, for !FIP firmware at least
*
* qlt81nvr->ext_blk.fcf_vlan_match = 0x81;
--- 2278,2311 ----
DMEM_WR32(qlt, icb+0x5c, BIT_11 | BIT_5 | BIT_4 |
BIT_2 | BIT_1 | BIT_0);
DMEM_WR32(qlt, icb+0x60, BIT_5);
DMEM_WR32(qlt, icb+0x64, BIT_14 | BIT_8 | BIT_7 |
BIT_4);
+
+ /* null MID setup */
+ DMEM_WR16(qlt, icb+0x80, 1); /* VP count 1 */
}
! if (qlt->qlt_fcoe_enabled) {
qlt_dmem_bctl_t *bctl;
uint32_t index;
caddr_t src;
caddr_t dst;
qlt_nvram_81xx_t *qlt81nvr;
! dst = icb+0xA0;
qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram;
src = (caddr_t)&qlt81nvr->ext_blk;
index = sizeof (qlt_ext_icb_81xx_t);
/* Use defaults for cases where we find nothing in NVR */
+ if ((qlt->qlt_83xx_chip) || (*src == 0)) {
if (*src == 0) {
EL(qlt, "nvram eicb=null\n");
cmn_err(CE_NOTE, "qlt(%d) NVR eicb is zeroed",
instance);
+ }
qlt81nvr->ext_blk.version[0] = 1;
/*
* not yet, for !FIP firmware at least
*
* qlt81nvr->ext_blk.fcf_vlan_match = 0x81;
*** 1386,1396 ****
while (index--) {
*dst++ = *src++;
}
bctl = (qlt_dmem_bctl_t *)mcp->dbuf->db_port_private;
! da = bctl->bctl_dev_addr + 0x80; /* base addr of eicb (phys) */
mcp->to_fw[11] = LSW(LSD(da));
mcp->to_fw[10] = MSW(LSD(da));
mcp->to_fw[13] = LSW(MSD(da));
mcp->to_fw[12] = MSW(MSD(da));
--- 2322,2332 ----
while (index--) {
*dst++ = *src++;
}
bctl = (qlt_dmem_bctl_t *)mcp->dbuf->db_port_private;
! da = bctl->bctl_dev_addr + 0xA0; /* base addr of eicb (phys) */
mcp->to_fw[11] = LSW(LSD(da));
mcp->to_fw[10] = MSW(LSD(da));
mcp->to_fw[13] = LSW(MSD(da));
mcp->to_fw[12] = MSW(MSD(da));
*** 1402,1453 ****
mcp->to_fw_mask |= BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 |
BIT_1;
}
qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORDEV);
mcp->to_fw[0] = MBC_INITIALIZE_FIRMWARE;
/*
* This is the 1st command after adapter initialize which will
* use interrupts and regular mailbox interface.
*/
qlt->mbox_io_state = MBOX_STATE_READY;
REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
/* Issue mailbox to firmware */
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mailbox_command=60h status=%llxh\n", ret);
cmn_err(CE_NOTE, "qlt(%d) init fw failed %llx, intr status %x",
instance, (long long)ret, REG_RD32(qlt, REG_INTR_STATUS));
}
mcp->to_fw_mask = BIT_0;
mcp->from_fw_mask = BIT_0 | BIT_1;
mcp->to_fw[0] = 0x28;
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mailbox_command=28h status=%llxh\n", ret);
cmn_err(CE_NOTE, "qlt(%d) get_fw_options %llx", instance,
(long long)ret);
}
/*
* Report FW versions for 81xx - MPI rev is useful
*/
! if (qlt->qlt_81xx_chip) {
mcp->to_fw_mask = BIT_0;
! mcp->from_fw_mask = BIT_11 | BIT_10 | BIT_3 | BIT_2 | BIT_1 |
! BIT_0;
! mcp->to_fw[0] = 0x8;
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
EL(qlt, "about fw failed: %llx\n", (long long)ret);
} else {
EL(qlt, "Firmware version %d.%d.%d, MPI: %d.%d.%d\n",
mcp->from_fw[1], mcp->from_fw[2], mcp->from_fw[3],
mcp->from_fw[10] & 0xff, mcp->from_fw[11] >> 8,
mcp->from_fw[11] & 0xff);
}
}
qlt_free_mailbox_command(qlt, mcp);
--- 2338,2480 ----
mcp->to_fw_mask |= BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 |
BIT_1;
}
qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORDEV);
+ if (((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip) ||
+ (qlt->qlt_27xx_chip) || ((qlt->qlt_25xx_chip) &&
+ (qlt->qlt_mq_enabled))) && (qlt->fw_attr & BIT_6)) {
+ mcp->to_fw[0] = MBC_INITIALIZE_MULTI_ID_FW;
+ } else {
mcp->to_fw[0] = MBC_INITIALIZE_FIRMWARE;
+ }
/*
* This is the 1st command after adapter initialize which will
* use interrupts and regular mailbox interface.
*/
+ qlt->qlt_intr_enabled = 1;
qlt->mbox_io_state = MBOX_STATE_READY;
REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
/* Issue mailbox to firmware */
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mbox_command=48h/60h status=%llxh\n", ret);
cmn_err(CE_NOTE, "qlt(%d) init fw failed %llx, intr status %x",
instance, (long long)ret, REG_RD32(qlt, REG_INTR_STATUS));
+ qlt_free_mailbox_command(qlt, mcp);
+ return (ret);
}
mcp->to_fw_mask = BIT_0;
mcp->from_fw_mask = BIT_0 | BIT_1;
mcp->to_fw[0] = 0x28;
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mbox_command=28h status=%llxh\n", ret);
cmn_err(CE_NOTE, "qlt(%d) get_fw_options %llx", instance,
(long long)ret);
+ qlt_free_mailbox_command(qlt, mcp);
+ return (ret);
}
+ if (qlt->qlt_mq_enabled == 1) {
+
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ da = qlt->mq_resp[i].queue_mem_mq_cookie.dmac_laddress;
+
+ mcp->to_fw_mask = BIT_14 | BIT_13 | BIT_12 | BIT_11 |
+ BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 |
+ BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0;
+ mcp->from_fw_mask = BIT_0 | BIT_1;
+
+ /* msix vector setup */
+ mcp->to_fw[14] = (uint16_t)(i);
+
+ mcp->to_fw[13] = 0;
+ mcp->to_fw[12] = 0;
+ mcp->to_fw[11] = 0;
+ mcp->to_fw[10] = 0;
+ mcp->to_fw[9] = 0;
+ mcp->to_fw[8] = 0;
+ mcp->to_fw[7] = LSW(MSD(da));
+ mcp->to_fw[6] = MSW(MSD(da));
+ mcp->to_fw[5] = RESPONSE_QUEUE_MQ_ENTRIES;
+ mcp->to_fw[4] = (uint16_t)(i);
+ mcp->to_fw[3] = LSW(LSD(da));
+ mcp->to_fw[2] = MSW(LSD(da));
+ mcp->to_fw[1] = BIT_6 | BIT_1;
+ mcp->to_fw[0] = 0x1F;
+ ret = qlt_mailbox_command(qlt, mcp);
+
+ if (ret != QLT_SUCCESS) {
+ EL(qlt, "qlt_mbox_command=1fh status=%llxh\n",
+ ret);
+ cmn_err(CE_NOTE, "qlt(%d) queue manage %llx",
+ instance, (long long)ret);
+ qlt_free_mailbox_command(qlt, mcp);
+ return (ret);
+ }
+
+ da = qlt->mq_req[i].queue_mem_mq_cookie.dmac_laddress;
+
+ mcp->to_fw_mask = BIT_14 | BIT_13 | BIT_12 | BIT_11 |
+ BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 |
+ BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0;
+ mcp->from_fw_mask = BIT_0 | BIT_1;
+
/*
+ * msix vector does not apply for request queue create
+ */
+ mcp->to_fw[14] = 2;
+ mcp->to_fw[13] = 0;
+ mcp->to_fw[12] = 4;
+ mcp->to_fw[11] = 0;
+ mcp->to_fw[10] = (uint16_t)(i);
+ mcp->to_fw[9] = 0;
+ mcp->to_fw[8] = 0;
+ mcp->to_fw[7] = LSW(MSD(da));
+ mcp->to_fw[6] = MSW(MSD(da));
+ mcp->to_fw[5] = REQUEST_QUEUE_MQ_ENTRIES;
+ mcp->to_fw[4] = (uint16_t)(i);
+ mcp->to_fw[3] = LSW(LSD(da));
+ mcp->to_fw[2] = MSW(LSD(da));
+ mcp->to_fw[1] = BIT_6;
+ mcp->to_fw[0] = 0x1F;
+ ret = qlt_mailbox_command(qlt, mcp);
+
+ if (ret != QLT_SUCCESS) {
+ EL(qlt, "qlt_mbox_command=1fh status=%llxh\n",
+ ret);
+ cmn_err(CE_NOTE, "qlt(%d) queue manage %llx",
+ instance, (long long)ret);
+ qlt_free_mailbox_command(qlt, mcp);
+ return (ret);
+ }
+ }
+ }
+
+ /*
* Report FW versions for 81xx - MPI rev is useful
*/
! /* if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip)) { */
! if (qlt->qlt_fcoe_enabled) {
mcp->to_fw_mask = BIT_0;
! mcp->from_fw_mask = BIT_11 | BIT_10 | BIT_6 | BIT_3 | BIT_2 |
! BIT_1 | BIT_0;
!
! mcp->to_fw[0] = MBC_ABOUT_FIRMWARE;
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
EL(qlt, "about fw failed: %llx\n", (long long)ret);
} else {
EL(qlt, "Firmware version %d.%d.%d, MPI: %d.%d.%d\n",
mcp->from_fw[1], mcp->from_fw[2], mcp->from_fw[3],
mcp->from_fw[10] & 0xff, mcp->from_fw[11] >> 8,
mcp->from_fw[11] & 0xff);
+ EL(qlt, "Firmware Attributes %x[h]\n",
+ mcp->from_fw[6]);
}
}
qlt_free_mailbox_command(qlt, mcp);
*** 1458,1474 ****
--- 2485,2503 ----
qlt->qlt_pmintry = 0;
qlt->qlt_pmin_ok = 0;
if (ret != QLT_SUCCESS)
return (ret);
+
return (FCT_SUCCESS);
}
fct_status_t
qlt_port_offline(qlt_state_t *qlt)
{
int retries;
+ int i;
mutex_enter(&qlt->mbox_lock);
if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) {
mutex_exit(&qlt->mbox_lock);
*** 1489,1501 ****
--- 2518,2540 ----
qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
mutex_exit(&qlt->mbox_lock);
poff_mbox_done:;
qlt->intr_sneak_counter = 10;
mutex_enter(&qlt->intr_lock);
+ if (qlt->qlt_mq_enabled == 1) {
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ mutex_enter(&qlt->mq_resp[i].mq_lock);
+ }
+ }
(void) qlt_reset_chip(qlt);
drv_usecwait(20);
qlt->intr_sneak_counter = 0;
+ if (qlt->qlt_mq_enabled == 1) {
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ mutex_exit(&qlt->mq_resp[i].mq_lock);
+ }
+ }
mutex_exit(&qlt->intr_lock);
return (FCT_SUCCESS);
}
*** 1516,1533 ****
mcp->to_fw_mask |= BIT_0 | BIT_9;
mcp->from_fw_mask |= BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_6 | BIT_7;
/* Issue mailbox to firmware */
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mailbox_command=20h status=%llxh\n", ret);
! if ((mcp->from_fw[0] == 0x4005) && (mcp->from_fw[1] == 7)) {
/* Firmware is not ready */
if (ddi_get_lbolt() < et) {
delay(drv_usectohz(50000));
goto link_info_retry;
}
}
stmf_trace(qlt->qlt_port_alias, "GET ID mbox failed, ret=%llx "
"mb0=%x mb1=%x", ret, mcp->from_fw[0], mcp->from_fw[1]);
fc_ret = FCT_FAILURE;
} else {
li->portid = ((uint32_t)(mcp->from_fw[2])) |
--- 2555,2575 ----
mcp->to_fw_mask |= BIT_0 | BIT_9;
mcp->from_fw_mask |= BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_6 | BIT_7;
/* Issue mailbox to firmware */
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mbox_command=20h status=%llxh\n", ret);
! if ((mcp->from_fw[0] == 0x4005) &&
! ((mcp->from_fw[1] == 7) || (mcp->from_fw[1] == 0x1b))) {
/* Firmware is not ready */
if (ddi_get_lbolt() < et) {
delay(drv_usectohz(50000));
goto link_info_retry;
}
}
+ EL(qlt, "GET ID mbox failed, ret=%llx mb0=%x mb1=%x",
+ ret, mcp->from_fw[0], mcp->from_fw[1]);
stmf_trace(qlt->qlt_port_alias, "GET ID mbox failed, ret=%llx "
"mb0=%x mb1=%x", ret, mcp->from_fw[0], mcp->from_fw[1]);
fc_ret = FCT_FAILURE;
} else {
li->portid = ((uint32_t)(mcp->from_fw[2])) |
*** 1556,1565 ****
--- 2598,2611 ----
li->port_topology = PORT_TOPOLOGY_UNKNOWN;
EL(qlt, "Unknown topology=%xh\n", mcp->from_fw[6]);
}
qlt->cur_topology = li->port_topology;
fc_ret = FCT_SUCCESS;
+
+ EL(qlt, "MBC_GET_ID done, Topology=%x, portid=%xh, "
+ "port speed=%xh\n", li->port_topology, li->portid,
+ li->port_speed);
}
qlt_free_mailbox_command(qlt, mcp);
if ((fc_ret == FCT_SUCCESS) && (li->port_fca_flogi_done)) {
mcp = qlt_alloc_mailbox_command(qlt, 64);
*** 1568,1578 ****
mcp->to_fw[9] = 0;
mcp->to_fw[10] = 0;
mcp->to_fw_mask |= BIT_0 | BIT_1 | BIT_9 | BIT_10;
fc_ret = qlt_mailbox_command(qlt, mcp);
if (fc_ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mailbox_command=64h status=%llxh\n",
fc_ret);
stmf_trace(qlt->qlt_port_alias, "Attempt to get port "
"database for F_port failed, ret = %llx", fc_ret);
} else {
uint8_t *p;
--- 2614,2624 ----
mcp->to_fw[9] = 0;
mcp->to_fw[10] = 0;
mcp->to_fw_mask |= BIT_0 | BIT_1 | BIT_9 | BIT_10;
fc_ret = qlt_mailbox_command(qlt, mcp);
if (fc_ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mbox_command=64h status=%llxh\n",
fc_ret);
stmf_trace(qlt->qlt_port_alias, "Attempt to get port "
"database for F_port failed, ret = %llx", fc_ret);
} else {
uint8_t *p;
*** 1579,1588 ****
--- 2625,2636 ----
qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
p = mcp->dbuf->db_sglist[0].seg_addr;
bcopy(p + 0x18, li->port_rpwwn, 8);
bcopy(p + 0x20, li->port_rnwwn, 8);
+ EL(qlt, "qlt_mbox_command=64h, GET_PORT_DATABASE "
+ "complete\n");
}
qlt_free_mailbox_command(qlt, mcp);
}
return (fc_ret);
}
*** 1693,1703 ****
void *obuf = NULL;
uint32_t *intp;
qlt_fw_info_t *fwi;
mbox_cmd_t *mcp;
fct_status_t st;
! char info[QLT_INFO_LEN];
fct_status_t ret2;
if (drv_priv(credp) != 0)
return (EPERM);
--- 2741,2751 ----
void *obuf = NULL;
uint32_t *intp;
qlt_fw_info_t *fwi;
mbox_cmd_t *mcp;
fct_status_t st;
! char info[80];
fct_status_t ret2;
if (drv_priv(credp) != 0)
return (EPERM);
*** 1747,1758 ****
if (qlt->qlt_state != FCT_STATE_ONLINE) {
ret = EACCES;
iocd->stmf_error = QLTIO_NOT_ONLINE;
break;
}
! (void) snprintf(info, sizeof (info), "qlt_ioctl: qlt-%p, "
"user triggered FWDUMP with RFLAG_RESET", (void *)qlt);
if ((ret2 = fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_USER_REQUEST | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info)) != FCT_SUCCESS) {
EL(qlt, "TRIGGER_FWDUMP fct_port_shutdown status="
"%llxh\n", ret2);
--- 2795,2807 ----
if (qlt->qlt_state != FCT_STATE_ONLINE) {
ret = EACCES;
iocd->stmf_error = QLTIO_NOT_ONLINE;
break;
}
! (void) snprintf(info, 80, "qlt_ioctl: qlt-%p, "
"user triggered FWDUMP with RFLAG_RESET", (void *)qlt);
+ info[79] = 0;
if ((ret2 = fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_USER_REQUEST | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info)) != FCT_SUCCESS) {
EL(qlt, "TRIGGER_FWDUMP fct_port_shutdown status="
"%llxh\n", ret2);
*** 1784,1793 ****
--- 2833,2843 ----
break;
}
if ((qlt->qlt_81xx_chip && ((intp[8] & 8) == 0)) ||
(qlt->qlt_25xx_chip && ((intp[8] & 4) == 0)) ||
(!qlt->qlt_25xx_chip && !qlt->qlt_81xx_chip &&
+ !qlt->qlt_83xx_chip && !qlt->qlt_27xx_chip &&
((intp[8] & 3) == 0))) {
EL(qlt, "UPLOAD_FW fw_type=%d\n", intp[8]);
ret = EACCES;
iocd->stmf_error = QLTIO_INVALID_FW_TYPE;
break;
*** 1843,1853 ****
fwi->fwi_loaded_major = (uint16_t)qlt->fw_code01[4];
fwi->fwi_loaded_minor = (uint16_t)qlt->fw_code01[5];
fwi->fwi_loaded_subminor = (uint16_t)qlt->fw_code01[6];
fwi->fwi_loaded_attr = (uint16_t)qlt->fw_code01[7];
}
! if (qlt->qlt_81xx_chip) {
fwi->fwi_default_major = (uint16_t)fw8100_code01[4];
fwi->fwi_default_minor = (uint16_t)fw8100_code01[5];
fwi->fwi_default_subminor = (uint16_t)fw8100_code01[6];
fwi->fwi_default_attr = (uint16_t)fw8100_code01[7];
} else if (qlt->qlt_25xx_chip) {
--- 2893,2914 ----
fwi->fwi_loaded_major = (uint16_t)qlt->fw_code01[4];
fwi->fwi_loaded_minor = (uint16_t)qlt->fw_code01[5];
fwi->fwi_loaded_subminor = (uint16_t)qlt->fw_code01[6];
fwi->fwi_loaded_attr = (uint16_t)qlt->fw_code01[7];
}
! if (qlt->qlt_27xx_chip) {
! fwi->fwi_default_major = (uint16_t)fw2700_code01[4];
! fwi->fwi_default_minor = (uint16_t)fw2700_code01[5];
! fwi->fwi_default_subminor = (uint16_t)fw2700_code01[6];
! fwi->fwi_default_attr = (uint16_t)fw2700_code01[7];
! } else if (qlt->qlt_83xx_chip) {
! fwi->fwi_default_major = (uint16_t)fw8300fc_code01[4];
! fwi->fwi_default_minor = (uint16_t)fw8300fc_code01[5];
! fwi->fwi_default_subminor =
! (uint16_t)fw8300fc_code01[6];
! fwi->fwi_default_attr = (uint16_t)fw8300fc_code01[7];
! } else if (qlt->qlt_81xx_chip) {
fwi->fwi_default_major = (uint16_t)fw8100_code01[4];
fwi->fwi_default_minor = (uint16_t)fw8100_code01[5];
fwi->fwi_default_subminor = (uint16_t)fw8100_code01[6];
fwi->fwi_default_attr = (uint16_t)fw8100_code01[7];
} else if (qlt->qlt_25xx_chip) {
*** 1918,1928 ****
}
}
break;
case QLT_IOCTL_ELOG:
! qlt_dump_el_trace_buffer(qlt);
break;
default:
EL(qlt, "Unknown ioctl-%xh\n", cmd);
ret = ENOTTY;
--- 2979,2989 ----
}
}
break;
case QLT_IOCTL_ELOG:
! EL(qlt, "Not support yet, ioctl-%xh\n", cmd);
break;
default:
EL(qlt, "Unknown ioctl-%xh\n", cmd);
ret = ENOTTY;
*** 1950,1968 ****
{
mbox_cmd_t *mcp;
fct_status_t rval;
mcp = qlt_alloc_mailbox_command(qlt, 0);
! mcp->to_fw[0] = 0x0072;
mcp->to_fw[1] = BIT_4;
mcp->to_fw[3] = 1;
mcp->to_fw_mask |= BIT_1 | BIT_3;
rval = qlt_mailbox_command(qlt, mcp);
if (rval != FCT_SUCCESS) {
! EL(qlt, "qlt force lip MB failed: rval=%x", rval);
} else {
! if (mcp->from_fw[0] != 0x4000) {
QLT_LOG(qlt->qlt_port_alias, "qlt FLIP: fw[0]=%x",
mcp->from_fw[0]);
rval = FCT_FAILURE;
}
}
--- 3011,3033 ----
{
mbox_cmd_t *mcp;
fct_status_t rval;
mcp = qlt_alloc_mailbox_command(qlt, 0);
! if (qlt->qlt_fcoe_enabled) {
! mcp->to_fw[0] = MBC_PORT_RESET;
! } else {
! mcp->to_fw[0] = MBC_LIP_FULL_LOGIN;
mcp->to_fw[1] = BIT_4;
mcp->to_fw[3] = 1;
mcp->to_fw_mask |= BIT_1 | BIT_3;
+ }
rval = qlt_mailbox_command(qlt, mcp);
if (rval != FCT_SUCCESS) {
! EL(qlt, "qlt force lip MB failed: rval=%x\n", rval);
} else {
! if (mcp->from_fw[0] != QLT_MBX_CMD_SUCCESS) {
QLT_LOG(qlt->qlt_port_alias, "qlt FLIP: fw[0]=%x",
mcp->from_fw[0]);
rval = FCT_FAILURE;
}
}
*** 1986,1995 ****
--- 3051,3063 ----
qlt = (qlt_state_t *)port->port_fca_private;
st.st_completion_status = FCT_SUCCESS;
st.st_additional_info = NULL;
+ EL(qlt, "port (%p) qlt_state (%xh) cmd (%xh) arg (%p)\n",
+ port, qlt->qlt_state, cmd, arg);
+
switch (cmd) {
case FCT_CMD_PORT_ONLINE:
if (qlt->qlt_state == FCT_STATE_ONLINE)
st.st_completion_status = STMF_ALREADY;
else if (qlt->qlt_state != FCT_STATE_OFFLINE)
*** 2059,2079 ****
}
}
break;
case FCT_CMD_FORCE_LIP:
! if (qlt->qlt_81xx_chip) {
EL(qlt, "force lip is an unsupported command "
"for this adapter type\n");
} else {
*((fct_status_t *)arg) = qlt_force_lip(qlt);
EL(qlt, "forcelip done\n");
}
break;
default:
! EL(qlt, "unsupport cmd - 0x%02X", cmd);
break;
}
}
/* ARGSUSED */
--- 3127,3149 ----
}
}
break;
case FCT_CMD_FORCE_LIP:
! if (qlt->qlt_fcoe_enabled) {
EL(qlt, "force lip is an unsupported command "
"for this adapter type\n");
} else {
+ if (qlt->qlt_state == FCT_STATE_ONLINE) {
*((fct_status_t *)arg) = qlt_force_lip(qlt);
EL(qlt, "forcelip done\n");
}
+ }
break;
default:
! EL(qlt, "unsupport cmd - 0x%02X\n", cmd);
break;
}
}
/* ARGSUSED */
*** 2093,2149 ****
* less/zero entries are available. Retuns NULL if it still cannot
* fullfill the request.
* **CALL qlt_submit_req_entries() BEFORE DROPPING THE LOCK**
*/
caddr_t
! qlt_get_req_entries(qlt_state_t *qlt, uint32_t n)
{
int try = 0;
! while (qlt->req_available < n) {
uint32_t val1, val2, val3;
val1 = REG_RD32(qlt, REG_REQ_OUT_PTR);
val2 = REG_RD32(qlt, REG_REQ_OUT_PTR);
val3 = REG_RD32(qlt, REG_REQ_OUT_PTR);
if ((val1 != val2) || (val2 != val3))
continue;
! qlt->req_ndx_from_fw = val1;
! qlt->req_available = REQUEST_QUEUE_ENTRIES - 1 -
! ((qlt->req_ndx_to_fw - qlt->req_ndx_from_fw) &
(REQUEST_QUEUE_ENTRIES - 1));
! if (qlt->req_available < n) {
if (try < 2) {
drv_usecwait(100);
try++;
continue;
} else {
stmf_trace(qlt->qlt_port_alias,
! "Req Q is full");
return (NULL);
}
}
break;
}
/* We dont change anything until the entries are sumitted */
! return (&qlt->req_ptr[qlt->req_ndx_to_fw << 6]);
}
/*
* updates the req in ptr to fw. Assumes that req lock is held.
*/
void
! qlt_submit_req_entries(qlt_state_t *qlt, uint32_t n)
{
ASSERT(n >= 1);
- qlt->req_ndx_to_fw += n;
- qlt->req_ndx_to_fw &= REQUEST_QUEUE_ENTRIES - 1;
- qlt->req_available -= n;
- REG_WR32(qlt, REG_REQ_IN_PTR, qlt->req_ndx_to_fw);
- }
/*
* Return a pointer to n entries in the priority request queue. Assumes that
* priority request queue lock is held. Does a very short busy wait if
* less/zero entries are available. Retuns NULL if it still cannot
* fullfill the request.
--- 3163,3255 ----
* less/zero entries are available. Retuns NULL if it still cannot
* fullfill the request.
* **CALL qlt_submit_req_entries() BEFORE DROPPING THE LOCK**
*/
caddr_t
! qlt_get_req_entries(qlt_state_t *qlt, uint32_t n, uint16_t qi)
{
int try = 0;
! while (qlt->mq_req[qi].mq_available < n) {
uint32_t val1, val2, val3;
+
+ if (qlt->qlt_mq_enabled) {
+ /* debounce */
+ val1 = MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT);
+ val2 = MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT);
+ val3 = MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT);
+ } else {
val1 = REG_RD32(qlt, REG_REQ_OUT_PTR);
val2 = REG_RD32(qlt, REG_REQ_OUT_PTR);
val3 = REG_RD32(qlt, REG_REQ_OUT_PTR);
+ }
if ((val1 != val2) || (val2 != val3))
continue;
! qlt->mq_req[qi].mq_ndx_from_fw = val1;
! if (qi != 0) {
! qlt->mq_req[qi].mq_available =
! REQUEST_QUEUE_MQ_ENTRIES - 1 -
! ((qlt->mq_req[qi].mq_ndx_to_fw -
! qlt->mq_req[qi].mq_ndx_from_fw) &
! (REQUEST_QUEUE_MQ_ENTRIES - 1));
! } else {
! qlt->mq_req[qi].mq_available =
! REQUEST_QUEUE_ENTRIES - 1 -
! ((qlt->mq_req[qi].mq_ndx_to_fw -
! qlt->mq_req[qi].mq_ndx_from_fw) &
(REQUEST_QUEUE_ENTRIES - 1));
! }
! if (qlt->mq_req[qi].mq_available < n) {
if (try < 2) {
drv_usecwait(100);
try++;
continue;
} else {
stmf_trace(qlt->qlt_port_alias,
! "Req Q# %xh is full", qi);
! EL(qlt, "Req %xh is full (%d,%d) (%d,%d)\n",
! qi, qlt->mq_req[qi].mq_ndx_to_fw,
! qlt->mq_req[qi].mq_ndx_from_fw,
! n, qlt->mq_req[qi].mq_available);
return (NULL);
}
}
break;
}
/* We dont change anything until the entries are sumitted */
! return (&qlt->mq_req[qi].mq_ptr[qlt->mq_req[qi].mq_ndx_to_fw << 6]);
}
/*
* updates the req in ptr to fw. Assumes that req lock is held.
*/
void
! qlt_submit_req_entries(qlt_state_t *qlt, uint32_t n, uint16_t qi)
{
+
ASSERT(n >= 1);
+ qlt->mq_req[qi].mq_ndx_to_fw += n;
+ if (qi != 0) {
+ qlt->mq_req[qi].mq_ndx_to_fw &= REQUEST_QUEUE_MQ_ENTRIES - 1;
+ } else {
+ qlt->mq_req[qi].mq_ndx_to_fw &= REQUEST_QUEUE_ENTRIES - 1;
+ }
+ qlt->mq_req[qi].mq_available -= n;
+ if (qlt->qlt_mq_enabled) {
+ MQBAR_WR32(qlt, (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_IN,
+ qlt->mq_req[qi].mq_ndx_to_fw);
+ } else {
+ REG_WR32(qlt, REG_REQ_IN_PTR, qlt->mq_req[0].mq_ndx_to_fw);
+ }
+ }
+
/*
* Return a pointer to n entries in the priority request queue. Assumes that
* priority request queue lock is held. Does a very short busy wait if
* less/zero entries are available. Retuns NULL if it still cannot
* fullfill the request.
*** 2216,2225 ****
--- 3322,3332 ----
EL(qlt, "initiated\n");
/* XXX: Switch off LEDs */
+ qlt->qlt_intr_enabled = 0;
/* Disable Interrupts */
REG_WR32(qlt, REG_INTR_CTRL, 0);
(void) REG_RD32(qlt, REG_INTR_CTRL);
/* Stop DMA */
REG_WR32(qlt, REG_CTRL_STATUS, DMA_SHUTDOWN_CTRL | PCI_X_XFER_CTRL);
*** 2232,2249 ****
--- 3339,3386 ----
/* 3 sec should be more than enough */
if (cntr == 300)
return (QLT_DMA_STUCK);
}
+ /* need to ensure no one accesses the hw during the reset 100us */
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ mutex_enter(&qlt->mbox_lock);
+ if (qlt->qlt_mq_enabled == 1) {
+ int i;
+
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ mutex_enter(&qlt->mq_req[i].mq_lock);
+ }
+ }
+ mutex_enter(&qlt->mq_req[0].mq_lock);
+ /*
+ * We need to give time for other threads to finsh their
+ * interupts (or we need another lock)
+ */
+ drv_usecwait(40);
+ }
+
/* Reset the Chip */
REG_WR32(qlt, REG_CTRL_STATUS,
DMA_SHUTDOWN_CTRL | PCI_X_XFER_CTRL | CHIP_SOFT_RESET);
qlt->qlt_link_up = 0;
drv_usecwait(100);
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ mutex_exit(&qlt->mq_req[0].mq_lock);
+ if (qlt->qlt_mq_enabled == 1) {
+ int i;
+
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ mutex_exit(&qlt->mq_req[i].mq_lock);
+ }
+ }
+ mutex_exit(&qlt->mbox_lock);
+ }
+
/* Wait for ROM firmware to initialize (0x0000) in mailbox 0 */
cntr = 0;
while (REG_RD16(qlt, REG_MBOX(0)) != 0) {
delay(drv_usectohz(10000));
cntr++;
*** 2254,2263 ****
--- 3391,3401 ----
/* Disable Interrupts (Probably not needed) */
REG_WR32(qlt, REG_INTR_CTRL, 0);
return (QLT_SUCCESS);
}
+
/*
* - Should not be called from Interrupt.
* - A very hardware specific function. Does not touch driver state.
* - Assumes that interrupts are disabled or not there.
* - Expects that the caller makes sure that all activity has stopped
*** 2290,2299 ****
--- 3428,3454 ----
if (ret == QLT_SUCCESS) {
ret = qlt_load_risc_ram(qlt, qlt->fw_code02,
qlt->fw_length02, qlt->fw_addr02);
}
start_addr = qlt->fw_addr01;
+ } else if (qlt->qlt_27xx_chip) {
+ (void) qlt_27xx_get_dmp_template(qlt);
+ ret = qlt_load_risc_ram(qlt, fw2700_code01,
+ fw2700_length01, fw2700_addr01);
+ if (ret == QLT_SUCCESS) {
+ ret = qlt_load_risc_ram(qlt, fw2700_code02,
+ fw2700_length02, fw2700_addr02);
+ }
+ start_addr = fw2700_addr01;
+ } else if (qlt->qlt_83xx_chip) {
+ ret = qlt_load_risc_ram(qlt, fw8300fc_code01,
+ fw8300fc_length01, fw8300fc_addr01);
+ if (ret == QLT_SUCCESS) {
+ ret = qlt_load_risc_ram(qlt, fw8300fc_code02,
+ fw8300fc_length02, fw8300fc_addr02);
+ }
+ start_addr = fw8300fc_addr01;
} else if (qlt->qlt_81xx_chip) {
ret = qlt_load_risc_ram(qlt, fw8100_code01, fw8100_length01,
fw8100_addr01);
if (ret == QLT_SUCCESS) {
ret = qlt_load_risc_ram(qlt, fw8100_code02,
*** 2336,2352 ****
/* Execute firmware */
REG_WR16(qlt, REG_MBOX(0), MBC_EXECUTE_FIRMWARE);
REG_WR16(qlt, REG_MBOX(1), MSW(start_addr));
REG_WR16(qlt, REG_MBOX(2), LSW(start_addr));
REG_WR16(qlt, REG_MBOX(3), 0);
! REG_WR16(qlt, REG_MBOX(4), 1); /* 25xx enable additional credits */
ret = qlt_raw_mailbox_command(qlt);
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
if (ret != QLT_SUCCESS) {
EL(qlt, "qlt_raw_mailbox_command=2h status=%llxh\n", ret);
return (ret);
}
/* Get revisions (About Firmware) */
REG_WR16(qlt, REG_MBOX(0), MBC_ABOUT_FIRMWARE);
ret = qlt_raw_mailbox_command(qlt);
qlt->fw_major = REG_RD16(qlt, REG_MBOX(1));
--- 3491,3524 ----
/* Execute firmware */
REG_WR16(qlt, REG_MBOX(0), MBC_EXECUTE_FIRMWARE);
REG_WR16(qlt, REG_MBOX(1), MSW(start_addr));
REG_WR16(qlt, REG_MBOX(2), LSW(start_addr));
REG_WR16(qlt, REG_MBOX(3), 0);
! #ifdef EXTRA_CREDIT
! /* enable extra credits (reduces available buffers) */
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
! REG_WR16(qlt, REG_MBOX(4), 1);
! } else {
! REG_WR16(qlt, REG_MBOX(4), 0);
! }
! #else
! REG_WR16(qlt, REG_MBOX(4), 0);
! #endif
ret = qlt_raw_mailbox_command(qlt);
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
if (ret != QLT_SUCCESS) {
EL(qlt, "qlt_raw_mailbox_command=2h status=%llxh\n", ret);
return (ret);
+ } else {
+ if (qlt->qlt_27xx_chip) {
+ qlt->qlt_27xx_speed = (uint32_t)
+ (REG_RD16(qlt, REG_MBOX(3)) << 16 |
+ REG_RD16(qlt, REG_MBOX(2)));
+
}
+ }
/* Get revisions (About Firmware) */
REG_WR16(qlt, REG_MBOX(0), MBC_ABOUT_FIRMWARE);
ret = qlt_raw_mailbox_command(qlt);
qlt->fw_major = REG_RD16(qlt, REG_MBOX(1));
*** 2359,2368 ****
--- 3531,3559 ----
if (ret != QLT_SUCCESS) {
EL(qlt, "qlt_raw_mailbox_command=8h status=%llxh\n", ret);
return (ret);
}
+ if (qlt->qlt_27xx_chip) {
+ qlt->fw_ext_memory_end = SHORT_TO_LONG(
+ REG_RD16(qlt, REG_MBOX(4)),
+ REG_RD16(qlt, REG_MBOX(5)));
+ qlt->fw_shared_ram_start = SHORT_TO_LONG(
+ REG_RD16(qlt, REG_MBOX(18)),
+ REG_RD16(qlt, REG_MBOX(19)));
+ qlt->fw_shared_ram_end = SHORT_TO_LONG(
+ REG_RD16(qlt, REG_MBOX(20)),
+ REG_RD16(qlt, REG_MBOX(21)));
+ qlt->fw_ddr_ram_start = SHORT_TO_LONG(
+ REG_RD16(qlt, REG_MBOX(22)),
+ REG_RD16(qlt, REG_MBOX(23)));
+ qlt->fw_ddr_ram_end = SHORT_TO_LONG(
+ REG_RD16(qlt, REG_MBOX(24)),
+ REG_RD16(qlt, REG_MBOX(25)));
+ }
+
+
return (QLT_SUCCESS);
}
/*
* Used only from qlt_download_fw().
*** 2405,2414 ****
--- 3596,3606 ----
ret);
return (ret);
}
words_sent += words_being_sent;
}
+ EL(qlt, "qlt_raw_mailbox_command=0Bh, LOAD_RAM_EXTENDED complete\n");
return (QLT_SUCCESS);
}
/*
* Not used during normal operation. Only during driver init.
*** 2416,2437 ****
* Just triggers the mailbox command an waits for the completion.
* Also expects that There is nothing else going on and we will only
* get back a mailbox completion from firmware.
* ---DOES NOT CLEAR INTERRUPT---
* Used only from the code path originating from
! * qlt_reset_chip_and_download_fw()
*/
static fct_status_t
qlt_raw_mailbox_command(qlt_state_t *qlt)
{
int cntr = 0;
uint32_t status;
REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
while ((REG_RD32(qlt, REG_INTR_STATUS) & RISC_PCI_INTR_REQUEST) == 0) {
cntr++;
! if (cntr == 100) {
return (QLT_MAILBOX_STUCK);
}
delay(drv_usectohz(10000));
}
status = (REG_RD32(qlt, REG_RISC_STATUS) & FW_INTR_STATUS_MASK);
--- 3608,3634 ----
* Just triggers the mailbox command an waits for the completion.
* Also expects that There is nothing else going on and we will only
* get back a mailbox completion from firmware.
* ---DOES NOT CLEAR INTERRUPT---
* Used only from the code path originating from
! * qlt_reset_chip()
*/
static fct_status_t
qlt_raw_mailbox_command(qlt_state_t *qlt)
{
int cntr = 0;
uint32_t status;
+ fct_local_port_t *port = qlt->qlt_port;
REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
+ retry_raw:;
while ((REG_RD32(qlt, REG_INTR_STATUS) & RISC_PCI_INTR_REQUEST) == 0) {
cntr++;
! if (cntr == 3000) {
! EL(qlt, "polling exhausted, dump fw now..\n");
! (void) qlt_firmware_dump(port,
! (stmf_state_change_info_t *)NULL);
return (QLT_MAILBOX_STUCK);
}
delay(drv_usectohz(10000));
}
status = (REG_RD32(qlt, REG_RISC_STATUS) & FW_INTR_STATUS_MASK);
*** 2442,2454 ****
--- 3639,3682 ----
(status == MBX_CMD_NOT_SUCCESSFUL)) {
uint16_t mbox0 = REG_RD16(qlt, REG_MBOX(0));
if (mbox0 == QLT_MBX_CMD_SUCCESS) {
return (QLT_SUCCESS);
} else {
+ EL(qlt, "mbx cmd failed, dump fw now..\n");
+ (void) qlt_firmware_dump(port,
+ (stmf_state_change_info_t *)NULL);
return (QLT_MBOX_FAILED | mbox0);
}
+ } else if (status == ASYNC_EVENT) {
+ uint16_t mbox0, mbox1, mbox2, mbox3;
+ uint16_t mbox4, mbox5, mbox6, mbox7;
+
+ mbox0 = REG_RD16(qlt, REG_MBOX(0));
+ mbox1 = REG_RD16(qlt, REG_MBOX(1));
+ mbox2 = REG_RD16(qlt, REG_MBOX(2));
+ mbox3 = REG_RD16(qlt, REG_MBOX(3));
+ mbox4 = REG_RD16(qlt, REG_MBOX(4));
+ mbox5 = REG_RD16(qlt, REG_MBOX(5));
+ mbox6 = REG_RD16(qlt, REG_MBOX(6));
+ mbox7 = REG_RD16(qlt, REG_MBOX(7));
+
+ cmn_err(CE_NOTE, "!qlt(%d): Async event %x mb1=%x mb2=%x"
+ "mb3=%x mb4=%x mb5=%x mb6=%x mb7=%x",
+ qlt->instance, mbox0, mbox1, mbox2, mbox3,
+ mbox4, mbox5, mbox6, mbox7);
+ if (mbox0 == 0x8002) {
+ (void) qlt_firmware_dump(port,
+ (stmf_state_change_info_t *)NULL);
+ return (QLT_UNEXPECTED_RESPONSE);
+ } else {
+ REG_WR32(qlt,
+ REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ cntr = 0;
+ goto retry_raw;
}
+ }
+
/* This is unexpected, dump a message */
cmn_err(CE_WARN, "qlt(%d): Unexpect intr status %llx",
ddi_get_instance(qlt->dip), (unsigned long long)status);
return (QLT_UNEXPECTED_RESPONSE);
}
*** 2499,2515 ****
static fct_status_t
qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp)
{
int retries;
int i;
! char info[QLT_INFO_LEN];
if (curthread->t_flag & T_INTR_THREAD) {
ASSERT(0);
return (QLT_MBOX_FAILED);
}
mutex_enter(&qlt->mbox_lock);
/* See if mailboxes are still uninitialized */
if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) {
mutex_exit(&qlt->mbox_lock);
return (QLT_MBOX_NOT_INITIALIZED);
--- 3727,3746 ----
static fct_status_t
qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp)
{
int retries;
int i;
! char info[80];
if (curthread->t_flag & T_INTR_THREAD) {
ASSERT(0);
return (QLT_MBOX_FAILED);
}
+ EL(qlt, "mailbox:[0]=%xh [1]=%xh\n",
+ mcp->to_fw[0], mcp->to_fw[1]);
+
mutex_enter(&qlt->mbox_lock);
/* See if mailboxes are still uninitialized */
if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) {
mutex_exit(&qlt->mbox_lock);
return (QLT_MBOX_NOT_INITIALIZED);
*** 2539,2551 ****
qlt_mbox_wait_loop:;
/* Wait for mailbox command completion */
if (cv_timedwait(&qlt->mbox_cv, &qlt->mbox_lock, ddi_get_lbolt()
+ drv_usectohz(MBOX_TIMEOUT)) < 0) {
! (void) snprintf(info, sizeof (info),
! "qlt_mailbox_command: qlt-%p, "
"cmd-0x%02X timed out", (void *)qlt, qlt->mcp->to_fw[0]);
qlt->mcp = NULL;
qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
mutex_exit(&qlt->mbox_lock);
/*
--- 3770,3782 ----
qlt_mbox_wait_loop:;
/* Wait for mailbox command completion */
if (cv_timedwait(&qlt->mbox_cv, &qlt->mbox_lock, ddi_get_lbolt()
+ drv_usectohz(MBOX_TIMEOUT)) < 0) {
! (void) snprintf(info, 80, "qlt_mailbox_command: qlt-%p, "
"cmd-0x%02X timed out", (void *)qlt, qlt->mcp->to_fw[0]);
+ info[79] = 0;
qlt->mcp = NULL;
qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
mutex_exit(&qlt->mbox_lock);
/*
*** 2569,2596 ****
/* MBox command completed. Clear state, retuen based on mbox 0 */
/* Mailboxes are already loaded by interrupt routine */
qlt->mbox_io_state = MBOX_STATE_READY;
mutex_exit(&qlt->mbox_lock);
! if (mcp->from_fw[0] != QLT_MBX_CMD_SUCCESS)
return (QLT_MBOX_FAILED | mcp->from_fw[0]);
return (QLT_SUCCESS);
}
/*
* **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
*/
/* ARGSUSED */
static uint_t
qlt_isr(caddr_t arg, caddr_t arg2)
{
qlt_state_t *qlt = (qlt_state_t *)arg;
uint32_t risc_status, intr_type;
int i;
int intr_loop_count;
! char info[QLT_INFO_LEN];
risc_status = REG_RD32(qlt, REG_RISC_STATUS);
if (!mutex_tryenter(&qlt->intr_lock)) {
/*
* Normally we will always get this lock. If tryenter is
--- 3800,4244 ----
/* MBox command completed. Clear state, retuen based on mbox 0 */
/* Mailboxes are already loaded by interrupt routine */
qlt->mbox_io_state = MBOX_STATE_READY;
mutex_exit(&qlt->mbox_lock);
! if (mcp->from_fw[0] != QLT_MBX_CMD_SUCCESS) {
! EL(qlt, "fw[0] = %xh\n", mcp->from_fw[0]);
! if ((mcp->from_fw[0] != 0x4005) &&
! (mcp->from_fw[1] != 0x7)) {
! (void) qlt_firmware_dump(qlt->qlt_port,
! (stmf_state_change_info_t *)NULL);
! }
return (QLT_MBOX_FAILED | mcp->from_fw[0]);
+ }
return (QLT_SUCCESS);
}
+ clock_t qlt_next_invalid_msg = 0;
+ int qlt_invalid_idx_cnt = 0;
+
/*
* **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
*/
/* ARGSUSED */
static uint_t
+ qlt_msix_resp_handler(caddr_t arg, caddr_t arg2)
+ {
+ qlt_state_t *qlt = (qlt_state_t *)arg;
+ uint32_t risc_status;
+ uint16_t qi = 0;
+ clock_t now;
+
+ risc_status = REG_RD32(qlt, REG_RISC_STATUS);
+ if (qlt->qlt_mq_enabled) {
+ /* XXX: */
+ /* qi = (uint16_t)((unsigned long)arg2); */
+ qi = (uint16_t)(risc_status >> 16);
+ if (qi >= MQ_MAX_QUEUES) {
+ /*
+ * Two customers have reported panics in the call to
+ * mutex_enter below. Analysis showed the address passed
+ * in could only occur if 'qi' had a value of 0x4000.
+ * We'll ignore the upper bits and see if an index which
+ * at least within the range of possible produces some
+ * sane results.
+ */
+ now = ddi_get_lbolt();
+ if (now > qlt_next_invalid_msg) {
+ /*
+ * Since this issue has never been seen in the
+ * lab it's unknown if once this bit gets set
+ * does it remain until the next hardware reset?
+ * If so, we don't want to flood the message
+ * buffer or make it difficult to reboot the
+ * system.
+ */
+ qlt_next_invalid_msg = now +
+ drv_usectohz(MICROSEC * 10);
+ cmn_err(CE_NOTE, "QLT: hardware reporting "
+ "invalid index: 0x%x", qi);
+ }
+ qi &= MQ_MAX_QUEUES_MASK;
+ qlt_invalid_idx_cnt++;
+ }
+
+ mutex_enter(&qlt->mq_resp[qi].mq_lock);
+ if (!qlt->qlt_intr_enabled) {
+ /*
+ * No further interrupt since intr disabled.
+ */
+ REG_WR32(qlt, REG_HCCR,
+ HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ mutex_exit(&qlt->mq_resp[qi].mq_lock);
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ qlt->mq_resp[qi].mq_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
+
+ qlt_handle_resp_queue_update(qlt, qi);
+ mutex_exit(&qlt->mq_resp[qi].mq_lock);
+ } else {
+ mutex_enter(&qlt->intr_lock);
+ if (!qlt->qlt_intr_enabled) {
+ /*
+ * No further interrupt since intr disabled.
+ */
+ REG_WR32(qlt, REG_HCCR,
+ HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ mutex_exit(&qlt->intr_lock);
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ qlt->atio_ndx_from_fw =
+ (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
+ qlt_handle_atio_queue_update(qlt);
+
+ qlt->mq_resp[qi].mq_ndx_from_fw = risc_status >> 16;
+ qlt_handle_resp_queue_update(qlt, qi);
+ mutex_exit(&qlt->intr_lock);
+ }
+
+ if (risc_status & BIT_15) {
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ }
+ return (DDI_INTR_CLAIMED);
+ }
+
+
+ /*
+ * **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
+ */
+ /* ARGSUSED */
+ static uint_t
+ qlt_msix_default_handler(caddr_t arg, caddr_t arg2)
+ {
+ qlt_state_t *qlt = (qlt_state_t *)arg;
+ uint32_t risc_status, intr_type;
+ int i;
+ char info[80];
+
+ risc_status = REG_RD32(qlt, REG_RISC_STATUS);
+ if (!mutex_tryenter(&qlt->intr_lock)) {
+ /*
+ * Normally we will always get this lock. If tryenter is
+ * failing then it means that driver is trying to do
+ * some cleanup and is masking the intr but some intr
+ * has sneaked in between. See if our device has generated
+ * this intr. If so then wait a bit and return claimed.
+ * If not then return claimed if this is the 1st instance
+ * of a interrupt after driver has grabbed the lock.
+ */
+ if ((risc_status & BIT_15) == 0) {
+ return (DDI_INTR_UNCLAIMED);
+ } else {
+ /* try again */
+ drv_usecwait(10);
+ if (!mutex_tryenter(&qlt->intr_lock)) {
+ /* really bad! */
+ return (DDI_INTR_CLAIMED);
+ }
+ }
+ }
+ if (((risc_status & BIT_15) == 0) ||
+ (qlt->qlt_intr_enabled == 0)) {
+ /*
+ * This might be a pure coincedence that we are operating
+ * in a interrupt disabled mode and another device
+ * sharing the interrupt line has generated an interrupt
+ * while an interrupt from our device might be pending. Just
+ * ignore it and let the code handling the interrupt
+ * disabled mode handle it.
+ */
+ mutex_exit(&qlt->intr_lock);
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ /* REG_WR32(qlt, REG_INTR_CTRL, 0); */
+
+ /* check for risc pause - unlikely */
+ if (risc_status & BIT_8) {
+ uint32_t hccsr;
+
+ hccsr = REG_RD32(qlt, REG_HCCR);
+ EL(qlt, "Risc Pause status=%xh hccsr=%x\n",
+ risc_status, hccsr);
+ cmn_err(CE_WARN, "qlt(%d): Risc Pause %08x hccsr:%x",
+ qlt->instance, risc_status, hccsr);
+ (void) snprintf(info, 80, "Risc Pause %08x hccsr:%x",
+ risc_status, hccsr);
+ info[79] = 0;
+ (void) fct_port_shutdown(qlt->qlt_port,
+ STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
+ STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
+ }
+
+ /* check most likely types first */
+ intr_type = risc_status & 0xff;
+ if (intr_type == 0x1D) {
+ qlt->atio_ndx_from_fw =
+ (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
+ qlt_handle_atio_queue_update(qlt);
+ qlt->mq_resp[0].mq_ndx_from_fw = risc_status >> 16;
+ qlt_handle_resp_queue_update(qlt, 0);
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ } else if (intr_type == 0x1C) {
+ qlt->atio_ndx_from_fw = (uint16_t)(risc_status >> 16);
+ qlt_handle_atio_queue_update(qlt);
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ } else if (intr_type == 0x1E) {
+ /* 83xx */
+ qlt->atio_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt, MQBAR_ATIO_IN);
+ qlt_handle_atio_queue_update(qlt);
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ } else if (intr_type == 0x13) {
+ uint16_t qi;
+
+ qlt->atio_ndx_from_fw =
+ (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
+ qlt_handle_atio_queue_update(qlt);
+
+ if (qlt->qlt_mq_enabled) {
+ qi = (uint16_t)(risc_status >> 16);
+ qlt->mq_resp[qi].mq_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
+ /* FIX THIS to be optional */
+ REG_WR32(qlt, REG_HCCR,
+ HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ } else {
+ qi = 0;
+ REG_WR32(qlt, REG_HCCR,
+ HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ qlt->mq_resp[qi].mq_ndx_from_fw = risc_status >> 16;
+ }
+ qlt_handle_resp_queue_update(qlt, qi);
+
+ } else if (intr_type == 0x14) {
+ uint16_t qi = (uint16_t)(risc_status >> 16);
+
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ qlt->atio_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt, MQBAR_ATIO_IN);
+ } else {
+ qlt->atio_ndx_from_fw = (uint16_t)
+ REG_RD32(qlt, REG_ATIO_IN_PTR);
+ }
+ qlt_handle_atio_queue_update(qlt);
+
+ qlt->mq_resp[qi].mq_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
+ qlt_handle_resp_queue_update(qlt, qi);
+
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+
+ } else if (intr_type == 0x12) {
+ uint16_t code, mbox1, mbox2, mbox3, mbox4, mbox5, mbox6;
+
+ REG_WR32(qlt, REG_INTR_CTRL, 0);
+
+ code = (uint16_t)(risc_status >> 16);
+ mbox1 = REG_RD16(qlt, REG_MBOX(1));
+ mbox2 = REG_RD16(qlt, REG_MBOX(2));
+ mbox3 = REG_RD16(qlt, REG_MBOX(3));
+ mbox4 = REG_RD16(qlt, REG_MBOX(4));
+ mbox5 = REG_RD16(qlt, REG_MBOX(5));
+ mbox6 = REG_RD16(qlt, REG_MBOX(6));
+
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ EL(qlt, "Async event: %x mb1=%x mb2=%x,"
+ " mb3=%x, mb4=%x, mb5=%x, mb6=%x", code, mbox1, mbox2,
+ mbox3, mbox4, mbox5, mbox6);
+ stmf_trace(qlt->qlt_port_alias, "Async event: %x mb1=%x mb2=%x,"
+ " mb3=%x, mb4=%x, mb5=%x, mb6=%x", code, mbox1, mbox2,
+ mbox3, mbox4, mbox5, mbox6);
+ cmn_err(CE_NOTE, "!qlt(%d): Async event %x mb1=%x mb2=%x,"
+ " mb3=%x, mb4=%x, mb5=%x, mb6=%x", qlt->instance, code,
+ mbox1, mbox2, mbox3, mbox4, mbox5, mbox6);
+
+ if ((code == 0x8030) || (code == 0x8010) || (code == 0x8013)) {
+ if (qlt->qlt_link_up) {
+ fct_handle_event(qlt->qlt_port,
+ FCT_EVENT_LINK_RESET, 0, 0);
+ }
+ } else if (code == 0x8012) {
+ qlt->qlt_link_up = 0;
+ fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_DOWN,
+ 0, 0);
+ } else if (code == 0x8014) {
+ if (mbox1 == 0xffff) { /* global event */
+ uint8_t reason_code;
+
+ reason_code = (uint8_t)(mbox3 >> 8);
+
+ switch (reason_code) {
+ case 0x1d: /* FIP Clear Virtual Link received */
+ case 0x1a: /* received FLOGO */
+ case 0x1c: /* FCF configuration changed */
+ case 0x1e: /* FKA timeout */
+ if (mbox2 == 7) {
+ qlt->qlt_link_up = 0;
+ fct_handle_event(qlt->qlt_port,
+ FCT_EVENT_LINK_DOWN, 0, 0);
+ }
+ break;
+ case 0x12:
+ if (mbox2 == 4) {
+ qlt->qlt_link_up = 1;
+ fct_handle_event(qlt->qlt_port,
+ FCT_EVENT_LINK_UP, 0, 0);
+ stmf_trace(qlt->qlt_port_alias,
+ "SNS login and SCR done");
+ }
+ break;
+ case 0:
+ if ((mbox2 == 6) &&
+ (!qlt->qlt_link_up)) {
+ qlt->qlt_link_up = 1;
+ fct_handle_event(qlt->qlt_port,
+ FCT_EVENT_LINK_UP, 0, 0);
+ stmf_trace(qlt->qlt_port_alias,
+ "Link reinitialised");
+ }
+ break;
+ default:
+ stmf_trace(qlt->qlt_port_alias,
+ "AEN ignored");
+ break;
+ }
+ }
+ } else if (code == 0x8011) {
+ switch (mbox1) {
+ case 0: qlt->link_speed = PORT_SPEED_1G;
+ break;
+ case 1: qlt->link_speed = PORT_SPEED_2G;
+ break;
+ case 3: qlt->link_speed = PORT_SPEED_4G;
+ break;
+ case 4: qlt->link_speed = PORT_SPEED_8G;
+ break;
+ case 5: qlt->link_speed = PORT_SPEED_16G;
+ break;
+ case 0x13: qlt->link_speed = PORT_SPEED_10G;
+ break;
+ default:
+ qlt->link_speed = PORT_SPEED_UNKNOWN;
+ }
+ qlt->qlt_link_up = 1;
+ fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_UP,
+ 0, 0);
+ } else if ((code == 0x8002) || (code == 0x8003) ||
+ (code == 0x8004) || (code == 0x8005)) {
+ (void) snprintf(info, 80,
+ "Got %04x, mb1=%x mb2=%x mb5=%x mb6=%x",
+ code, mbox1, mbox2, mbox5, mbox6);
+ info[79] = 0;
+ (void) fct_port_shutdown(qlt->qlt_port,
+ STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
+ STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
+ } else if (code == 0x800F) {
+ (void) snprintf(info, 80,
+ "Got 800F, mb1=%x mb2=%x mb3=%x",
+ mbox1, mbox2, mbox3);
+
+ if (mbox1 != 1) {
+ /* issue "verify fw" */
+ qlt_verify_fw(qlt);
+ }
+ } else if (code == 0x8101) {
+ (void) snprintf(info, 80,
+ "IDC Req Rcvd:%04x, mb1=%x mb2=%x mb3=%x",
+ code, mbox1, mbox2, mbox3);
+ info[79] = 0;
+
+ /* check if "ACK" is required (timeout != 0) */
+ if (mbox1 & 0x0f00) {
+ caddr_t req;
+
+ /*
+ * Ack the request (queue work to do it?)
+ * using a mailbox iocb
+ * (Only Queue #0 allowed)
+ */
+ mutex_enter(&qlt->mq_req[0].mq_lock);
+ req = qlt_get_req_entries(qlt, 1, 0);
+ if (req) {
+ bzero(req, IOCB_SIZE);
+ req[0] = 0x39; req[1] = 1;
+ QMEM_WR16(qlt, req+8, 0x101);
+ QMEM_WR16(qlt, req+10, mbox1);
+ QMEM_WR16(qlt, req+12, mbox2);
+ QMEM_WR16(qlt, req+14, mbox3);
+ QMEM_WR16(qlt, req+16, mbox4);
+ QMEM_WR16(qlt, req+18, mbox5);
+ QMEM_WR16(qlt, req+20, mbox6);
+ qlt_submit_req_entries(qlt, 1, 0);
+ } else {
+ (void) snprintf(info, 80,
+ "IDC ACK failed");
+ info[79] = 0;
+ }
+ mutex_exit(&qlt->mq_req[0].mq_lock);
+ }
+ } else {
+ stmf_trace(qlt->qlt_port_alias,
+ "Async event: 0x%x ignored",
+ code);
+ }
+ REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
+ } else if ((intr_type == 0x10) || (intr_type == 0x11)) {
+ /* Handle mailbox completion */
+ mutex_enter(&qlt->mbox_lock);
+ if (qlt->mbox_io_state != MBOX_STATE_CMD_RUNNING) {
+ cmn_err(CE_WARN, "qlt(%d): mailbox completion received"
+ " when driver wasn't waiting for it %d",
+ qlt->instance, qlt->mbox_io_state);
+ } else {
+ for (i = 0; i < MAX_MBOXES; i++) {
+ if (qlt->mcp->from_fw_mask &
+ (((uint32_t)1) << i)) {
+ qlt->mcp->from_fw[i] =
+ REG_RD16(qlt, REG_MBOX(i));
+ }
+ }
+ qlt->mbox_io_state = MBOX_STATE_CMD_DONE;
+ }
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ cv_broadcast(&qlt->mbox_cv);
+ mutex_exit(&qlt->mbox_lock);
+ } else {
+ cmn_err(CE_WARN, "qlt(%d): Unknown intr type 0x%x",
+ qlt->instance, intr_type);
+ stmf_trace(qlt->qlt_port_alias,
+ "%s: Unknown intr type 0x%x [%x]",
+ __func__, intr_type, risc_status);
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ }
+
+ /* REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR); */
+ mutex_exit(&qlt->intr_lock);
+
+ return (DDI_INTR_CLAIMED);
+ }
+
+ /*
+ * **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
+ */
+ /* ARGSUSED */
+ static uint_t
qlt_isr(caddr_t arg, caddr_t arg2)
{
qlt_state_t *qlt = (qlt_state_t *)arg;
uint32_t risc_status, intr_type;
int i;
int intr_loop_count;
! char info[80];
risc_status = REG_RD32(qlt, REG_RISC_STATUS);
if (!mutex_tryenter(&qlt->intr_lock)) {
/*
* Normally we will always get this lock. If tryenter is
*** 2624,2634 ****
mutex_exit(&qlt->intr_lock);
return (DDI_INTR_UNCLAIMED);
}
/*
! * XXX take care for MSI case. disable intrs
* Its gonna be complicated because of the max iterations.
* as hba will have posted the intr which did not go on PCI
* but we did not service it either because of max iterations.
* Maybe offload the intr on a different thread.
*/
--- 4272,4282 ----
mutex_exit(&qlt->intr_lock);
return (DDI_INTR_UNCLAIMED);
}
/*
! * XXX take care for MSI-X case. disable intrs
* Its gonna be complicated because of the max iterations.
* as hba will have posted the intr which did not go on PCI
* but we did not service it either because of max iterations.
* Maybe offload the intr on a different thread.
*/
*** 2641,2674 ****
/* check for risc pause */
if (risc_status & BIT_8) {
EL(qlt, "Risc Pause status=%xh\n", risc_status);
cmn_err(CE_WARN, "qlt(%d): Risc Pause %08x",
qlt->instance, risc_status);
! (void) snprintf(info, sizeof (info), "Risc Pause %08x",
! risc_status);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
}
/* First check for high performance path */
intr_type = risc_status & 0xff;
if (intr_type == 0x1D) {
! qlt->atio_ndx_from_fw = (uint16_t)
! REG_RD32(qlt, REG_ATIO_IN_PTR);
! REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
! qlt->resp_ndx_from_fw = risc_status >> 16;
qlt_handle_atio_queue_update(qlt);
! qlt_handle_resp_queue_update(qlt);
} else if (intr_type == 0x1C) {
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
qlt->atio_ndx_from_fw = (uint16_t)(risc_status >> 16);
qlt_handle_atio_queue_update(qlt);
} else if (intr_type == 0x13) {
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
! qlt->resp_ndx_from_fw = risc_status >> 16;
! qlt_handle_resp_queue_update(qlt);
} else if (intr_type == 0x12) {
uint16_t code = (uint16_t)(risc_status >> 16);
uint16_t mbox1 = REG_RD16(qlt, REG_MBOX(1));
uint16_t mbox2 = REG_RD16(qlt, REG_MBOX(2));
uint16_t mbox3 = REG_RD16(qlt, REG_MBOX(3));
--- 4289,4375 ----
/* check for risc pause */
if (risc_status & BIT_8) {
EL(qlt, "Risc Pause status=%xh\n", risc_status);
cmn_err(CE_WARN, "qlt(%d): Risc Pause %08x",
qlt->instance, risc_status);
! (void) snprintf(info, 80, "Risc Pause %08x", risc_status);
! info[79] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
}
/* First check for high performance path */
intr_type = risc_status & 0xff;
if (intr_type == 0x1D) {
!
! /* process the atio queue first */
! qlt->atio_ndx_from_fw =
! (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
qlt_handle_atio_queue_update(qlt);
!
! /* process the response queue next */
! qlt->mq_resp[0].mq_ndx_from_fw =
! (uint16_t)REG_RD32(qlt, REG_RESP_IN_PTR);
! qlt_handle_resp_queue_update(qlt, 0);
! REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
!
} else if (intr_type == 0x1C) {
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
qlt->atio_ndx_from_fw = (uint16_t)(risc_status >> 16);
qlt_handle_atio_queue_update(qlt);
+ } else if (intr_type == 0x1E) {
+ /* 83xx Atio Queue update */
+ qlt->atio_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt, MQBAR_ATIO_IN);
+ qlt_handle_atio_queue_update(qlt);
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
} else if (intr_type == 0x13) {
+ uint16_t qi;
+
+ qlt->atio_ndx_from_fw =
+ (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
+ qlt_handle_atio_queue_update(qlt);
+
+ if (qlt->qlt_mq_enabled) {
+ qi = (uint16_t)(risc_status >> 16);
+ qlt->mq_resp[0].mq_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
+ /* FIX THIS to be optional */
+ REG_WR32(qlt, REG_HCCR,
+ HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ } else {
+ qi = 0;
+ REG_WR32(qlt, REG_HCCR,
+ HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ qlt->mq_resp[qi].mq_ndx_from_fw = risc_status >> 16;
+ REG_WR32(qlt, REG_HCCR,
+ HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ }
+ qlt_handle_resp_queue_update(qlt, qi);
+
+ } else if (intr_type == 0x14) {
+ /* MQ */
+ uint16_t qi = 0;
+
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ qlt->atio_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt, MQBAR_ATIO_IN);
+ } else {
+ qi = (uint16_t)(risc_status >> 16);
+ qlt->atio_ndx_from_fw = (uint16_t)
+ REG_RD32(qlt, REG_ATIO_IN_PTR);
+ }
+ qlt_handle_atio_queue_update(qlt);
+
+ qlt->mq_resp[qi].mq_ndx_from_fw =
+ (uint16_t)MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
+ qlt_handle_resp_queue_update(qlt, qi);
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
!
} else if (intr_type == 0x12) {
uint16_t code = (uint16_t)(risc_status >> 16);
uint16_t mbox1 = REG_RD16(qlt, REG_MBOX(1));
uint16_t mbox2 = REG_RD16(qlt, REG_MBOX(2));
uint16_t mbox3 = REG_RD16(qlt, REG_MBOX(3));
*** 2675,2689 ****
uint16_t mbox4 = REG_RD16(qlt, REG_MBOX(4));
uint16_t mbox5 = REG_RD16(qlt, REG_MBOX(5));
uint16_t mbox6 = REG_RD16(qlt, REG_MBOX(6));
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
! stmf_trace(qlt->qlt_port_alias, "Async event %x mb1=%x mb2=%x,"
! " mb3=%x, mb5=%x, mb6=%x", code, mbox1, mbox2, mbox3,
mbox5, mbox6);
! EL(qlt, "Async event %x mb1=%x mb2=%x, mb3=%x, mb5=%x, mb6=%x",
! code, mbox1, mbox2, mbox3, mbox5, mbox6);
if ((code == 0x8030) || (code == 0x8010) || (code == 0x8013)) {
if (qlt->qlt_link_up) {
fct_handle_event(qlt->qlt_port,
FCT_EVENT_LINK_RESET, 0, 0);
--- 4376,4394 ----
uint16_t mbox4 = REG_RD16(qlt, REG_MBOX(4));
uint16_t mbox5 = REG_RD16(qlt, REG_MBOX(5));
uint16_t mbox6 = REG_RD16(qlt, REG_MBOX(6));
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
! EL(qlt, "Async event %x mb1=%x, mb2=%x, mb3=%x, mb4=%x, "
! "mb5=%x, mb6=%x\n", code, mbox1, mbox2, mbox3, mbox4,
mbox5, mbox6);
! stmf_trace(qlt->qlt_port_alias, "Async event %x mb1=%x mb2=%x,"
! " mb3=%x, mb4=%x, mb5=%x, mb6=%x", code, mbox1, mbox2,
! mbox3, mbox4, mbox5, mbox6);
! cmn_err(CE_NOTE, "!qlt(%d): Async event %x mb1=%x mb2=%x,"
! " mb3=%x, mb4=%x, mb5=%x, mb6=%x", qlt->instance, code,
! mbox1, mbox2, mbox3, mbox4, mbox5, mbox6);
if ((code == 0x8030) || (code == 0x8010) || (code == 0x8013)) {
if (qlt->qlt_link_up) {
fct_handle_event(qlt->qlt_port,
FCT_EVENT_LINK_RESET, 0, 0);
*** 2690,2699 ****
--- 4395,4446 ----
}
} else if (code == 0x8012) {
qlt->qlt_link_up = 0;
fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_DOWN,
0, 0);
+ } else if (code == 0x8014) {
+ if (mbox1 == 0xffff) { /* global event */
+ uint8_t reason_code;
+
+ reason_code = (uint8_t)(mbox3 >> 8);
+
+ switch (reason_code) {
+ case 0x1d: /* FIP Clear Virtual Link received */
+ case 0x1a: /* received FLOGO */
+ case 0x1c: /* FCF configuration changed */
+ case 0x1e: /* FKA timeout */
+ if (mbox2 == 7) {
+ qlt->qlt_link_up = 0;
+ fct_handle_event(qlt->qlt_port,
+ FCT_EVENT_LINK_DOWN, 0, 0);
+ }
+ break;
+ case 0x12:
+ if (mbox2 == 4) {
+ qlt->qlt_link_up = 1;
+ fct_handle_event(qlt->qlt_port,
+ FCT_EVENT_LINK_UP, 0, 0);
+ stmf_trace(qlt->qlt_port_alias,
+ "SNS login and SCR done");
+ }
+ break;
+ case 0:
+ if ((mbox2 == 6) &&
+ (!qlt->qlt_link_up)) {
+ qlt->qlt_link_up = 1;
+ fct_handle_event(qlt->qlt_port,
+ FCT_EVENT_LINK_UP, 0, 0);
+ stmf_trace(qlt->qlt_port_alias,
+ "Link reinitialised");
+ }
+ break;
+ default:
+ stmf_trace(qlt->qlt_port_alias,
+ "AEN ignored");
+ break;
+ }
+ }
} else if (code == 0x8011) {
switch (mbox1) {
case 0: qlt->link_speed = PORT_SPEED_1G;
break;
case 1: qlt->link_speed = PORT_SPEED_2G;
*** 2700,2709 ****
--- 4447,4460 ----
break;
case 3: qlt->link_speed = PORT_SPEED_4G;
break;
case 4: qlt->link_speed = PORT_SPEED_8G;
break;
+ case 5: qlt->link_speed = PORT_SPEED_16G;
+ break;
+ case 6: qlt->link_speed = PORT_SPEED_32G;
+ break;
case 0x13: qlt->link_speed = PORT_SPEED_10G;
break;
default:
qlt->link_speed = PORT_SPEED_UNKNOWN;
}
*** 2710,2749 ****
qlt->qlt_link_up = 1;
fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_UP,
0, 0);
} else if ((code == 0x8002) || (code == 0x8003) ||
(code == 0x8004) || (code == 0x8005)) {
! (void) snprintf(info, sizeof (info),
"Got %04x, mb1=%x mb2=%x mb5=%x mb6=%x",
code, mbox1, mbox2, mbox5, mbox6);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
} else if (code == 0x800F) {
! (void) snprintf(info, sizeof (info),
"Got 800F, mb1=%x mb2=%x mb3=%x",
mbox1, mbox2, mbox3);
if (mbox1 != 1) {
/* issue "verify fw" */
qlt_verify_fw(qlt);
}
} else if (code == 0x8101) {
! (void) snprintf(info, sizeof (info),
"IDC Req Rcvd:%04x, mb1=%x mb2=%x mb3=%x",
code, mbox1, mbox2, mbox3);
/* check if "ACK" is required (timeout != 0) */
if (mbox1 & 0x0f00) {
caddr_t req;
/*
* Ack the request (queue work to do it?)
! * using a mailbox iocb
*/
! mutex_enter(&qlt->req_lock);
! req = qlt_get_req_entries(qlt, 1);
if (req) {
bzero(req, IOCB_SIZE);
req[0] = 0x39; req[1] = 1;
QMEM_WR16(qlt, req+8, 0x101);
QMEM_WR16(qlt, req+10, mbox1);
--- 4461,4502 ----
qlt->qlt_link_up = 1;
fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_UP,
0, 0);
} else if ((code == 0x8002) || (code == 0x8003) ||
(code == 0x8004) || (code == 0x8005)) {
! (void) snprintf(info, 80,
"Got %04x, mb1=%x mb2=%x mb5=%x mb6=%x",
code, mbox1, mbox2, mbox5, mbox6);
+ info[79] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
} else if (code == 0x800F) {
! (void) snprintf(info, 80,
"Got 800F, mb1=%x mb2=%x mb3=%x",
mbox1, mbox2, mbox3);
if (mbox1 != 1) {
/* issue "verify fw" */
qlt_verify_fw(qlt);
}
} else if (code == 0x8101) {
! (void) snprintf(info, 80,
"IDC Req Rcvd:%04x, mb1=%x mb2=%x mb3=%x",
code, mbox1, mbox2, mbox3);
+ info[79] = 0;
/* check if "ACK" is required (timeout != 0) */
if (mbox1 & 0x0f00) {
caddr_t req;
/*
* Ack the request (queue work to do it?)
! * using a mailbox iocb (only Queue 0 allowed)
*/
! mutex_enter(&qlt->mq_req[0].mq_lock);
! req = qlt_get_req_entries(qlt, 1, 0);
if (req) {
bzero(req, IOCB_SIZE);
req[0] = 0x39; req[1] = 1;
QMEM_WR16(qlt, req+8, 0x101);
QMEM_WR16(qlt, req+10, mbox1);
*** 2750,2765 ****
QMEM_WR16(qlt, req+12, mbox2);
QMEM_WR16(qlt, req+14, mbox3);
QMEM_WR16(qlt, req+16, mbox4);
QMEM_WR16(qlt, req+18, mbox5);
QMEM_WR16(qlt, req+20, mbox6);
! qlt_submit_req_entries(qlt, 1);
} else {
! (void) snprintf(info, sizeof (info),
"IDC ACK failed");
}
! mutex_exit(&qlt->req_lock);
}
}
} else if ((intr_type == 0x10) || (intr_type == 0x11)) {
/* Handle mailbox completion */
mutex_enter(&qlt->mbox_lock);
--- 4503,4519 ----
QMEM_WR16(qlt, req+12, mbox2);
QMEM_WR16(qlt, req+14, mbox3);
QMEM_WR16(qlt, req+16, mbox4);
QMEM_WR16(qlt, req+18, mbox5);
QMEM_WR16(qlt, req+20, mbox6);
! qlt_submit_req_entries(qlt, 1, 0);
} else {
! (void) snprintf(info, 80,
"IDC ACK failed");
+ info[79] = 0;
}
! mutex_exit(&qlt->mq_req[0].mq_lock);
}
}
} else if ((intr_type == 0x10) || (intr_type == 0x11)) {
/* Handle mailbox completion */
mutex_enter(&qlt->mbox_lock);
*** 2781,2803 ****
cv_broadcast(&qlt->mbox_cv);
mutex_exit(&qlt->mbox_lock);
} else {
cmn_err(CE_WARN, "qlt(%d): Unknown intr type 0x%x",
qlt->instance, intr_type);
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
}
(void) REG_RD32(qlt, REG_HCCR); /* PCI Posting */
risc_status = REG_RD32(qlt, REG_RISC_STATUS);
if ((risc_status & BIT_15) &&
(++intr_loop_count < QLT_MAX_ITERATIONS_PER_INTR)) {
goto intr_again;
}
-
REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
-
mutex_exit(&qlt->intr_lock);
return (DDI_INTR_CLAIMED);
}
/* **************** NVRAM Functions ********************** */
--- 4535,4565 ----
cv_broadcast(&qlt->mbox_cv);
mutex_exit(&qlt->mbox_lock);
} else {
cmn_err(CE_WARN, "qlt(%d): Unknown intr type 0x%x",
qlt->instance, intr_type);
+ stmf_trace(qlt->qlt_port_alias,
+ "%s: Unknown intr type 0x%x [%x]",
+ __func__, intr_type, risc_status);
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
}
(void) REG_RD32(qlt, REG_HCCR); /* PCI Posting */
+
+ if ((qlt->intr_flags & QLT_INTR_MSIX) == 0) {
risc_status = REG_RD32(qlt, REG_RISC_STATUS);
if ((risc_status & BIT_15) &&
(++intr_loop_count < QLT_MAX_ITERATIONS_PER_INTR)) {
goto intr_again;
}
REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
mutex_exit(&qlt->intr_lock);
+ } else {
+ mutex_exit(&qlt->intr_lock);
+ REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
+ }
+
return (DDI_INTR_CLAIMED);
}
/* **************** NVRAM Functions ********************** */
*** 2839,2850 ****
uint32_t val, *ptr;
fct_status_t ret;
qlt_nvram_t *nv;
uint64_t empty_node_name = 0;
! if (qlt->qlt_81xx_chip) {
addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
QLT81_NVRAM_FUNC1_ADDR : QLT81_NVRAM_FUNC0_ADDR;
} else if (qlt->qlt_25xx_chip) {
addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
QLT25_NVRAM_FUNC1_ADDR : QLT25_NVRAM_FUNC0_ADDR;
} else {
--- 4601,4632 ----
uint32_t val, *ptr;
fct_status_t ret;
qlt_nvram_t *nv;
uint64_t empty_node_name = 0;
! if (qlt->qlt_27xx_chip) {
! int func;
!
! func = ((REG_RD32(qlt, REG_CTRL_STATUS) & 0x0000f000) >> 12);
! switch (func) {
! case 0: addr = QLT27_NVRAM_FUNC0_ADDR; break;
! case 1: addr = QLT27_NVRAM_FUNC1_ADDR; break;
! case 2: addr = QLT27_NVRAM_FUNC2_ADDR; break;
! case 3: addr = QLT27_NVRAM_FUNC3_ADDR; break;
! }
! } else if (qlt->qlt_83xx_chip) {
! if (qlt->qlt_fcoe_enabled) {
addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
+ QLT83FCOE_NVRAM_FUNC1_ADDR :
+ QLT83FCOE_NVRAM_FUNC0_ADDR;
+ } else {
+ addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
+ QLT83FC_NVRAM_FUNC1_ADDR :
+ QLT83FC_NVRAM_FUNC0_ADDR;
+ }
+ } else if (qlt->qlt_81xx_chip) {
+ addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
QLT81_NVRAM_FUNC1_ADDR : QLT81_NVRAM_FUNC0_ADDR;
} else if (qlt->qlt_25xx_chip) {
addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
QLT25_NVRAM_FUNC1_ADDR : QLT25_NVRAM_FUNC0_ADDR;
} else {
*** 2897,2906 ****
--- 4679,4909 ----
}
return (QLT_SUCCESS);
}
+ fct_status_t
+ qlt_read_vpd(qlt_state_t *qlt)
+ {
+ uint32_t index, addr, chksum;
+ uint32_t val, *ptr;
+ fct_status_t ret;
+
+ if (qlt->qlt_27xx_chip) {
+ int func;
+
+ func = ((REG_RD32(qlt, REG_CTRL_STATUS) & 0x0000f000) >> 12);
+ switch (func) {
+ case 0: addr = QLT27_VPD_FUNC0_ADDR; break;
+ case 1: addr = QLT27_VPD_FUNC1_ADDR; break;
+ case 2: addr = QLT27_VPD_FUNC2_ADDR; break;
+ case 3: addr = QLT27_VPD_FUNC3_ADDR; break;
+ }
+ } else if (qlt->qlt_83xx_chip) {
+ if (qlt->qlt_fcoe_enabled) {
+ addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
+ QLT83FCOE_VPD_FUNC1_ADDR :
+ QLT83FCOE_VPD_FUNC0_ADDR;
+ } else {
+ addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
+ QLT83FC_VPD_FUNC1_ADDR :
+ QLT83FC_VPD_FUNC0_ADDR;
+ }
+ } else if (qlt->qlt_81xx_chip) {
+ addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
+ QLT81_VPD_FUNC1_ADDR : QLT81_VPD_FUNC0_ADDR;
+ } else if (qlt->qlt_25xx_chip) {
+ addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
+ QLT25_VPD_FUNC1_ADDR : QLT25_VPD_FUNC0_ADDR;
+ } else {
+ addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
+ QLT24_VPD_FUNC1_ADDR : QLT24_VPD_FUNC0_ADDR;
+ }
+ mutex_enter(&qlt_global_lock);
+
+ /* Pause RISC. */
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE));
+ (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
+
+ /* Get VPD data and calculate checksum. */
+ ptr = (uint32_t *)qlt->vpd;
+ chksum = 0;
+ for (index = 0; index < QL_24XX_VPD_SIZE / 4; index++) {
+ ret = qlt_read_flash_word(qlt, addr++, &val);
+ if (ret != QLT_SUCCESS) {
+ EL(qlt, "qlt_read_flash_word, status=%llxh\n", ret);
+ mutex_exit(&qlt_global_lock);
+ return (ret);
+ }
+ chksum += val;
+ *ptr = LE_32(val);
+ ptr++;
+ }
+
+ /* Release RISC Pause */
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_PAUSE));
+ (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
+
+ mutex_exit(&qlt_global_lock);
+
+ return (QLT_SUCCESS);
+ }
+
+ fct_status_t
+ qlt_read_bfe(qlt_state_t *qlt, uint32_t in_addr, uint32_t *out_addr, uint32_t i)
+ {
+ uint32_t index;
+ uint32_t chksum;
+ fct_status_t ret = QLT_SUCCESS;
+ uint32_t val;
+ uint16_t dataoffset;
+ uint32_t *ptr;
+ uint32_t addr, addr0;
+ uint16_t length;
+
+ val = chksum = 0;
+ ptr = (uint32_t *)&qlt->rimage[i].header;
+
+ addr = in_addr;
+ addr0 = addr;
+
+ /* read rom header first */
+ for (index = 0; index < sizeof (qlt_rom_header_t)/4;
+ index ++) {
+ ret = qlt_read_flash_word(qlt, addr++, &val);
+ if (ret != QLT_SUCCESS) {
+ EL(qlt, "read flash, status=%llxh\n", ret);
+ return (ret);
+ }
+ chksum += val;
+ *ptr = LE_32(val);
+ ptr++;
+ }
+
+ /* check the signature */
+ if (qlt->rimage[i].header.signature[0] != PCI_HEADER0) {
+ EL(qlt, "hdr[%d] sig[1] [0] (%xh) (%xh) is wrong.\n",
+ i, qlt->rimage[i].header.signature[1],
+ qlt->rimage[i].header.signature[0]);
+ return (QLT_SUCCESS);
+ }
+
+ if ((qlt->rimage[i].header.signature[0] == PCI_HEADER0) &&
+ (qlt->rimage[i].header.signature[1] == PCI_HEADER1)) {
+ /* get dataoffset */
+ dataoffset = (qlt->rimage[i].header.dataoffset[1] |
+ qlt->rimage[i].header.dataoffset[0]);
+ EL(qlt, "dataoffset[0] = %xh\n", dataoffset);
+
+ ptr = (uint32_t *)&qlt->rimage[i].data;
+
+ /* adjust addr */
+ addr = addr0 + (dataoffset/4);
+ for (index = 0; index < sizeof (qlt_rom_data_t)/4;
+ index ++) {
+ ret = qlt_read_flash_word(qlt, addr++, &val);
+ if (ret != QLT_SUCCESS) {
+ EL(qlt, "read flash, status=%llxh\n", ret);
+ return (ret);
+ }
+ chksum += val;
+ *ptr = LE_32(val);
+ ptr++;
+ }
+
+ /* check signature */
+ if ((qlt->rimage[i].data.signature[0] != 0x50) &&
+ (qlt->rimage[i].data.signature[1] != 0x43) &&
+ (qlt->rimage[i].data.signature[2] != 0x49) &&
+ (qlt->rimage[i].data.signature[3] != 0x52)) {
+ EL(qlt,
+ "data sig[3] [2] [1] [0] (%xh)(%xh)(%xh)(%xh)\n",
+ qlt->rimage[i].data.signature[3],
+ qlt->rimage[i].data.signature[2],
+ qlt->rimage[i].data.signature[1],
+ qlt->rimage[i].data.signature[0]);
+ return (QLT_SUCCESS);
+ }
+
+ EL(qlt, "codetype (%xh) revisionlevel[1][0] (%xh)(%xh)\n",
+ qlt->rimage[i].data.codetype,
+ qlt->rimage[i].data.revisionlevel[1],
+ qlt->rimage[i].data.revisionlevel[0]);
+
+ /* check if this is the last image */
+ if (qlt->rimage[i].data.indicator == PCI_IND_LAST_IMAGE) {
+ EL(qlt, "last image (%xh)\n",
+ qlt->rimage[i].data.indicator);
+ return (QLT_SUCCESS);
+
+ }
+
+ /* Get the image length and adjust the addr according */
+ length = (qlt->rimage[i].data.imagelength[1] |
+ qlt->rimage[i].data.imagelength[0]);
+
+ EL(qlt, "image[%d] length[1][0] (%xh) (%xh) in sectors\n",
+ i, length);
+
+ /* the starting addr of the next image */
+ addr = addr0 + ((length * 512)/4);
+ *out_addr = addr;
+ }
+
+ return (QLT_SUCCESS);
+ }
+
+ fct_status_t
+ qlt_read_rom_image(qlt_state_t *qlt)
+ {
+ uint32_t addr;
+ uint32_t out_addr = 0;
+ uint32_t count = 0;
+ boolean_t last_image = FALSE;
+ fct_status_t ret;
+
+ if (qlt->qlt_27xx_chip) {
+ addr = FLASH_2700_DATA_ADDR + FLASH_2700_BOOT_CODE_ADDR;
+ } else if (qlt->qlt_83xx_chip) {
+ addr = FLASH_8300_DATA_ADDR + FLASH_8300_BOOT_CODE_ADDR;
+ } else if (qlt->qlt_81xx_chip) {
+ addr = FLASH_8100_DATA_ADDR + FLASH_8100_BOOT_CODE_ADDR;
+ } else if (qlt->qlt_25xx_chip) {
+ addr = FLASH_2500_DATA_ADDR + FLASH_2500_BOOT_CODE_ADDR;
+ } else {
+ addr = FLASH_2400_DATA_ADDR + FLASH_2400_BOOT_CODE_ADDR;
+ }
+ mutex_enter(&qlt_global_lock);
+
+ /* Pause RISC. */
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE));
+ (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
+
+ do {
+ ret = qlt_read_bfe(qlt, addr, &out_addr, count);
+ if (ret != QLT_SUCCESS) {
+ EL(qlt, "qlt_read_bfe, status=%llxh\n", ret);
+ break;
+ }
+ if (qlt->rimage[count].data.indicator ==
+ PCI_IND_LAST_IMAGE) {
+ last_image = TRUE;
+ } else {
+ addr = out_addr;
+ }
+ count ++;
+ } while ((last_image != TRUE) && (count < 6));
+
+ /* Release RISC Pause */
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_PAUSE));
+ (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
+
+ mutex_exit(&qlt_global_lock);
+
+ return (QLT_SUCCESS);
+ }
+
uint32_t
qlt_sync_atio_queue(qlt_state_t *qlt)
{
uint32_t total_ent;
*** 2940,2955 ****
ent_cnt = (uint32_t)(atio[1]);
if (ent_cnt > total_ent) {
break;
}
switch ((uint8_t)(atio[0])) {
case 0x0d: /* INOT */
qlt_handle_inot(qlt, atio);
break;
- case 0x06: /* ATIO */
- qlt_handle_atio(qlt, atio);
- break;
default:
EL(qlt, "atio_queue_update atio[0]=%xh\n", atio[0]);
cmn_err(CE_WARN, "qlt_handle_atio_queue_update: "
"atio[0] is %x, qlt-%p", atio[0], (void *)qlt);
break;
--- 4943,4958 ----
ent_cnt = (uint32_t)(atio[1]);
if (ent_cnt > total_ent) {
break;
}
switch ((uint8_t)(atio[0])) {
+ case 0x06: /* ATIO, make performance case the 1st test */
+ qlt_handle_atio(qlt, atio);
+ break;
case 0x0d: /* INOT */
qlt_handle_inot(qlt, atio);
break;
default:
EL(qlt, "atio_queue_update atio[0]=%xh\n", atio[0]);
cmn_err(CE_WARN, "qlt_handle_atio_queue_update: "
"atio[0] is %x, qlt-%p", atio[0], (void *)qlt);
break;
*** 2956,3015 ****
}
qlt->atio_ndx_to_fw = (uint16_t)(
(qlt->atio_ndx_to_fw + ent_cnt) & (ATIO_QUEUE_ENTRIES - 1));
total_ent -= ent_cnt;
} while (total_ent > 0);
REG_WR32(qlt, REG_ATIO_OUT_PTR, qlt->atio_ndx_to_fw);
}
uint32_t
! qlt_sync_resp_queue(qlt_state_t *qlt)
{
uint32_t total_ent;
! if (qlt->resp_ndx_from_fw > qlt->resp_ndx_to_fw) {
! total_ent = qlt->resp_ndx_from_fw - qlt->resp_ndx_to_fw;
! (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
! RESPONSE_QUEUE_OFFSET
! + (qlt->resp_ndx_to_fw << 6), total_ent << 6,
DDI_DMA_SYNC_FORCPU);
} else {
! total_ent = RESPONSE_QUEUE_ENTRIES - qlt->resp_ndx_to_fw +
! qlt->resp_ndx_from_fw;
(void) ddi_dma_sync(qlt->queue_mem_dma_handle,
! RESPONSE_QUEUE_OFFSET
! + (qlt->resp_ndx_to_fw << 6), (RESPONSE_QUEUE_ENTRIES -
! qlt->resp_ndx_to_fw) << 6, DDI_DMA_SYNC_FORCPU);
(void) ddi_dma_sync(qlt->queue_mem_dma_handle,
RESPONSE_QUEUE_OFFSET,
! qlt->resp_ndx_from_fw << 6, DDI_DMA_SYNC_FORCPU);
}
return (total_ent);
}
void
! qlt_handle_resp_queue_update(qlt_state_t *qlt)
{
uint32_t total_ent;
uint8_t c;
! if (qlt->resp_ndx_to_fw == qlt->resp_ndx_from_fw)
return;
! total_ent = qlt_sync_resp_queue(qlt);
do {
! caddr_t resp = &qlt->resp_ptr[qlt->resp_ndx_to_fw << 6];
uint32_t ent_cnt;
ent_cnt = (uint32_t)(resp[0] == 0x51 ? resp[1] : 1);
if (ent_cnt > total_ent) {
break;
}
switch ((uint8_t)(resp[0])) {
case 0x12: /* CTIO completion */
! qlt_handle_ctio_completion(qlt, (uint8_t *)resp);
break;
case 0x0e: /* NACK */
/* Do Nothing */
break;
case 0x1b: /* Verify FW */
--- 4959,5057 ----
}
qlt->atio_ndx_to_fw = (uint16_t)(
(qlt->atio_ndx_to_fw + ent_cnt) & (ATIO_QUEUE_ENTRIES - 1));
total_ent -= ent_cnt;
} while (total_ent > 0);
+
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ MQBAR_WR32(qlt, MQBAR_ATIO_OUT, qlt->atio_ndx_to_fw);
+ } else {
REG_WR32(qlt, REG_ATIO_OUT_PTR, qlt->atio_ndx_to_fw);
+ }
}
uint32_t
! qlt_sync_resp_queue(qlt_state_t *qlt, uint16_t qi)
{
uint32_t total_ent;
! if (qlt->mq_resp[qi].mq_ndx_from_fw > qlt->mq_resp[qi].mq_ndx_to_fw) {
! total_ent = qlt->mq_resp[qi].mq_ndx_from_fw -
! qlt->mq_resp[qi].mq_ndx_to_fw;
! if (qi) {
! (void) ddi_dma_sync(
! qlt->mq_resp[qi].queue_mem_mq_dma_handle,
! (qlt->mq_resp[qi].mq_ndx_to_fw << 6),
! total_ent << 6,
DDI_DMA_SYNC_FORCPU);
} else {
! (void) ddi_dma_sync(
! qlt->queue_mem_dma_handle,
! RESPONSE_QUEUE_OFFSET +
! (qlt->mq_resp[qi].mq_ndx_to_fw << 6),
! total_ent << 6,
! DDI_DMA_SYNC_FORCPU);
! }
! } else {
! total_ent =
! (qi ? RESPONSE_QUEUE_MQ_ENTRIES : RESPONSE_QUEUE_ENTRIES) -
! qlt->mq_resp[qi].mq_ndx_to_fw +
! qlt->mq_resp[qi].mq_ndx_from_fw;
!
! if (qi) {
!
! (void) ddi_dma_sync(
! qlt->mq_resp[qi].queue_mem_mq_dma_handle,
! qlt->mq_resp[qi].mq_ndx_to_fw << 6,
! (RESPONSE_QUEUE_MQ_ENTRIES -
! qlt->mq_resp[qi].mq_ndx_to_fw) << 6,
! DDI_DMA_SYNC_FORCPU);
! (void) ddi_dma_sync(
! qlt->mq_resp[qi].queue_mem_mq_dma_handle, 0,
! qlt->mq_resp[qi].mq_ndx_from_fw << 6,
! DDI_DMA_SYNC_FORCPU);
! } else {
(void) ddi_dma_sync(qlt->queue_mem_dma_handle,
! RESPONSE_QUEUE_OFFSET +
! (qlt->mq_resp[qi].mq_ndx_to_fw << 6),
! (RESPONSE_QUEUE_ENTRIES -
! qlt->mq_resp[qi].mq_ndx_to_fw) << 6,
! DDI_DMA_SYNC_FORCPU);
(void) ddi_dma_sync(qlt->queue_mem_dma_handle,
RESPONSE_QUEUE_OFFSET,
! qlt->mq_resp[qi].mq_ndx_from_fw << 6,
! DDI_DMA_SYNC_FORCPU);
}
+ }
+
return (total_ent);
}
void
! qlt_handle_resp_queue_update(qlt_state_t *qlt, uint16_t qi)
{
uint32_t total_ent;
uint8_t c;
! if (qlt->mq_resp[qi].mq_ndx_to_fw == qlt->mq_resp[qi].mq_ndx_from_fw)
return;
! total_ent = qlt_sync_resp_queue(qlt, qi);
do {
! uint32_t qe = qlt->mq_resp[qi].mq_ndx_to_fw;
! caddr_t resp = &qlt->mq_resp[qi].mq_ptr[qe << 6];
!
uint32_t ent_cnt;
ent_cnt = (uint32_t)(resp[0] == 0x51 ? resp[1] : 1);
if (ent_cnt > total_ent) {
break;
}
switch ((uint8_t)(resp[0])) {
case 0x12: /* CTIO completion */
! qlt_handle_ctio_completion(qlt, (uint8_t *)resp, qi);
break;
case 0x0e: /* NACK */
/* Do Nothing */
break;
case 0x1b: /* Verify FW */
*** 3016,3025 ****
--- 5058,5070 ----
qlt_handle_verify_fw_completion(qlt, (uint8_t *)resp);
break;
case 0x29: /* CT PassThrough */
qlt_handle_ct_completion(qlt, (uint8_t *)resp);
break;
+ case 0x32: /* Report ID */
+ EL(qlt, "report Id received [type %xh]\n", resp[0]);
+ break;
case 0x33: /* Abort IO IOCB completion */
qlt_handle_sol_abort_completion(qlt, (uint8_t *)resp);
break;
case 0x51: /* PUREX */
qlt_handle_purex(qlt, (uint8_t *)resp);
*** 3039,3062 ****
qlt_handle_unsol_els_completion(qlt,
(uint8_t *)resp);
}
break;
case 0x54: /* ABTS received */
! qlt_handle_rcvd_abts(qlt, (uint8_t *)resp);
break;
case 0x55: /* ABTS completion */
! qlt_handle_abts_completion(qlt, (uint8_t *)resp);
break;
default:
EL(qlt, "response entry=%xh\n", resp[0]);
break;
}
! qlt->resp_ndx_to_fw = (qlt->resp_ndx_to_fw + ent_cnt) &
(RESPONSE_QUEUE_ENTRIES - 1);
total_ent -= ent_cnt;
} while (total_ent > 0);
! REG_WR32(qlt, REG_RESP_OUT_PTR, qlt->resp_ndx_to_fw);
}
fct_status_t
qlt_portid_to_handle(qlt_state_t *qlt, uint32_t id, uint16_t cmd_handle,
uint16_t *ret_handle)
--- 5084,5119 ----
qlt_handle_unsol_els_completion(qlt,
(uint8_t *)resp);
}
break;
case 0x54: /* ABTS received */
! qlt_handle_rcvd_abts(qlt, (uint8_t *)resp, qi);
break;
case 0x55: /* ABTS completion */
! qlt_handle_abts_completion(qlt, (uint8_t *)resp, qi);
break;
default:
EL(qlt, "response entry=%xh\n", resp[0]);
break;
}
! if (qi != 0) {
! qlt->mq_resp[qi].mq_ndx_to_fw =
! (qlt->mq_resp[qi].mq_ndx_to_fw + ent_cnt) &
! (RESPONSE_QUEUE_MQ_ENTRIES - 1);
! } else {
! qlt->mq_resp[qi].mq_ndx_to_fw =
! (qlt->mq_resp[qi].mq_ndx_to_fw + ent_cnt) &
(RESPONSE_QUEUE_ENTRIES - 1);
+ }
total_ent -= ent_cnt;
} while (total_ent > 0);
! if (qlt->qlt_mq_enabled) {
! MQBAR_WR32(qlt, (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_OUT,
! qlt->mq_resp[qi].mq_ndx_to_fw);
! } else {
! REG_WR32(qlt, REG_RESP_OUT_PTR, qlt->mq_resp[qi].mq_ndx_to_fw);
! }
}
fct_status_t
qlt_portid_to_handle(qlt_state_t *qlt, uint32_t id, uint16_t cmd_handle,
uint16_t *ret_handle)
*** 3079,3095 ****
mcp->to_fw_mask |= BIT_9 | BIT_8;
mcp->from_fw_mask |= BIT_1 | BIT_2;
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mailbox_command=7Ch status=%llxh\n", ret);
! cmn_err(CE_WARN, "GET ID list failed, ret = %llx, mb0=%x, "
! "mb1=%x, mb2=%x", (long long)ret, mcp->from_fw[0],
! mcp->from_fw[1], mcp->from_fw[2]);
qlt_free_mailbox_command(qlt, mcp);
return (ret);
}
qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
p = mcp->dbuf->db_sglist[0].seg_addr;
for (n = 0; n < mcp->from_fw[1]; n++) {
ent_id = LE_32(*((uint32_t *)p)) & 0xFFFFFF;
h = (uint16_t)((uint16_t)p[4] | (((uint16_t)p[5]) << 8));
--- 5136,5156 ----
mcp->to_fw_mask |= BIT_9 | BIT_8;
mcp->from_fw_mask |= BIT_1 | BIT_2;
ret = qlt_mailbox_command(qlt, mcp);
if (ret != QLT_SUCCESS) {
! EL(qlt, "qlt_mbox_command=7Ch status=%llxh\n", ret);
! cmn_err(CE_WARN, "qlt(%d) GET ID list failed, ret = %llx, "
! "mb0=%x, mb1=%x, mb2=%x", qlt->instance, (long long)ret,
! mcp->from_fw[0], mcp->from_fw[1], mcp->from_fw[2]);
qlt_free_mailbox_command(qlt, mcp);
return (ret);
}
+
+ EL(qlt, "mbx cmd=7Ch, GET_ID_LIST id=%x fw[1]=%x\n",
+ id, mcp->from_fw[1]);
+
qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
p = mcp->dbuf->db_sglist[0].seg_addr;
for (n = 0; n < mcp->from_fw[1]; n++) {
ent_id = LE_32(*((uint32_t *)p)) & 0xFFFFFF;
h = (uint16_t)((uint16_t)p[4] | (((uint16_t)p[5]) << 8));
*** 3096,3118 ****
if (ent_id == id) {
found = 1;
*ret_handle = h;
if ((cmd_handle != FCT_HANDLE_NONE) &&
(cmd_handle != h)) {
! cmn_err(CE_WARN, "login for portid %x came in "
! "with handle %x, while the portid was "
! "already using a different handle %x",
! id, cmd_handle, h);
qlt_free_mailbox_command(qlt, mcp);
return (QLT_FAILURE);
}
break;
}
if ((cmd_handle != FCT_HANDLE_NONE) && (h == cmd_handle)) {
! cmn_err(CE_WARN, "login for portid %x came in with "
! "handle %x, while the handle was already in use "
! "for portid %x", id, cmd_handle, ent_id);
qlt_free_mailbox_command(qlt, mcp);
return (QLT_FAILURE);
}
p += 8;
}
--- 5157,5180 ----
if (ent_id == id) {
found = 1;
*ret_handle = h;
if ((cmd_handle != FCT_HANDLE_NONE) &&
(cmd_handle != h)) {
! cmn_err(CE_WARN, "qlt(%d) login for portid %x "
! "came in with handle %x, while the portid "
! "was already using a different handle %x",
! qlt->instance, id, cmd_handle, h);
qlt_free_mailbox_command(qlt, mcp);
return (QLT_FAILURE);
}
break;
}
if ((cmd_handle != FCT_HANDLE_NONE) && (h == cmd_handle)) {
! cmn_err(CE_WARN, "qlt(%d) login for portid %x came in "
! "with handle %x, while the handle was already in "
! "use for portid %x",
! qlt->instance, id, cmd_handle, ent_id);
qlt_free_mailbox_command(qlt, mcp);
return (QLT_FAILURE);
}
p += 8;
}
*** 3189,3198 ****
--- 5251,5263 ----
if (ret != FCT_SUCCESS) {
EL(qlt, "qlt_fill_plogi, status=%llxh\n", ret);
return (ret);
}
+ EL(qlt, "rport id=%xh cmd_type=%xh handle=%xh(%xh)\n",
+ rp->rp_id, login->cmd_type, h, rp->rp_handle);
+
if (h == FCT_HANDLE_NONE)
return (FCT_SUCCESS);
if (rp->rp_handle == FCT_HANDLE_NONE) {
rp->rp_handle = h;
*** 3200,3212 ****
}
if (rp->rp_handle == h)
return (FCT_SUCCESS);
! EL(qlt, "rp_handle=%xh != h=%xh\n", rp->rp_handle, h);
return (FCT_FAILURE);
}
/* invoked in single thread */
fct_status_t
qlt_deregister_remote_port(fct_local_port_t *port, fct_remote_port_t *rp)
{
uint8_t *req;
--- 5265,5278 ----
}
if (rp->rp_handle == h)
return (FCT_SUCCESS);
! EL(qlt, "failed, rp_handle=%xh != h=%xh\n", rp->rp_handle, h);
return (FCT_FAILURE);
}
+
/* invoked in single thread */
fct_status_t
qlt_deregister_remote_port(fct_local_port_t *port, fct_remote_port_t *rp)
{
uint8_t *req;
*** 3219,3253 ****
if ((qlt->qlt_state == FCT_STATE_OFFLINE) ||
(qlt->qlt_state == FCT_STATE_OFFLINING))
return (FCT_SUCCESS);
ASSERT(qlt->rp_id_in_dereg == 0);
mutex_enter(&qlt->preq_lock);
req = (uint8_t *)qlt_get_preq_entries(qlt, 1);
if (req == NULL) {
mutex_exit(&qlt->preq_lock);
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
req[0] = 0x52; req[1] = 1;
/* QMEM_WR32(qlt, (&req[4]), 0xffffffff); */
QMEM_WR16(qlt, (&req[0xA]), rp->rp_handle);
QMEM_WR16(qlt, (&req[0xC]), 0x98); /* implicit logo */
QMEM_WR32(qlt, (&req[0x10]), rp->rp_id);
qlt->rp_id_in_dereg = rp->rp_id;
qlt_submit_preq_entries(qlt, 1);
dereg_req_timer = ddi_get_lbolt() + drv_usectohz(DEREG_RP_TIMEOUT);
if (cv_timedwait(&qlt->rp_dereg_cv,
! &qlt->preq_lock, dereg_req_timer) > 0) {
ret = qlt->rp_dereg_status;
} else {
ret = FCT_BUSY;
}
qlt->rp_dereg_status = 0;
qlt->rp_id_in_dereg = 0;
mutex_exit(&qlt->preq_lock);
return (ret);
}
/*
* Pass received ELS up to framework.
--- 5285,5344 ----
if ((qlt->qlt_state == FCT_STATE_OFFLINE) ||
(qlt->qlt_state == FCT_STATE_OFFLINING))
return (FCT_SUCCESS);
ASSERT(qlt->rp_id_in_dereg == 0);
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ mutex_enter(&qlt->mq_req[0].mq_lock);
+ req = (uint8_t *)qlt_get_req_entries(qlt, 1, 0);
+ if (req == NULL) {
+ EL(qlt, "req = NULL\n");
+ mutex_exit(&qlt->mq_req[0].mq_lock);
+ return (FCT_BUSY);
+ }
+ } else {
mutex_enter(&qlt->preq_lock);
req = (uint8_t *)qlt_get_preq_entries(qlt, 1);
if (req == NULL) {
+ EL(qlt, "req = NULL\n");
mutex_exit(&qlt->preq_lock);
return (FCT_BUSY);
}
+ }
bzero(req, IOCB_SIZE);
req[0] = 0x52; req[1] = 1;
/* QMEM_WR32(qlt, (&req[4]), 0xffffffff); */
QMEM_WR16(qlt, (&req[0xA]), rp->rp_handle);
QMEM_WR16(qlt, (&req[0xC]), 0x98); /* implicit logo */
QMEM_WR32(qlt, (&req[0x10]), rp->rp_id);
qlt->rp_id_in_dereg = rp->rp_id;
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ qlt_submit_req_entries(qlt, 1, 0);
+ } else {
qlt_submit_preq_entries(qlt, 1);
+ }
dereg_req_timer = ddi_get_lbolt() + drv_usectohz(DEREG_RP_TIMEOUT);
if (cv_timedwait(&qlt->rp_dereg_cv,
! (((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) ?
! &qlt->mq_req[0].mq_lock : &qlt->preq_lock),
! dereg_req_timer) > 0) {
ret = qlt->rp_dereg_status;
} else {
ret = FCT_BUSY;
}
qlt->rp_dereg_status = 0;
qlt->rp_id_in_dereg = 0;
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ mutex_exit(&qlt->mq_req[0].mq_lock);
+ } else {
mutex_exit(&qlt->preq_lock);
+ }
+
+ EL(qlt, "Dereg remote port(%Xh), ret=%llxh\n",
+ rp->rp_id, ret);
+
return (ret);
}
/*
* Pass received ELS up to framework.
*** 3261,3271 ****
uint32_t payload_size;
uint32_t remote_portid;
uint8_t *pldptr, *bndrptr;
int i, off;
uint16_t iocb_flags;
! char info[QLT_INFO_LEN];
remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) |
((uint32_t)(resp[0x1A])) << 16;
iocb_flags = QMEM_RD16(qlt, (&resp[8]));
if (iocb_flags & BIT_15) {
--- 5352,5362 ----
uint32_t payload_size;
uint32_t remote_portid;
uint8_t *pldptr, *bndrptr;
int i, off;
uint16_t iocb_flags;
! char info[160];
remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) |
((uint32_t)(resp[0x1A])) << 16;
iocb_flags = QMEM_RD16(qlt, (&resp[8]));
if (iocb_flags & BIT_15) {
*** 3283,3295 ****
cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ELS,
(int)(payload_size + GET_STRUCT_SIZE(qlt_cmd_t)), 0);
if (cmd == NULL) {
EL(qlt, "fct_alloc cmd==NULL\n");
cmd_null:;
! (void) snprintf(info, sizeof (info),
! "qlt_handle_purex: qlt-%p, "
! "can't allocate space for fct_cmd", (void *)qlt);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
--- 5374,5386 ----
cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ELS,
(int)(payload_size + GET_STRUCT_SIZE(qlt_cmd_t)), 0);
if (cmd == NULL) {
EL(qlt, "fct_alloc cmd==NULL\n");
cmd_null:;
! (void) snprintf(info, 160, "qlt_handle_purex: qlt-%p, can't "
! "allocate space for fct_cmd", (void *)qlt);
! info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
*** 3309,3342 ****
cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) |
((uint32_t)(resp[0x16])) << 16;
cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26]));
cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24]));
pldptr = &resp[0x2C];
! bndrptr = (uint8_t *)(qlt->resp_ptr + (RESPONSE_QUEUE_ENTRIES << 6));
for (i = 0, off = 0x2c; i < payload_size; i += 4) {
/* Take care of fw's swapping of payload */
els->els_req_payload[i] = pldptr[3];
els->els_req_payload[i+1] = pldptr[2];
els->els_req_payload[i+2] = pldptr[1];
els->els_req_payload[i+3] = pldptr[0];
pldptr += 4;
if (pldptr == bndrptr)
! pldptr = (uint8_t *)qlt->resp_ptr;
off += 4;
if (off >= IOCB_SIZE) {
off = 4;
pldptr += 4;
}
}
fct_post_rcvd_cmd(cmd, 0);
}
fct_status_t
qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags)
{
qlt_state_t *qlt;
! char info[QLT_INFO_LEN];
qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
--- 5400,5438 ----
cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) |
((uint32_t)(resp[0x16])) << 16;
cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26]));
cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24]));
pldptr = &resp[0x2C];
! bndrptr = (uint8_t *)(qlt->mq_resp[0].mq_ptr
! + (RESPONSE_QUEUE_ENTRIES << 6));
for (i = 0, off = 0x2c; i < payload_size; i += 4) {
/* Take care of fw's swapping of payload */
els->els_req_payload[i] = pldptr[3];
els->els_req_payload[i+1] = pldptr[2];
els->els_req_payload[i+2] = pldptr[1];
els->els_req_payload[i+3] = pldptr[0];
pldptr += 4;
if (pldptr == bndrptr)
! pldptr = (uint8_t *)qlt->mq_resp[0].mq_ptr;
off += 4;
if (off >= IOCB_SIZE) {
off = 4;
pldptr += 4;
}
}
+
+ EL(qlt, "remote portid = %xh logi/o(%xh) to us revd rex1=%xh\n",
+ remote_portid, els->els_req_payload[0], qcmd->fw_xchg_addr);
+
fct_post_rcvd_cmd(cmd, 0);
}
fct_status_t
qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags)
{
qlt_state_t *qlt;
! char info[160];
qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
*** 3366,3379 ****
ASSERT(0);
return (FCT_FAILURE);
}
fatal_panic:;
! (void) snprintf(info, sizeof (info),
! "qlt_send_cmd_response: can not handle "
"FCT_IOF_FORCE_FCA_DONE for cmd %p, ioflags-%x", (void *)cmd,
ioflags);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return (FCT_FAILURE);
}
--- 5462,5475 ----
ASSERT(0);
return (FCT_FAILURE);
}
fatal_panic:;
! (void) snprintf(info, 160, "qlt_send_cmd_response: can not handle "
"FCT_IOF_FORCE_FCA_DONE for cmd %p, ioflags-%x", (void *)cmd,
ioflags);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return (FCT_FAILURE);
}
*** 3385,3395 ****
--- 5481,5495 ----
qlt_state_t *qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
uint8_t *req, rcnt;
uint16_t flags;
uint16_t cookie_count;
+ uint32_t ent_cnt;
+ uint16_t qi;
+ qi = qcmd->qid;
+
if (dbuf->db_handle == 0)
qcmd->dbuf = dbuf;
flags = (uint16_t)(((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5);
if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
flags = (uint16_t)(flags | 2);
*** 3409,3438 ****
rcnt = qlt_get_iocb_count(cookie_count);
} else {
cookie_count = 1;
rcnt = 1;
}
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, rcnt);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
return (FCT_BUSY);
}
! bzero(req, IOCB_SIZE); /* XXX needed ? */
req[0] = 0x12;
req[1] = rcnt;
req[2] = dbuf->db_handle;
! QMEM_WR32(qlt, req+4, cmd->cmd_handle);
! QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle);
! QMEM_WR16(qlt, req+10, 60); /* 60 seconds timeout */
! QMEM_WR16(qlt, req+12, cookie_count);
! QMEM_WR32(qlt, req+0x10, cmd->cmd_rportid);
! QMEM_WR32(qlt, req+0x14, qcmd->fw_xchg_addr);
! QMEM_WR16(qlt, req+0x1A, flags);
! QMEM_WR16(qlt, req+0x20, cmd->cmd_oxid);
! QMEM_WR32(qlt, req+0x24, dbuf->db_relative_offset);
! QMEM_WR32(qlt, req+0x2C, dbuf->db_data_size);
if (dbuf->db_flags & DB_LU_DATA_BUF) {
uint8_t *qptr; /* qlt continuation segs */
uint16_t cookie_resid;
uint16_t cont_segs;
ddi_dma_cookie_t cookie, *ckp;
--- 5509,5538 ----
rcnt = qlt_get_iocb_count(cookie_count);
} else {
cookie_count = 1;
rcnt = 1;
}
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_BUSY);
}
! bzero(req, IOCB_SIZE);
req[0] = 0x12;
req[1] = rcnt;
req[2] = dbuf->db_handle;
! QMEM_WR32_REQ(qlt, qi, req+4, cmd->cmd_handle);
! QMEM_WR16_REQ(qlt, qi, req+8, cmd->cmd_rp->rp_handle);
! QMEM_WR16_REQ(qlt, qi, req+10, 60); /* 60 seconds timeout */
! QMEM_WR16_REQ(qlt, qi, req+12, cookie_count);
! QMEM_WR32_REQ(qlt, qi, req+0x10, cmd->cmd_rportid);
! QMEM_WR32_REQ(qlt, qi, req+0x14, qcmd->fw_xchg_addr);
! QMEM_WR16_REQ(qlt, qi, req+0x1A, flags);
! QMEM_WR16_REQ(qlt, qi, req+0x20, cmd->cmd_oxid);
! QMEM_WR32_REQ(qlt, qi, req+0x24, dbuf->db_relative_offset);
! QMEM_WR32_REQ(qlt, qi, req+0x2C, dbuf->db_data_size);
if (dbuf->db_flags & DB_LU_DATA_BUF) {
uint8_t *qptr; /* qlt continuation segs */
uint16_t cookie_resid;
uint16_t cont_segs;
ddi_dma_cookie_t cookie, *ckp;
*** 3445,3472 ****
/*
* Program the first segment into main record.
*/
if (ckp) {
ASSERT(ckp->dmac_size);
! QMEM_WR64(qlt, req+0x34, ckp->dmac_laddress);
! QMEM_WR32(qlt, req+0x3c, ckp->dmac_size);
} else {
qlt_ddi_dma_nextcookie(dbuf, &cookie);
ASSERT(cookie.dmac_size);
! QMEM_WR64(qlt, req+0x34, cookie.dmac_laddress);
! QMEM_WR32(qlt, req+0x3c, cookie.dmac_size);
}
cookie_resid = cookie_count-1;
/*
* Program remaining segments into continuation records.
*/
while (cookie_resid) {
req += IOCB_SIZE;
! if (req >= (uint8_t *)qlt->resp_ptr) {
! req = (uint8_t *)qlt->req_ptr;
}
req[0] = 0x0a;
req[1] = 1;
req[2] = req[3] = 0; /* tidy */
qptr = &req[4];
for (cont_segs = CONT_A64_DATA_SEGMENTS;
--- 5545,5576 ----
/*
* Program the first segment into main record.
*/
if (ckp) {
ASSERT(ckp->dmac_size);
! QMEM_WR64_REQ(qlt, qi, req+0x34, ckp->dmac_laddress);
! QMEM_WR32_REQ(qlt, qi, req+0x3c, ckp->dmac_size);
} else {
qlt_ddi_dma_nextcookie(dbuf, &cookie);
ASSERT(cookie.dmac_size);
! QMEM_WR64_REQ(qlt, qi, req+0x34, cookie.dmac_laddress);
! QMEM_WR32_REQ(qlt, qi, req+0x3c, cookie.dmac_size);
}
cookie_resid = cookie_count-1;
+ ent_cnt = (qi == 0) ? REQUEST_QUEUE_ENTRIES :
+ REQUEST_QUEUE_MQ_ENTRIES;
/*
* Program remaining segments into continuation records.
*/
while (cookie_resid) {
req += IOCB_SIZE;
! if (req >= (uint8_t *)(qlt->mq_req[qi].mq_ptr +
! (ent_cnt * IOCB_SIZE))) {
! req = (uint8_t *)(qlt->mq_req[qi].mq_ptr);
}
+
req[0] = 0x0a;
req[1] = 1;
req[2] = req[3] = 0; /* tidy */
qptr = &req[4];
for (cont_segs = CONT_A64_DATA_SEGMENTS;
*** 3473,3494 ****
cont_segs && cookie_resid; cont_segs--) {
if (ckp) {
++ckp; /* next cookie */
ASSERT(ckp->dmac_size != 0);
! QMEM_WR64(qlt, qptr,
ckp->dmac_laddress);
qptr += 8; /* skip over laddress */
! QMEM_WR32(qlt, qptr, ckp->dmac_size);
qptr += 4; /* skip over size */
} else {
qlt_ddi_dma_nextcookie(dbuf, &cookie);
ASSERT(cookie.dmac_size != 0);
! QMEM_WR64(qlt, qptr,
cookie.dmac_laddress);
qptr += 8; /* skip over laddress */
! QMEM_WR32(qlt, qptr, cookie.dmac_size);
qptr += 4; /* skip over size */
}
cookie_resid--;
}
/*
--- 5577,5600 ----
cont_segs && cookie_resid; cont_segs--) {
if (ckp) {
++ckp; /* next cookie */
ASSERT(ckp->dmac_size != 0);
! QMEM_WR64_REQ(qlt, qi, qptr,
ckp->dmac_laddress);
qptr += 8; /* skip over laddress */
! QMEM_WR32_REQ(qlt, qi, qptr,
! ckp->dmac_size);
qptr += 4; /* skip over size */
} else {
qlt_ddi_dma_nextcookie(dbuf, &cookie);
ASSERT(cookie.dmac_size != 0);
! QMEM_WR64_REQ(qlt, qi, qptr,
cookie.dmac_laddress);
qptr += 8; /* skip over laddress */
! QMEM_WR32_REQ(qlt, qi, qptr,
! cookie.dmac_size);
qptr += 4; /* skip over size */
}
cookie_resid--;
}
/*
*** 3502,3525 ****
bzero(qptr, resid);
}
}
} else {
/* Single, contiguous buffer */
! QMEM_WR64(qlt, req+0x34, bctl->bctl_dev_addr);
! QMEM_WR32(qlt, req+0x34+8, dbuf->db_data_size);
}
! qlt_submit_req_entries(qlt, rcnt);
! mutex_exit(&qlt->req_lock);
return (STMF_SUCCESS);
}
/*
* We must construct proper FCP_RSP_IU now. Here we only focus on
* the handling of FCP_SNS_INFO. If there's protocol failures (FCP_RSP_INFO),
! * we could have catched them before we enter here.
*/
fct_status_t
qlt_send_status(qlt_state_t *qlt, fct_cmd_t *cmd)
{
qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
--- 5608,5631 ----
bzero(qptr, resid);
}
}
} else {
/* Single, contiguous buffer */
! QMEM_WR64_REQ(qlt, qi, req+0x34, bctl->bctl_dev_addr);
! QMEM_WR32_REQ(qlt, qi, req+0x34+8, dbuf->db_data_size);
}
! qlt_submit_req_entries(qlt, rcnt, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (STMF_SUCCESS);
}
/*
* We must construct proper FCP_RSP_IU now. Here we only focus on
* the handling of FCP_SNS_INFO. If there's protocol failures (FCP_RSP_INFO),
! * we could have caught them before we enter here.
*/
fct_status_t
qlt_send_status(qlt_state_t *qlt, fct_cmd_t *cmd)
{
qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
*** 3530,3540 ****
--- 5636,5649 ----
uint8_t *psd, sensbuf[24]; /* sense data */
uint16_t flags;
uint16_t scsi_status;
int use_mode2;
int ndx;
+ uint16_t qi;
+ qi = qcmd->qid;
+
/*
* Enter fast channel for non check condition
*/
if (task->task_scsi_status != STATUS_CHECK) {
/*
*** 3542,3564 ****
*/
flags = (uint16_t)(BIT_6 | BIT_15 |
(((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
scsi_status = (uint16_t)task->task_scsi_status;
if (task->task_status_ctrl == TASK_SCTRL_OVER) {
! scsi_status = (uint16_t)(scsi_status | BIT_10);
} else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
! scsi_status = (uint16_t)(scsi_status | BIT_11);
}
qcmd->dbuf_rsp_iu = NULL;
/*
* Fillout CTIO type 7 IOCB
*/
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
return (FCT_BUSY);
}
/*
* Common fields
--- 5651,5673 ----
*/
flags = (uint16_t)(BIT_6 | BIT_15 |
(((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
scsi_status = (uint16_t)task->task_scsi_status;
if (task->task_status_ctrl == TASK_SCTRL_OVER) {
! scsi_status = (uint16_t)(scsi_status | FCP_RESID_OVER);
} else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
! scsi_status = (uint16_t)(scsi_status | FCP_RESID_UNDER);
}
qcmd->dbuf_rsp_iu = NULL;
/*
* Fillout CTIO type 7 IOCB
*/
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_BUSY);
}
/*
* Common fields
*** 3565,3592 ****
*/
bzero(req, IOCB_SIZE);
req[0x00] = 0x12;
req[0x01] = 0x1;
req[0x02] = BIT_7; /* indicate if it's a pure status req */
! QMEM_WR32(qlt, req + 0x04, cmd->cmd_handle);
! QMEM_WR16(qlt, req + 0x08, cmd->cmd_rp->rp_handle);
! QMEM_WR32(qlt, req + 0x10, cmd->cmd_rportid);
! QMEM_WR32(qlt, req + 0x14, qcmd->fw_xchg_addr);
/*
* Mode-specific fields
*/
! QMEM_WR16(qlt, req + 0x1A, flags);
! QMEM_WR32(qlt, req + 0x1C, task->task_resid);
! QMEM_WR16(qlt, req + 0x20, cmd->cmd_oxid);
! QMEM_WR16(qlt, req + 0x22, scsi_status);
/*
* Trigger FW to send SCSI status out
*/
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
return (STMF_SUCCESS);
}
ASSERT(task->task_scsi_status == STATUS_CHECK);
/*
--- 5674,5710 ----
*/
bzero(req, IOCB_SIZE);
req[0x00] = 0x12;
req[0x01] = 0x1;
req[0x02] = BIT_7; /* indicate if it's a pure status req */
! QMEM_WR32_REQ(qlt, qi, req + 0x04, cmd->cmd_handle);
! QMEM_WR16_REQ(qlt, qi, req + 0x08, cmd->cmd_rp->rp_handle);
! QMEM_WR32_REQ(qlt, qi, req + 0x10, cmd->cmd_rportid);
! QMEM_WR32_REQ(qlt, qi, req + 0x14, qcmd->fw_xchg_addr);
+ /* handle TMF completion - !!! Important FIX */
+ if (task->task_mgmt_function) {
+ scsi_status =
+ (uint16_t)(scsi_status | FCP_RESP_LEN_VALID);
+
+ /* no sense length, 4 bytes of resp info */
+ QMEM_WR16_REQ(qlt, qi, req + 0x24, 4);
+ }
+
/*
* Mode-specific fields
*/
! QMEM_WR16_REQ(qlt, qi, req + 0x1A, flags);
! QMEM_WR32_REQ(qlt, qi, req + 0x1C, task->task_resid);
! QMEM_WR16_REQ(qlt, qi, req + 0x20, cmd->cmd_oxid);
! QMEM_WR16_REQ(qlt, qi, req + 0x22, scsi_status);
/*
* Trigger FW to send SCSI status out
*/
! qlt_submit_req_entries(qlt, 1, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (STMF_SUCCESS);
}
ASSERT(task->task_scsi_status == STATUS_CHECK);
/*
*** 3679,3692 ****
}
/*
* Fillout CTIO type 7 IOCB
*/
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
if (use_mode2) {
qlt_dmem_free(cmd->cmd_port->port_fds,
qcmd->dbuf_rsp_iu);
qcmd->dbuf_rsp_iu = NULL;
}
--- 5797,5810 ----
}
/*
* Fillout CTIO type 7 IOCB
*/
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! mutex_exit(&qlt->mq_req[qi].mq_lock);
if (use_mode2) {
qlt_dmem_free(cmd->cmd_port->port_fds,
qcmd->dbuf_rsp_iu);
qcmd->dbuf_rsp_iu = NULL;
}
*** 3698,3732 ****
*/
bzero(req, IOCB_SIZE);
req[0x00] = 0x12;
req[0x01] = 0x1;
req[0x02] = BIT_7; /* to indicate if it's a pure status req */
! QMEM_WR32(qlt, req + 0x04, cmd->cmd_handle);
! QMEM_WR16(qlt, req + 0x08, cmd->cmd_rp->rp_handle);
! QMEM_WR16(qlt, req + 0x0A, 0); /* not timed by FW */
if (use_mode2) {
! QMEM_WR16(qlt, req+0x0C, 1); /* FCP RSP IU data field */
}
! QMEM_WR32(qlt, req + 0x10, cmd->cmd_rportid);
! QMEM_WR32(qlt, req + 0x14, qcmd->fw_xchg_addr);
/*
* Mode-specific fields
*/
if (!use_mode2) {
! QMEM_WR16(qlt, req + 0x18, task->task_sense_length);
}
! QMEM_WR16(qlt, req + 0x1A, flags);
! QMEM_WR32(qlt, req + 0x1C, task->task_resid);
! QMEM_WR16(qlt, req + 0x20, cmd->cmd_oxid);
if (use_mode2) {
bctl = (qlt_dmem_bctl_t *)qcmd->dbuf_rsp_iu->db_port_private;
! QMEM_WR32(qlt, req + 0x2C, 24 + task->task_sense_length);
! QMEM_WR64(qlt, req + 0x34, bctl->bctl_dev_addr);
! QMEM_WR32(qlt, req + 0x3C, 24 + task->task_sense_length);
} else {
! QMEM_WR16(qlt, req + 0x22, scsi_status);
psd = req+0x28;
/*
* Data in sense buf is always big-endian, data in IOCB
* should always be little-endian, so we must do swapping.
--- 5816,5853 ----
*/
bzero(req, IOCB_SIZE);
req[0x00] = 0x12;
req[0x01] = 0x1;
req[0x02] = BIT_7; /* to indicate if it's a pure status req */
! QMEM_WR32_REQ(qlt, qi, req + 0x04, cmd->cmd_handle);
! QMEM_WR16_REQ(qlt, qi, req + 0x08, cmd->cmd_rp->rp_handle);
! QMEM_WR16_REQ(qlt, qi, req + 0x0A, 0); /* not timed by FW */
if (use_mode2) {
! /* FCP RSP IU data field */
! QMEM_WR16_REQ(qlt, qi, req+0x0C, 1);
}
! QMEM_WR32_REQ(qlt, qi, req + 0x10, cmd->cmd_rportid);
! QMEM_WR32_REQ(qlt, qi, req + 0x14, qcmd->fw_xchg_addr);
/*
* Mode-specific fields
*/
if (!use_mode2) {
! QMEM_WR16_REQ(qlt, qi, req + 0x18, task->task_sense_length);
}
! QMEM_WR16_REQ(qlt, qi, req + 0x1A, flags);
! QMEM_WR32_REQ(qlt, qi, req + 0x1C, task->task_resid);
! QMEM_WR16_REQ(qlt, qi, req + 0x20, cmd->cmd_oxid);
if (use_mode2) {
bctl = (qlt_dmem_bctl_t *)qcmd->dbuf_rsp_iu->db_port_private;
! QMEM_WR32_REQ(qlt, qi, req + 0x2C,
! 24 + task->task_sense_length);
! QMEM_WR64_REQ(qlt, qi, req + 0x34, bctl->bctl_dev_addr);
! QMEM_WR32_REQ(qlt, qi, req + 0x3C,
! 24 + task->task_sense_length);
} else {
! QMEM_WR16_REQ(qlt, qi, req + 0x22, scsi_status);
psd = req+0x28;
/*
* Data in sense buf is always big-endian, data in IOCB
* should always be little-endian, so we must do swapping.
*** 3741,3752 ****
}
/*
* Trigger FW to send SCSI status out
*/
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
return (STMF_SUCCESS);
}
fct_status_t
--- 5862,5873 ----
}
/*
* Trigger FW to send SCSI status out
*/
! qlt_submit_req_entries(qlt, 1, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (STMF_SUCCESS);
}
fct_status_t
*** 3756,3765 ****
--- 5877,5887 ----
fct_els_t *els = (fct_els_t *)cmd->cmd_specific;
uint8_t *req, *addr;
qlt_dmem_bctl_t *bctl;
uint32_t minsize;
uint8_t elsop, req1f;
+ uint16_t qi = 0;
addr = els->els_resp_payload;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
minsize = els->els_resp_size;
*** 3781,3794 ****
if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) ||
(elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) {
req1f = (uint8_t)(req1f | BIT_4);
}
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
qlt_dmem_free(NULL, qcmd->dbuf);
qcmd->dbuf = NULL;
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
--- 5903,5918 ----
if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) ||
(elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) {
req1f = (uint8_t)(req1f | BIT_4);
}
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! EL(qlt, "req = NULL, %xh %xh %p %xh\n", cmd->cmd_oxid,
! cmd->cmd_rportid, cmd, qcmd->fw_xchg_addr);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
qlt_dmem_free(NULL, qcmd->dbuf);
qcmd->dbuf = NULL;
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
*** 3805,3817 ****
req[0x1d] = (uint8_t)((cmd->cmd_lportid >> 8) & 0xff);
}
QMEM_WR32(qlt, (&req[0x24]), els->els_resp_size);
QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr);
QMEM_WR32(qlt, (&req[0x30]), els->els_resp_size);
- qlt_submit_req_entries(qlt, 1);
- mutex_exit(&qlt->req_lock);
return (FCT_SUCCESS);
}
fct_status_t
qlt_send_abts_response(qlt_state_t *qlt, fct_cmd_t *cmd, int terminate)
--- 5929,5945 ----
req[0x1d] = (uint8_t)((cmd->cmd_lportid >> 8) & 0xff);
}
QMEM_WR32(qlt, (&req[0x24]), els->els_resp_size);
QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr);
QMEM_WR32(qlt, (&req[0x30]), els->els_resp_size);
+ EL(qlt, "elsop=%xh req1f=%xh IOCB_TYPE_ELSPASS: rex1=%xh\n",
+ elsop, req1f, qcmd->fw_xchg_addr);
+
+ qlt_submit_req_entries(qlt, 1, qi);
+ mutex_exit(&qlt->mq_req[qi].mq_lock);
+
return (FCT_SUCCESS);
}
fct_status_t
qlt_send_abts_response(qlt_state_t *qlt, fct_cmd_t *cmd, int terminate)
*** 3820,3836 ****
fct_rcvd_abts_t *abts = (fct_rcvd_abts_t *)cmd->cmd_specific;
uint8_t *req;
uint32_t lportid;
uint32_t fctl;
int i;
qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private;
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
return (FCT_BUSY);
}
bcopy(qcmd->buf, req, IOCB_SIZE);
lportid = QMEM_RD32(qlt, req+0x14) & 0xFFFFFF;
fctl = QMEM_RD32(qlt, req+0x1C);
--- 5948,5983 ----
fct_rcvd_abts_t *abts = (fct_rcvd_abts_t *)cmd->cmd_specific;
uint8_t *req;
uint32_t lportid;
uint32_t fctl;
int i;
+ uint16_t qi;
+ uint32_t rex1, rex2;
+ uint8_t temp[64];
+ qi = 0;
+
qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private;
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! bcopy(qcmd->buf, &temp, IOCB_SIZE);
! for (i = 0; i < 12; i += 4) {
! /* Take care of firmware's LE requirement */
! temp[0x2C+i] = abts->abts_resp_payload[i+3];
! temp[0x2C+i+1] = abts->abts_resp_payload[i+2];
! temp[0x2C+i+2] = abts->abts_resp_payload[i+1];
! temp[0x2C+i+3] = abts->abts_resp_payload[i];
! }
! rex1 = QMEM_RD32(qlt, &temp[0x10]);
! rex2 = QMEM_RD32(qlt, &temp[0x3C]);
!
! EL(qlt, "req = NULL, %xh %xh %p %xh %xh\n", cmd->cmd_oxid,
! cmd->cmd_rportid, cmd, rex1, rex2);
!
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_BUSY);
}
bcopy(qcmd->buf, req, IOCB_SIZE);
lportid = QMEM_RD32(qlt, req+0x14) & 0xFFFFFF;
fctl = QMEM_RD32(qlt, req+0x1C);
*** 3854,3881 ****
req[0x2C+i] = abts->abts_resp_payload[i+3];
req[0x2C+i+1] = abts->abts_resp_payload[i+2];
req[0x2C+i+2] = abts->abts_resp_payload[i+1];
req[0x2C+i+3] = abts->abts_resp_payload[i];
}
- qlt_submit_req_entries(qlt, 1);
- mutex_exit(&qlt->req_lock);
return (FCT_SUCCESS);
}
static void
qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot)
{
int i;
uint32_t d;
caddr_t req;
/* Just put it on the request queue */
! mutex_enter(&qlt->req_lock);
! req = qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
! /* XXX handle this */
return;
}
for (i = 0; i < 16; i++) {
d = QMEM_RD32(qlt, inot);
inot += 4;
--- 6001,6043 ----
req[0x2C+i] = abts->abts_resp_payload[i+3];
req[0x2C+i+1] = abts->abts_resp_payload[i+2];
req[0x2C+i+2] = abts->abts_resp_payload[i+1];
req[0x2C+i+3] = abts->abts_resp_payload[i];
}
+ rex1 = QMEM_RD32(qlt, &req[0x10]);
+ rex2 = QMEM_RD32(qlt, &req[0x3C]);
+
+ EL(qlt, "%xh %xh %d %p %xh %xh\n",
+ QMEM_RD16(qlt, req+0x26), QMEM_RD16(qlt, req+0x24),
+ terminate, cmd, rex1, rex2);
+
+ qlt_submit_req_entries(qlt, 1, qi);
+ mutex_exit(&qlt->mq_req[qi].mq_lock);
+
return (FCT_SUCCESS);
}
static void
qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot)
{
int i;
uint32_t d;
caddr_t req;
+ uint16_t qi;
+ uint8_t *entry = inot;
+
+ qi = 0;
+
/* Just put it on the request queue */
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! mutex_exit(&qlt->mq_req[qi].mq_lock);
! stmf_trace(qlt->qlt_port_alias,
! "qlt_handle_inot: can't get a ReqQ entry");
! EL(qlt, "req = NULL\n");
return;
}
for (i = 0; i < 16; i++) {
d = QMEM_RD32(qlt, inot);
inot += 4;
*** 3882,3895 ****
QMEM_WR32(qlt, req, d);
req += 4;
}
req -= 64;
req[0] = 0x0e;
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
}
uint8_t qlt_task_flags[] = { 1, 3, 2, 1, 4, 0, 1, 1 };
static void
qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio)
{
fct_cmd_t *cmd;
--- 6044,6131 ----
QMEM_WR32(qlt, req, d);
req += 4;
}
req -= 64;
req[0] = 0x0e;
!
! QMEM_WR32(qlt, entry+0x3c, 0xdeadbeef);
! EL(qlt, "Issue inot ack\n");
!
! qlt_submit_req_entries(qlt, 1, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
}
+ static uint16_t
+ qlt_get_queue_id(qlt_state_t *qlt, int id)
+ {
+ uint16_t qid;
+
+ if ((!qlt->qlt_mq_enabled) || (qlt->qlt_queue_cnt == 1)) {
+ return (0);
+ }
+
+ mutex_enter(&qlt->qlock);
+ if ((id == 0) && (qlt->last_qi == 0)) {
+ qlt->last_qi++;
+ }
+ qid = qlt->last_qi;
+ qlt->last_qi++;
+
+ if (qlt->last_qi >= qlt->qlt_queue_cnt) {
+ qlt->last_qi -= qlt->qlt_queue_cnt;
+ }
+ mutex_exit(&qlt->qlock);
+
+ return (qid);
+ }
+
+ static fct_status_t
+ qlt_verify_atio_entry(qlt_state_t *qlt, uint8_t *atio)
+ {
+ uint32_t sig;
+ int i;
+ char info[160];
+
+
+ sig = QMEM_RD32(qlt, atio+0x3c);
+ for (i = 0; ((sig == 0xdeadbeef) &&
+ (i < qlt_reprocess_attempt_cnt)); i++) {
+ (void) ddi_dma_sync(
+ qlt->queue_mem_dma_handle,
+ ATIO_QUEUE_OFFSET + (qlt->atio_ndx_to_fw << 6),
+ IOCB_SIZE, DDI_DMA_SYNC_FORCPU);
+
+ qlt->qlt_atio_reproc_cnt++;
+ drv_usecwait(qlt_reprocess_delay);
+ sig = QMEM_RD32(qlt, atio+0x3c);
+ }
+
+ if (i) {
+ if (i >= qlt_reprocess_attempt_cnt) {
+ EL(qlt, "atio entry reprocess failed, %x\n",
+ qlt->qlt_atio_reproc_cnt);
+ cmn_err(CE_WARN, "qlt%d: atio entry reprocess"
+ " failed %x\n",
+ qlt->instance, qlt->qlt_atio_reproc_cnt);
+ (void) snprintf(info, 160,
+ "qlt_handle_ctio_completion: atio entry reprocess"
+ " failed, %x rsp-%p",
+ qlt->qlt_atio_reproc_cnt, (void *)atio);
+ info[159] = 0;
+ (void) fct_port_shutdown(qlt->qlt_port,
+ STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
+ STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
+ return (QLT_FAILURE);
+ } else {
+ EL(qlt, "atio entry reprocess succeeded, %x %x\n",
+ i, qlt->qlt_atio_reproc_cnt);
+ }
+ }
+
+ return (QLT_SUCCESS);
+ }
+
uint8_t qlt_task_flags[] = { 1, 3, 2, 1, 4, 0, 1, 1 };
static void
qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio)
{
fct_cmd_t *cmd;
*** 3896,3907 ****
scsi_task_t *task;
qlt_cmd_t *qcmd;
uint32_t rportid, fw_xchg_addr;
uint8_t *p, *q, *req, tm;
uint16_t cdb_size, flags, oxid;
! char info[QLT_INFO_LEN];
/*
* If either bidirection xfer is requested of there is extended
* CDB, atio[0x20 + 11] will be greater than or equal to 3.
*/
cdb_size = 16;
--- 6132,6147 ----
scsi_task_t *task;
qlt_cmd_t *qcmd;
uint32_t rportid, fw_xchg_addr;
uint8_t *p, *q, *req, tm;
uint16_t cdb_size, flags, oxid;
! char info[160];
! uint16_t qi;
+ if (qlt_verify_atio_entry(qlt, atio) != QLT_SUCCESS)
+ return;
+
/*
* If either bidirection xfer is requested of there is extended
* CDB, atio[0x20 + 11] will be greater than or equal to 3.
*/
cdb_size = 16;
*** 3950,3971 ****
if (cmd == NULL) {
EL(qlt, "fct_scsi_task_alloc cmd==NULL\n");
}
}
if (cmd == NULL) {
EL(qlt, "fct_scsi_task_alloc cmd==NULL\n");
/* Abort this IO */
flags = (uint16_t)(BIT_14 | ((atio[3] & 0xF0) << 5));
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
! (void) snprintf(info, sizeof (info),
"qlt_handle_atio: qlt-%p, can't "
"allocate space for scsi_task", (void *)qlt);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
bzero(req, IOCB_SIZE);
--- 6190,6214 ----
if (cmd == NULL) {
EL(qlt, "fct_scsi_task_alloc cmd==NULL\n");
}
}
if (cmd == NULL) {
+ qi = 0; /* just use request queue 0 */
+
EL(qlt, "fct_scsi_task_alloc cmd==NULL\n");
/* Abort this IO */
flags = (uint16_t)(BIT_14 | ((atio[3] & 0xF0) << 5));
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! mutex_exit(&qlt->mq_req[0].mq_lock);
! (void) snprintf(info, 160,
"qlt_handle_atio: qlt-%p, can't "
"allocate space for scsi_task", (void *)qlt);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
bzero(req, IOCB_SIZE);
*** 3976,3995 ****
QMEM_WR16(qlt, req+10, 60);
QMEM_WR32(qlt, req+0x10, rportid);
QMEM_WR32(qlt, req+0x14, fw_xchg_addr);
QMEM_WR16(qlt, req+0x1A, flags);
QMEM_WR16(qlt, req+0x20, oxid);
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
return;
}
task = (scsi_task_t *)cmd->cmd_specific;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
qcmd->fw_xchg_addr = fw_xchg_addr;
qcmd->param.atio_byte3 = atio[3];
cmd->cmd_oxid = oxid;
cmd->cmd_rxid = (uint16_t)((((uint16_t)atio[8 + 18]) << 8) |
atio[8+19]);
cmd->cmd_rportid = rportid;
cmd->cmd_lportid = (((uint32_t)atio[8 + 1]) << 16) |
--- 6219,6333 ----
QMEM_WR16(qlt, req+10, 60);
QMEM_WR32(qlt, req+0x10, rportid);
QMEM_WR32(qlt, req+0x14, fw_xchg_addr);
QMEM_WR16(qlt, req+0x1A, flags);
QMEM_WR16(qlt, req+0x20, oxid);
! qlt_submit_req_entries(qlt, 1, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return;
}
+ if (cmd == NULL) {
+ uint32_t res;
+ uint16_t scsi_status = 0;
+ uint16_t rphdl = 0;
+ qi = 0; /* always use request queue 0 */
+
+ rphdl = fct_get_rp_handle(qlt->qlt_port, rportid);
+ if ((rphdl != 0xFFFF) &&
+ (rphdl >= qlt->qlt_port->port_max_logins)) {
+ rphdl = 0xFFFF;
+ }
+
+ mutex_enter(&qlt->mq_req[qi].mq_lock);
+ req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
+ if (req == NULL) {
+ EL(qlt, "cannot get reqq\n");
+ mutex_exit(&qlt->mq_req[qi].mq_lock);
+ (void) snprintf(info, 160,
+ "qlt_handle_atio: qlt-%p, can't "
+ "allocate space for termi-excg", (void *)qlt);
+ info[159] = 0;
+ (void) fct_port_shutdown(qlt->qlt_port,
+ STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
+ return;
+ }
+
+ if (rphdl != 0xFFFF) {
+ /* Driver send scsi qfull status now */
+ flags = (uint16_t)(BIT_15 |
+ ((uint16_t)(atio[0x3] & 0xF0) << 5));
+ /* always use SCSI status mode 1 */
+ flags = (uint16_t)(flags | BIT_6);
+
+ scsi_status |= (uint16_t)(0x28);
+
+ /* Build SCSI Status Mode 1, FCP_RSP IU 24-48 byte */
+ bzero(req, IOCB_SIZE);
+ req[0] = 0x12;
+ req[1] = 0x1;
+
+ /* allocate a special IOCB handle? or donot care */
+ QMEM_WR32(qlt, req+4, 0);
+ QMEM_WR16(qlt, req+8, rphdl);
+ QMEM_WR16(qlt, req+10, 60);
+ QMEM_WR32(qlt, req+0x10, rportid);
+ QMEM_WR32(qlt, req+0x14, fw_xchg_addr);
+
+ /* sense_length set to 0 */
+ QMEM_WR16(qlt, req+0x18, 0);
+
+ QMEM_WR16(qlt, req+0x1A, flags);
+
+ /* Residual transfer length */
+ res = QMEM_RD32(qlt, atio+0x3C);
+ BIG_ENDIAN_32(&res);
+ if (res != 0) {
+ scsi_status |= FCP_RESID_UNDER;
+ }
+ QMEM_WR32_REQ(qlt, qi, req + 0x1C, res);
+
+ QMEM_WR16(qlt, req+0x20, oxid);
+ QMEM_WR16_REQ(qlt, qi, req + 0x22, scsi_status);
+
+ EL(qlt, "Send qfull (%Xh) (%Xh)(%Xh)(%Xh) from port "
+ "(%Xh:%Xh)\n", scsi_status, fw_xchg_addr, flags,
+ oxid, rportid, rphdl);
+ } else {
+ /* Terminate exchange because no remote port context */
+ flags = (uint16_t)(BIT_14 | ((atio[3] & 0xF0) << 5));
+
+ bzero(req, IOCB_SIZE);
+ req[0] = 0x12;
+ req[1] = 0x1;
+
+ QMEM_WR32(qlt, req+4, 0);
+ QMEM_WR16(qlt, req+8, rphdl);
+ QMEM_WR16(qlt, req+10, 60);
+ QMEM_WR32(qlt, req+0x10, rportid);
+ QMEM_WR32(qlt, req+0x14, fw_xchg_addr);
+ QMEM_WR16(qlt, req+0x1A, flags);
+ QMEM_WR16(qlt, req+0x20, oxid);
+
+ EL(qlt, "Termi excg (%Xh)(%Xh)(%Xh) from port (%Xh)\n",
+ fw_xchg_addr, flags, oxid, rportid);
+
+ EL(qlt, "Termi rp_handle (%Xh)\n", rphdl);
+ }
+
+ qlt_submit_req_entries(qlt, 1, qi);
+ mutex_exit(&qlt->mq_req[qi].mq_lock);
+ return;
+ }
+
+ qi = qlt_get_queue_id(qlt, 0);
task = (scsi_task_t *)cmd->cmd_specific;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
qcmd->fw_xchg_addr = fw_xchg_addr;
qcmd->param.atio_byte3 = atio[3];
+ qcmd->qid = qi;
cmd->cmd_oxid = oxid;
cmd->cmd_rxid = (uint16_t)((((uint16_t)atio[8 + 18]) << 8) |
atio[8+19]);
cmd->cmd_rportid = rportid;
cmd->cmd_lportid = (((uint32_t)atio[8 + 1]) << 16) |
*** 4052,4061 ****
--- 6390,6401 ----
} else {
task->task_expected_xfer_length = (((uint32_t)q[0]) << 24) |
(((uint32_t)q[1]) << 16) |
(((uint32_t)q[2]) << 8) | q[3];
}
+
+ QMEM_WR32(qlt, atio+0x3c, 0xdeadbeef);
fct_post_rcvd_cmd(cmd, 0);
}
static void
qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp)
*** 4067,4085 ****
--- 6407,6433 ----
status = QMEM_RD16(qlt, rsp+8);
portid = QMEM_RD32(qlt, rsp+0x10) & 0xffffff;
subcode1 = QMEM_RD32(qlt, rsp+0x14);
subcode2 = QMEM_RD32(qlt, rsp+0x18);
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ mutex_enter(&qlt->mq_req[0].mq_lock);
+ } else {
mutex_enter(&qlt->preq_lock);
+ }
if (portid != qlt->rp_id_in_dereg) {
int instance = ddi_get_instance(qlt->dip);
EL(qlt, "implicit logout reveived portid = %xh\n", portid);
cmn_err(CE_WARN, "qlt(%d): implicit logout completion for 0x%x"
" received when driver wasn't waiting for it",
instance, portid);
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ mutex_exit(&qlt->mq_req[0].mq_lock);
+ } else {
mutex_exit(&qlt->preq_lock);
+ }
return;
}
if (status != 0) {
EL(qlt, "implicit logout completed for %xh with status %xh, "
*** 4096,4138 ****
}
} else {
qlt->rp_dereg_status = FCT_SUCCESS;
}
cv_signal(&qlt->rp_dereg_cv);
mutex_exit(&qlt->preq_lock);
}
/*
* Note that when an ELS is aborted, the regular or aborted completion
* (if any) gets posted before the abort IOCB comes back on response queue.
*/
static void
qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp)
{
! char info[QLT_INFO_LEN];
fct_cmd_t *cmd;
qlt_cmd_t *qcmd;
uint32_t hndl;
uint32_t subcode1, subcode2;
uint16_t status;
hndl = QMEM_RD32(qlt, rsp+4);
status = QMEM_RD16(qlt, rsp+8);
subcode1 = QMEM_RD32(qlt, rsp+0x24);
subcode2 = QMEM_RD32(qlt, rsp+0x28);
if (!CMD_HANDLE_VALID(hndl)) {
EL(qlt, "handle = %xh\n", hndl);
/*
* This cannot happen for unsol els completion. This can
* only happen when abort for an unsol els completes.
* This condition indicates a firmware bug.
*/
! (void) snprintf(info, sizeof (info),
! "qlt_handle_unsol_els_completion: "
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
hndl, status, subcode1, subcode2, (void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
--- 6444,6492 ----
}
} else {
qlt->rp_dereg_status = FCT_SUCCESS;
}
cv_signal(&qlt->rp_dereg_cv);
+ if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
+ mutex_exit(&qlt->mq_req[0].mq_lock);
+ } else {
mutex_exit(&qlt->preq_lock);
+ }
}
/*
* Note that when an ELS is aborted, the regular or aborted completion
* (if any) gets posted before the abort IOCB comes back on response queue.
*/
static void
qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp)
{
! char info[160];
fct_cmd_t *cmd;
qlt_cmd_t *qcmd;
uint32_t hndl;
uint32_t subcode1, subcode2;
uint16_t status;
+ uint8_t elsop;
hndl = QMEM_RD32(qlt, rsp+4);
status = QMEM_RD16(qlt, rsp+8);
subcode1 = QMEM_RD32(qlt, rsp+0x24);
subcode2 = QMEM_RD32(qlt, rsp+0x28);
+ elsop = rsp[0x16];
if (!CMD_HANDLE_VALID(hndl)) {
EL(qlt, "handle = %xh\n", hndl);
/*
* This cannot happen for unsol els completion. This can
* only happen when abort for an unsol els completes.
* This condition indicates a firmware bug.
*/
! (void) snprintf(info, 160, "qlt_handle_unsol_els_completion: "
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
hndl, status, subcode1, subcode2, (void *)rsp);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
*** 4153,4166 ****
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
/*
* Now why would this happen ???
*/
! (void) snprintf(info, sizeof (info),
"qlt_handle_unsol_els_completion: can not "
"get cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
--- 6507,6521 ----
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
/*
* Now why would this happen ???
*/
! (void) snprintf(info, 160,
"qlt_handle_unsol_els_completion: can not "
"get cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
*** 4184,4203 ****
qcmd->dbuf = NULL;
}
if (status == 0) {
fct_send_response_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
} else {
fct_send_response_done(cmd,
QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0);
}
}
static void
qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt, uint8_t *rsp)
{
! char info[QLT_INFO_LEN];
fct_cmd_t *cmd;
qlt_cmd_t *qcmd;
uint32_t hndl;
uint32_t subcode1, subcode2;
uint16_t status;
--- 6539,6574 ----
qcmd->dbuf = NULL;
}
if (status == 0) {
fct_send_response_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
+
+ if ((elsop == ELS_OP_LOGO) &&
+ (qlt->cur_topology == PORT_TOPOLOGY_PT_TO_PT)) {
+ EL(qlt, "reset link since this is LOGO and N2N\n");
+ (void) snprintf(info, 80,
+ "qlt_handle_unsol_els_completion: qlt-%p, "
+ "trigger RFLAG_RESET to recover",
+ (void *)qlt);
+
+ info[79] = 0;
+ (void) fct_port_shutdown(qlt->qlt_port,
+ STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
+ info);
+ }
} else {
+ EL(qlt, "status (0xh) sucode1=%xh subconde2=%xh\n",
+ status, subcode1, subcode2);
fct_send_response_done(cmd,
QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0);
}
}
static void
qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt, uint8_t *rsp)
{
! char info[160];
fct_cmd_t *cmd;
qlt_cmd_t *qcmd;
uint32_t hndl;
uint32_t subcode1, subcode2;
uint16_t status;
*** 4218,4231 ****
EL(qlt, "status = %xh\n", status);
/*
* There could be exchange resource leakage, so
* throw HBA fatal error event now
*/
! (void) snprintf(info, sizeof (info),
"qlt_handle_unsol_els_abort_completion: "
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
hndl, status, subcode1, subcode2, (void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
--- 6589,6603 ----
EL(qlt, "status = %xh\n", status);
/*
* There could be exchange resource leakage, so
* throw HBA fatal error event now
*/
! (void) snprintf(info, 160,
"qlt_handle_unsol_els_abort_completion: "
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
hndl, status, subcode1, subcode2, (void *)rsp);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
*** 4237,4250 ****
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
/*
* Why would this happen ??
*/
! (void) snprintf(info, sizeof (info),
"qlt_handle_unsol_els_abort_completion: can not get "
"cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
--- 6609,6623 ----
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
/*
* Why would this happen ??
*/
! (void) snprintf(info, 160,
"qlt_handle_unsol_els_abort_completion: can not get "
"cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
*** 4269,4279 ****
}
static void
qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp)
{
! char info[QLT_INFO_LEN];
fct_cmd_t *cmd;
fct_els_t *els;
qlt_cmd_t *qcmd;
uint32_t hndl;
uint32_t subcode1, subcode2;
--- 6642,6652 ----
}
static void
qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp)
{
! char info[160];
fct_cmd_t *cmd;
fct_els_t *els;
qlt_cmd_t *qcmd;
uint32_t hndl;
uint32_t subcode1, subcode2;
*** 4287,4313 ****
if (!CMD_HANDLE_VALID(hndl)) {
EL(qlt, "handle = %xh\n", hndl);
/*
* This cannot happen for sol els completion.
*/
! (void) snprintf(info, sizeof (info),
! "qlt_handle_sol_els_completion: "
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
hndl, status, subcode1, subcode2, (void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
! (void) snprintf(info, sizeof (info),
"qlt_handle_sol_els_completion: can not "
"get cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
--- 6660,6687 ----
if (!CMD_HANDLE_VALID(hndl)) {
EL(qlt, "handle = %xh\n", hndl);
/*
* This cannot happen for sol els completion.
*/
! (void) snprintf(info, 160, "qlt_handle_sol_els_completion: "
"Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
hndl, status, subcode1, subcode2, (void *)rsp);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
! (void) snprintf(info, 160,
"qlt_handle_sol_els_completion: can not "
"get cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
*** 4349,4384 ****
fct_cmd_t *cmd;
fct_sol_ct_t *ct;
qlt_cmd_t *qcmd;
uint32_t hndl;
uint16_t status;
! char info[QLT_INFO_LEN];
hndl = QMEM_RD32(qlt, rsp+4);
status = QMEM_RD16(qlt, rsp+8);
if (!CMD_HANDLE_VALID(hndl)) {
EL(qlt, "handle = %xh\n", hndl);
/*
* Solicited commands will always have a valid handle.
*/
! (void) snprintf(info, sizeof (info),
! "qlt_handle_ct_completion: "
! "hndl-%x, status-%x, rsp-%p", hndl, status, (void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
! (void) snprintf(info, sizeof (info),
"qlt_handle_ct_completion: cannot find "
"cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
--- 6723,6760 ----
fct_cmd_t *cmd;
fct_sol_ct_t *ct;
qlt_cmd_t *qcmd;
uint32_t hndl;
uint16_t status;
! char info[160];
hndl = QMEM_RD32(qlt, rsp+4);
status = QMEM_RD16(qlt, rsp+8);
if (!CMD_HANDLE_VALID(hndl)) {
EL(qlt, "handle = %xh\n", hndl);
/*
* Solicited commands will always have a valid handle.
*/
! (void) snprintf(info, 160, "qlt_handle_ct_completion: hndl-"
! "%x, status-%x, rsp-%p", hndl, status, (void *)rsp);
! info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
+ EL(qlt, "cmd=%ph hndl=%xh status=%xh\n", cmd, hndl, status);
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
! (void) snprintf(info, 160,
"qlt_handle_ct_completion: cannot find "
"cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
*** 4393,4438 ****
*/
return;
}
ASSERT(qcmd->dbuf);
! if (status == 0) {
qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORKERNEL);
bcopy(qcmd->dbuf->db_sglist[0].seg_addr +
qcmd->param.resp_offset,
ct->ct_resp_payload, ct->ct_resp_size);
}
qlt_dmem_free(NULL, qcmd->dbuf);
qcmd->dbuf = NULL;
! if (status == 0) {
fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
} else {
fct_send_cmd_done(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0);
}
}
static void
! qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp)
{
fct_cmd_t *cmd;
scsi_task_t *task;
qlt_cmd_t *qcmd;
stmf_data_buf_t *dbuf;
fct_status_t fc_st;
uint32_t iof = 0;
uint32_t hndl;
uint16_t status;
uint16_t flags;
uint8_t abort_req;
uint8_t n;
! char info[QLT_INFO_LEN];
/* XXX: Check validity of the IOCB by checking 4th byte. */
! hndl = QMEM_RD32(qlt, rsp+4);
! status = QMEM_RD16(qlt, rsp+8);
! flags = QMEM_RD16(qlt, rsp+0x1a);
n = rsp[2];
if (!CMD_HANDLE_VALID(hndl)) {
EL(qlt, "handle = %xh\n", hndl);
ASSERT(hndl == 0);
--- 6769,6869 ----
*/
return;
}
ASSERT(qcmd->dbuf);
! if ((status == 0) || (status == 0x15)) {
qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORKERNEL);
bcopy(qcmd->dbuf->db_sglist[0].seg_addr +
qcmd->param.resp_offset,
ct->ct_resp_payload, ct->ct_resp_size);
}
qlt_dmem_free(NULL, qcmd->dbuf);
qcmd->dbuf = NULL;
! if ((status == 0) || (status == 0x15)) {
fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
} else {
fct_send_cmd_done(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0);
}
}
+ static fct_status_t
+ qlt_verify_resp_entry(qlt_state_t *qlt, uint8_t *rsp, uint16_t qi)
+ {
+ uint32_t sig;
+ int i;
+ char info[160];
+
+ sig = QMEM_RD32_RSPQ(qlt, qi, rsp+0x3c);
+ for (i = 0; ((sig == 0xdeadbeef) &&
+ (i < qlt_reprocess_attempt_cnt)); i++) {
+ (void) ddi_dma_sync(
+ qlt->mq_resp[qi].queue_mem_mq_dma_handle,
+ (qlt->mq_resp[qi].mq_ndx_to_fw << 6),
+ IOCB_SIZE, DDI_DMA_SYNC_FORCPU);
+
+ qlt->qlt_resp_reproc_cnt++;
+ drv_usecwait(qlt_reprocess_delay);
+ sig = QMEM_RD32_RSPQ(qlt, qi, rsp+0x3c);
+ }
+
+ if (i) {
+ if (i >= qlt_reprocess_attempt_cnt) {
+ EL(qlt, "resp entry reprocess failed, %x\n",
+ qlt->qlt_resp_reproc_cnt);
+ cmn_err(CE_WARN, "qlt%d: resp entry reprocess"
+ " failed %x\n",
+ qlt->instance, qlt->qlt_resp_reproc_cnt);
+ (void) snprintf(info, 160,
+ "qlt_handle_ctio_completion: resp entry reprocess"
+ " failed, %x rsp-%p",
+ qlt->qlt_resp_reproc_cnt, (void *)rsp);
+ info[159] = 0;
+ (void) fct_port_shutdown(qlt->qlt_port,
+ STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
+ info);
+ return (QLT_FAILURE);
+ } else {
+ EL(qlt, "resp entry reprocess succeeded, %x %x\n",
+ i, qlt->qlt_resp_reproc_cnt);
+ }
+ }
+
+ return (QLT_SUCCESS);
+ }
+
static void
! qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp, uint16_t qi)
{
fct_cmd_t *cmd;
scsi_task_t *task;
qlt_cmd_t *qcmd;
stmf_data_buf_t *dbuf;
fct_status_t fc_st;
uint32_t iof = 0;
uint32_t hndl;
+ uint32_t rex1;
+ uint16_t oxid;
uint16_t status;
uint16_t flags;
uint8_t abort_req;
uint8_t n;
! char info[160];
+ if (qlt_verify_resp_entry(qlt, rsp, qi) != QLT_SUCCESS)
+ return;
+
+ /* write a deadbeef in the last 4 bytes of the IOCB */
+ QMEM_WR32_RSPQ(qlt, qi, rsp+0x3c, 0xdeadbeef);
+
/* XXX: Check validity of the IOCB by checking 4th byte. */
! hndl = QMEM_RD32_RSPQ(qlt, qi, rsp+4);
! status = QMEM_RD16_RSPQ(qlt, qi, rsp+8);
! flags = QMEM_RD16_RSPQ(qlt, qi, rsp+0x1a);
! oxid = QMEM_RD16_RSPQ(qlt, qi, rsp+0x20);
! rex1 = QMEM_RD32_RSPQ(qlt, qi, rsp+0x14);
n = rsp[2];
if (!CMD_HANDLE_VALID(hndl)) {
EL(qlt, "handle = %xh\n", hndl);
ASSERT(hndl == 0);
*** 4442,4463 ****
*/
EL(qlt, "hndl-%xh, status-%xh, rsp-%p\n", hndl, status,
(void *)rsp);
if ((status != 1) && (status != 2)) {
EL(qlt, "status = %xh\n", status);
/*
! * There could be exchange resource leakage, so
! * throw HBA fatal error event now
*/
! (void) snprintf(info, sizeof (info),
! "qlt_handle_ctio_completion: hndl-"
! "%x, status-%x, rsp-%p", hndl, status, (void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
! STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
}
return;
}
if (flags & BIT_14) {
abort_req = 1;
--- 6873,6956 ----
*/
EL(qlt, "hndl-%xh, status-%xh, rsp-%p\n", hndl, status,
(void *)rsp);
if ((status != 1) && (status != 2)) {
EL(qlt, "status = %xh\n", status);
+ if (status == 0x29) {
+ uint8_t *req;
+
/*
! * The qlt port received an ATIO request from
! * remote port before it issued a plogi.
! * The qlt fw returned the CTIO completion
! * status 0x29 to inform driver to do cleanup
! * (terminate the IO exchange). The subsequent
! * ABTS from the initiator can be handled
! * cleanly.
*/
! qi = 0;
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)
! qlt_get_req_entries(qlt, 1, qi);
!
! if (req == NULL) {
! EL(qlt, "No reqq entry available to "
! "termi exchg\n");
! mutex_exit(&qlt->mq_req[qi].mq_lock);
!
! (void) snprintf(info, 160,
! "qlt_handle_ctio_completion: no "
! "reqq entry available, status-%x,"
! "rsp-%p", status, (void *)rsp);
!
! info[159] = 0;
!
(void) fct_port_shutdown(qlt->qlt_port,
! STMF_RFLAG_FATAL_ERROR |
! STMF_RFLAG_RESET,
! info);
+ return;
}
+ flags &= 0x1E00;
+ flags |= BIT_14;
+
+ bzero(req, IOCB_SIZE);
+ req[0] = 0x12;
+ req[1] = 0x1;
+
+ QMEM_WR32(qlt, req+4, 0);
+ QMEM_WR16(qlt, req+8, 0xFFFF);
+ QMEM_WR16(qlt, req+10, 60);
+ QMEM_WR32(qlt, req+0x14, rex1);
+ QMEM_WR16(qlt, req+0x1A, flags);
+ QMEM_WR16(qlt, req+0x20, oxid);
+
+ EL(qlt, "Termi exchg (%Xh)(%Xh)(%Xh) "
+ "rphdl=0xFFFF\n", rex1, flags, oxid);
+
+ qlt_submit_req_entries(qlt, 1, qi);
+ mutex_exit(&qlt->mq_req[qi].mq_lock);
+ } else {
+ /*
+ * There could be exchange resource leakage,
+ * so throw HBA fatal error event now
+ */
+ (void) snprintf(info, 160,
+ "qlt_handle_ctio_completion: hndl-%x, "
+ "status-%x, rsp-%p", hndl, status,
+ (void *)rsp);
+
+ info[159] = 0;
+
+ (void) fct_port_shutdown(qlt->qlt_port,
+ STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
+ info);
+ }
+ }
+
return;
}
if (flags & BIT_14) {
abort_req = 1;
*** 4468,4483 ****
}
cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
! (void) snprintf(info, sizeof (info),
"qlt_handle_ctio_completion: cannot find "
"cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
! STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
task = (scsi_task_t *)cmd->cmd_specific;
--- 6961,6979 ----
}
cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
! (void) snprintf(info, 160,
"qlt_handle_ctio_completion: cannot find "
"cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
(void *)rsp);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
! /* STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); */
! STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
! STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
task = (scsi_task_t *)cmd->cmd_specific;
*** 4535,4550 ****
fct_send_response_done(cmd, fc_st, iof);
return;
}
fct_cmd_fca_aborted(cmd, fc_st, iof);
}
static void
qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp)
{
! char info[QLT_INFO_LEN];
fct_cmd_t *cmd;
qlt_cmd_t *qcmd;
uint32_t h;
uint16_t status;
--- 7031,7051 ----
fct_send_response_done(cmd, fc_st, iof);
return;
}
fct_cmd_fca_aborted(cmd, fc_st, iof);
+
+ EL(qlt, "(%d) (%p)(%xh,%xh),%x %x %x\n",
+ qi, cmd, cmd->cmd_oxid, cmd->cmd_rxid,
+ cmd->cmd_handle, qcmd->fw_xchg_addr,
+ fc_st);
}
static void
qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp)
{
! char info[80];
fct_cmd_t *cmd;
qlt_cmd_t *qcmd;
uint32_t h;
uint16_t status;
*** 4554,4566 ****
if (!CMD_HANDLE_VALID(h)) {
EL(qlt, "handle = %xh\n", h);
/*
* Solicited commands always have a valid handle.
*/
! (void) snprintf(info, sizeof (info),
"qlt_handle_sol_abort_completion: hndl-"
"%x, status-%x, rsp-%p", h, status, (void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
--- 7055,7068 ----
if (!CMD_HANDLE_VALID(h)) {
EL(qlt, "handle = %xh\n", h);
/*
* Solicited commands always have a valid handle.
*/
! (void) snprintf(info, 80,
"qlt_handle_sol_abort_completion: hndl-"
"%x, status-%x, rsp-%p", h, status, (void *)rsp);
+ info[79] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
return;
}
*** 4568,4581 ****
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", h);
/*
* What happened to the cmd ??
*/
! (void) snprintf(info, sizeof (info),
"qlt_handle_sol_abort_completion: cannot "
"find cmd, hndl-%x, status-%x, rsp-%p", h, status,
(void *)rsp);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
--- 7070,7084 ----
if (cmd == NULL) {
EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", h);
/*
* What happened to the cmd ??
*/
! (void) snprintf(info, 80,
"qlt_handle_sol_abort_completion: cannot "
"find cmd, hndl-%x, status-%x, rsp-%p", h, status,
(void *)rsp);
+ info[79] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
*** 4586,4595 ****
--- 7089,7099 ----
if (qcmd->dbuf != NULL) {
qlt_dmem_free(NULL, qcmd->dbuf);
qcmd->dbuf = NULL;
}
ASSERT(qcmd->flags & QLT_CMD_ABORTING);
+ EL(qlt, "status=%xh\n", status);
if (status == 0) {
fct_cmd_fca_aborted(cmd, FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
} else if (status == 0x31) {
fct_cmd_fca_aborted(cmd, FCT_NOT_FOUND, FCT_IOF_FCA_DONE);
} else {
*** 4596,4628 ****
fct_cmd_fca_aborted(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0);
}
}
static void
! qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp)
{
qlt_abts_cmd_t *qcmd;
fct_cmd_t *cmd;
uint32_t remote_portid;
! char info[QLT_INFO_LEN];
remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) |
((uint32_t)(resp[0x1A])) << 16;
cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ABTS,
sizeof (qlt_abts_cmd_t), 0);
if (cmd == NULL) {
EL(qlt, "fct_alloc cmd==NULL\n");
! (void) snprintf(info, sizeof (info),
"qlt_handle_rcvd_abts: qlt-%p, can't "
"allocate space for fct_cmd", (void *)qlt);
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
resp[0xC] = resp[0xD] = resp[0xE] = 0;
qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private;
bcopy(resp, qcmd->buf, IOCB_SIZE);
cmd->cmd_port = qlt->qlt_port;
cmd->cmd_rp_handle = QMEM_RD16(qlt, resp+0xA);
if (cmd->cmd_rp_handle == 0xFFFF)
cmd->cmd_rp_handle = FCT_HANDLE_NONE;
--- 7100,7136 ----
fct_cmd_fca_aborted(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0);
}
}
static void
! qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp, uint16_t qi)
{
qlt_abts_cmd_t *qcmd;
fct_cmd_t *cmd;
uint32_t remote_portid;
! uint32_t rex1;
! uint32_t rex2;
! char info[160];
remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) |
((uint32_t)(resp[0x1A])) << 16;
cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ABTS,
sizeof (qlt_abts_cmd_t), 0);
if (cmd == NULL) {
EL(qlt, "fct_alloc cmd==NULL\n");
! (void) snprintf(info, 160,
"qlt_handle_rcvd_abts: qlt-%p, can't "
"allocate space for fct_cmd", (void *)qlt);
+ info[159] = 0;
(void) fct_port_shutdown(qlt->qlt_port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
return;
}
resp[0xC] = resp[0xD] = resp[0xE] = 0;
qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private;
+ qcmd->qid = qi;
bcopy(resp, qcmd->buf, IOCB_SIZE);
cmd->cmd_port = qlt->qlt_port;
cmd->cmd_rp_handle = QMEM_RD16(qlt, resp+0xA);
if (cmd->cmd_rp_handle == 0xFFFF)
cmd->cmd_rp_handle = FCT_HANDLE_NONE;
*** 4630,4658 ****
cmd->cmd_rportid = remote_portid;
cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) |
((uint32_t)(resp[0x16])) << 16;
cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26]));
cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24]));
fct_post_rcvd_cmd(cmd, 0);
}
static void
! qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp)
{
uint16_t status;
! char info[QLT_INFO_LEN];
status = QMEM_RD16(qlt, resp+8);
if ((status == 0) || (status == 5)) {
return;
}
! EL(qlt, "status = %xh\n", status);
! (void) snprintf(info, sizeof (info),
! "ABTS completion failed %x/%x/%x resp_off %x",
status, QMEM_RD32(qlt, resp+0x34), QMEM_RD32(qlt, resp+0x38),
! ((uint32_t)(qlt->resp_ndx_to_fw)) << 6);
(void) fct_port_shutdown(qlt->qlt_port, STMF_RFLAG_FATAL_ERROR |
STMF_RFLAG_RESET | STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
}
#ifdef DEBUG
--- 7138,7182 ----
cmd->cmd_rportid = remote_portid;
cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) |
((uint32_t)(resp[0x16])) << 16;
cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26]));
cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24]));
+
+ rex1 = QMEM_RD32(qlt, resp+0x10);
+ rex2 = QMEM_RD32(qlt, resp+0x3C);
+
+ EL(qlt, "(%d)(%xh %xh) (%xh)(%p) (%xh %xh) (%x)\n",
+ qi, cmd->cmd_oxid, cmd->cmd_rxid, remote_portid,
+ cmd, rex1, rex2, cmd->cmd_handle);
+
fct_post_rcvd_cmd(cmd, 0);
}
static void
! qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp, uint16_t qi)
{
uint16_t status;
! char info[80];
status = QMEM_RD16(qlt, resp+8);
if ((status == 0) || (status == 5)) {
+ EL(qlt, "qi(%d) status =%xh,(%xh %xh)\n",
+ qi, status, QMEM_RD16(qlt, resp+0x26),
+ QMEM_RD16(qlt, resp+0x24));
return;
}
!
! EL(qlt, "ABTS status=%x/%x/%x resp_off %x",
! status, QMEM_RD32(qlt, resp+0x34),
! QMEM_RD32(qlt, resp+0x38),
! ((uint32_t)(qlt->mq_resp[0].mq_ndx_to_fw)) << 6);
!
! (void) snprintf(info, 80, "ABTS completion failed %x/%x/%x resp_off %x",
status, QMEM_RD32(qlt, resp+0x34), QMEM_RD32(qlt, resp+0x38),
! ((uint32_t)(qlt->mq_resp[0].mq_ndx_to_fw)) << 6);
! info[79] = 0;
(void) fct_port_shutdown(qlt->qlt_port, STMF_RFLAG_FATAL_ERROR |
STMF_RFLAG_RESET | STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
}
#ifdef DEBUG
*** 4674,4692 ****
--- 7198,7218 ----
if (atomic_dec_32_nv(&qlt_drop_abort_counter) == 1)
return (FCT_SUCCESS);
}
#endif
+ EL(qlt, "cmd_type = %x\n", cmd->cmd_type);
if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
return (qlt_abort_unsol_scsi_cmd(qlt, cmd));
}
if (flags & FCT_IOF_FORCE_FCA_DONE) {
cmd->cmd_handle = 0;
}
if (cmd->cmd_type == FCT_CMD_RCVD_ABTS) {
+ /* this is retried ABTS, terminate it now */
return (qlt_send_abts_response(qlt, cmd, 1));
}
if (cmd->cmd_type == FCT_CMD_RCVD_ELS) {
return (qlt_abort_purex(qlt, cmd));
*** 4694,4704 ****
if ((cmd->cmd_type == FCT_CMD_SOL_ELS) ||
(cmd->cmd_type == FCT_CMD_SOL_CT)) {
return (qlt_abort_sol_cmd(qlt, cmd));
}
! EL(qlt, "cmd->cmd_type = %xh\n", cmd->cmd_type);
ASSERT(0);
return (FCT_FAILURE);
}
--- 7220,7230 ----
if ((cmd->cmd_type == FCT_CMD_SOL_ELS) ||
(cmd->cmd_type == FCT_CMD_SOL_CT)) {
return (qlt_abort_sol_cmd(qlt, cmd));
}
! EL(qlt, "cmd->cmd_type = %x\n", cmd->cmd_type);
ASSERT(0);
return (FCT_FAILURE);
}
*** 4705,4723 ****
fct_status_t
qlt_abort_sol_cmd(qlt_state_t *qlt, fct_cmd_t *cmd)
{
uint8_t *req;
qlt_cmd_t *qcmd;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
! EL(qlt, "fctcmd-%p, cmd_handle-%xh\n", cmd, cmd->cmd_handle);
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
req[0] = 0x33; req[1] = 1;
--- 7231,7254 ----
fct_status_t
qlt_abort_sol_cmd(qlt_state_t *qlt, fct_cmd_t *cmd)
{
uint8_t *req;
qlt_cmd_t *qcmd;
+ uint16_t qi;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
! qi = qcmd->qid;
! EL(qlt, "fctcmd-%p, cmd_handle-%xh rportid=%xh\n",
! cmd, cmd->cmd_handle, cmd->cmd_rportid);
!
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! EL(qlt, "req == NULL\n");
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
req[0] = 0x33; req[1] = 1;
*** 4728,4739 ****
QMEM_WR16(qlt, req+8, 0xFFFF);
}
QMEM_WR32(qlt, req+0xc, cmd->cmd_handle);
QMEM_WR32(qlt, req+0x30, cmd->cmd_rportid);
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
return (FCT_SUCCESS);
}
fct_status_t
--- 7259,7270 ----
QMEM_WR16(qlt, req+8, 0xFFFF);
}
QMEM_WR32(qlt, req+0xc, cmd->cmd_handle);
QMEM_WR32(qlt, req+0x30, cmd->cmd_rportid);
! qlt_submit_req_entries(qlt, 1, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_SUCCESS);
}
fct_status_t
*** 4741,4767 ****
{
uint8_t *req;
qlt_cmd_t *qcmd;
fct_els_t *els;
uint8_t elsop, req1f;
els = (fct_els_t *)cmd->cmd_specific;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
elsop = els->els_req_payload[0];
! EL(qlt, "fctcmd-%p, cmd_handle-%xh, elsop-%xh\n", cmd, cmd->cmd_handle,
! elsop);
req1f = 0x60; /* Terminate xchg */
if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) ||
(elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) {
req1f = (uint8_t)(req1f | BIT_4);
}
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
!
return (FCT_BUSY);
}
qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
bzero(req, IOCB_SIZE);
--- 7272,7300 ----
{
uint8_t *req;
qlt_cmd_t *qcmd;
fct_els_t *els;
uint8_t elsop, req1f;
+ uint16_t qi;
els = (fct_els_t *)cmd->cmd_specific;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
+ qi = qcmd->qid;
elsop = els->els_req_payload[0];
! EL(qlt, "fctcmd-%p, cmd_handle-%xh, elsop-%xh\n", cmd,
! cmd->cmd_handle, elsop);
req1f = 0x60; /* Terminate xchg */
if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) ||
(elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) {
req1f = (uint8_t)(req1f | BIT_4);
}
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! EL(qlt, "req == NULL\n");
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_BUSY);
}
qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
bzero(req, IOCB_SIZE);
*** 4776,4787 ****
EL(qlt, "cmd_rp_handle-%x\n", cmd->cmd_rp_handle);
}
QMEM_WR32(qlt, (&req[0x10]), qcmd->fw_xchg_addr);
QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rportid);
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
return (FCT_SUCCESS);
}
fct_status_t
--- 7309,7320 ----
EL(qlt, "cmd_rp_handle-%x\n", cmd->cmd_rp_handle);
}
QMEM_WR32(qlt, (&req[0x10]), qcmd->fw_xchg_addr);
QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rportid);
! qlt_submit_req_entries(qlt, 1, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_SUCCESS);
}
fct_status_t
*** 4788,4822 ****
qlt_abort_unsol_scsi_cmd(qlt_state_t *qlt, fct_cmd_t *cmd)
{
qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
uint8_t *req;
uint16_t flags;
flags = (uint16_t)(BIT_14 |
(((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
- EL(qlt, "fctcmd-%p, cmd_handle-%x\n", cmd, cmd->cmd_handle);
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
! if (req == NULL) {
! mutex_exit(&qlt->req_lock);
return (FCT_BUSY);
}
qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
bzero(req, IOCB_SIZE);
req[0] = 0x12; req[1] = 0x1;
! QMEM_WR32(qlt, req+4, cmd->cmd_handle);
! QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle);
! QMEM_WR16(qlt, req+10, 60); /* 60 seconds timeout */
! QMEM_WR32(qlt, req+0x10, cmd->cmd_rportid);
! QMEM_WR32(qlt, req+0x14, qcmd->fw_xchg_addr);
! QMEM_WR16(qlt, req+0x1A, flags);
! QMEM_WR16(qlt, req+0x20, cmd->cmd_oxid);
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
return (FCT_SUCCESS);
}
fct_status_t
--- 7321,7360 ----
qlt_abort_unsol_scsi_cmd(qlt_state_t *qlt, fct_cmd_t *cmd)
{
qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
uint8_t *req;
uint16_t flags;
+ uint16_t qi;
+ qi = qcmd->qid;
+
flags = (uint16_t)(BIT_14 |
(((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
! EL(qlt, "(%d) (%x) (%p) (%x)\n", qi, cmd->cmd_oxid,
! cmd, qcmd->fw_xchg_addr);
+ mutex_enter(&qlt->mq_req[qi].mq_lock);
+ req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
+ if (req == NULL) {
+ EL(qlt, "req == NULL\n");
+ mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_BUSY);
}
qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
bzero(req, IOCB_SIZE);
req[0] = 0x12; req[1] = 0x1;
! QMEM_WR32_REQ(qlt, qi, req+4, cmd->cmd_handle);
! QMEM_WR16_REQ(qlt, qi, req+8, cmd->cmd_rp->rp_handle);
! QMEM_WR16_REQ(qlt, qi, req+10, 60); /* 60 seconds timeout */
! QMEM_WR32_REQ(qlt, qi, req+0x10, cmd->cmd_rportid);
! QMEM_WR32_REQ(qlt, qi, req+0x14, qcmd->fw_xchg_addr);
! QMEM_WR16_REQ(qlt, qi, req+0x1A, flags);
! QMEM_WR16_REQ(qlt, qi, req+0x20, cmd->cmd_oxid);
! qlt_submit_req_entries(qlt, 1, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_SUCCESS);
}
fct_status_t
*** 4823,4838 ****
qlt_send_cmd(fct_cmd_t *cmd)
{
qlt_state_t *qlt;
qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
if (cmd->cmd_type == FCT_CMD_SOL_ELS) {
return (qlt_send_els(qlt, cmd));
} else if (cmd->cmd_type == FCT_CMD_SOL_CT) {
return (qlt_send_ct(qlt, cmd));
}
! EL(qlt, "cmd->cmd_type = %xh\n", cmd->cmd_type);
ASSERT(0);
return (FCT_FAILURE);
}
--- 7361,7377 ----
qlt_send_cmd(fct_cmd_t *cmd)
{
qlt_state_t *qlt;
qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
+ EL(qlt, "cmd->cmd_type = %xh\n", cmd->cmd_type);
if (cmd->cmd_type == FCT_CMD_SOL_ELS) {
return (qlt_send_els(qlt, cmd));
} else if (cmd->cmd_type == FCT_CMD_SOL_CT) {
return (qlt_send_ct(qlt, cmd));
}
! EL(qlt, "Unknown cmd->cmd_type = %xh\n", cmd->cmd_type);
ASSERT(0);
return (FCT_FAILURE);
}
*** 4843,4853 ****
--- 7382,7395 ----
fct_els_t *els;
qlt_cmd_t *qcmd;
stmf_data_buf_t *buf;
qlt_dmem_bctl_t *bctl;
uint32_t sz, minsz;
+ uint16_t qi;
+ qi = 0;
+
els = (fct_els_t *)cmd->cmd_specific;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
qcmd->flags = QLT_CMD_TYPE_SOLICITED;
qcmd->param.resp_offset = (uint16_t)((els->els_req_size + 7) & ~7);
sz = minsz = qcmd->param.resp_offset + els->els_resp_size;
*** 4860,4874 ****
qcmd->dbuf = buf;
bcopy(els->els_req_payload, buf->db_sglist[0].seg_addr,
els->els_req_size);
qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV);
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
qlt_dmem_free(NULL, buf);
! mutex_exit(&qlt->req_lock);
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
req[0] = 0x53; req[1] = 1;
QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
--- 7402,7418 ----
qcmd->dbuf = buf;
bcopy(els->els_req_payload, buf->db_sglist[0].seg_addr,
els->els_req_size);
qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV);
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
+ EL(qlt, "req = NULL, %xh %xh %p %xh\n", cmd->cmd_oxid,
+ cmd->cmd_rportid, cmd, qcmd->fw_xchg_addr);
qlt_dmem_free(NULL, buf);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
req[0] = 0x53; req[1] = 1;
QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
*** 4888,4900 ****
QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr);
QMEM_WR32(qlt, (&req[0x30]), els->els_req_size);
QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr +
qcmd->param.resp_offset));
QMEM_WR32(qlt, (&req[0x3C]), els->els_resp_size);
- qlt_submit_req_entries(qlt, 1);
- mutex_exit(&qlt->req_lock);
return (FCT_SUCCESS);
}
fct_status_t
qlt_send_ct(qlt_state_t *qlt, fct_cmd_t *cmd)
--- 7432,7448 ----
QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr);
QMEM_WR32(qlt, (&req[0x30]), els->els_req_size);
QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr +
qcmd->param.resp_offset));
QMEM_WR32(qlt, (&req[0x3C]), els->els_resp_size);
+ EL(qlt, "ELS opcode %xh to %xh\n",
+ req[0x16], cmd->cmd_rp->rp_id);
+
+ qlt_submit_req_entries(qlt, 1, qi);
+ mutex_exit(&qlt->mq_req[qi].mq_lock);
+
return (FCT_SUCCESS);
}
fct_status_t
qlt_send_ct(qlt_state_t *qlt, fct_cmd_t *cmd)
*** 4903,4913 ****
--- 7451,7464 ----
fct_sol_ct_t *ct;
qlt_cmd_t *qcmd;
stmf_data_buf_t *buf;
qlt_dmem_bctl_t *bctl;
uint32_t sz, minsz;
+ uint16_t qi;
+ qi = 0;
+
ct = (fct_sol_ct_t *)cmd->cmd_specific;
qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
qcmd->flags = QLT_CMD_TYPE_SOLICITED;
qcmd->param.resp_offset = (uint16_t)((ct->ct_req_size + 7) & ~7);
sz = minsz = qcmd->param.resp_offset + ct->ct_resp_size;
*** 4920,4934 ****
qcmd->dbuf = buf;
bcopy(ct->ct_req_payload, buf->db_sglist[0].seg_addr,
ct->ct_req_size);
qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV);
! mutex_enter(&qlt->req_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1);
if (req == NULL) {
qlt_dmem_free(NULL, buf);
! mutex_exit(&qlt->req_lock);
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
req[0] = 0x29; req[1] = 1;
QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
--- 7471,7487 ----
qcmd->dbuf = buf;
bcopy(ct->ct_req_payload, buf->db_sglist[0].seg_addr,
ct->ct_req_size);
qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV);
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
+ EL(qlt, "req = NULL, %xh %xh %p %xh\n", cmd->cmd_oxid,
+ cmd->cmd_rportid, cmd, qcmd->fw_xchg_addr);
qlt_dmem_free(NULL, buf);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return (FCT_BUSY);
}
bzero(req, IOCB_SIZE);
req[0] = 0x29; req[1] = 1;
QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
*** 4944,4960 ****
QMEM_WR32(qlt, (&req[0x30]), ct->ct_req_size);
QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr +
qcmd->param.resp_offset)); /* RESPONSE DSD */
QMEM_WR32(qlt, (&req[0x3C]), ct->ct_resp_size);
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
return (FCT_SUCCESS);
}
/*
* All QLT_FIRMWARE_* will mainly be handled in this function
* It can not be called in interrupt context
*
* FWDUMP's purpose is to serve ioctl, so we will use qlt_ioctl_flags
--- 7497,7729 ----
QMEM_WR32(qlt, (&req[0x30]), ct->ct_req_size);
QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr +
qcmd->param.resp_offset)); /* RESPONSE DSD */
QMEM_WR32(qlt, (&req[0x3C]), ct->ct_resp_size);
! EL(qlt, "%p cmd_hdl=%xh %xh %xh\n",
! cmd, cmd->cmd_handle, ct->ct_req_size, ct->ct_resp_size);
+ qlt_submit_req_entries(qlt, 1, qi);
+ mutex_exit(&qlt->mq_req[qi].mq_lock);
+
return (FCT_SUCCESS);
}
+ /*ARGSUSED*/
+ caddr_t
+ qlt_str_ptr(qlt_state_t *qlt, caddr_t bp, uint32_t *len)
+ {
+ caddr_t sp;
+ uint32_t i = 0;
+ sp = bp;
+ while (*sp++ != 0) i++;
+ if (i > *len || !(*len -= i)) {
+ EL(qlt, "full buffer\n");
+ return (NULL);
+ }
+ return (bp += i);
+ }
+
+ static fct_status_t
+ qlt_27xx_fw_dump(fct_local_port_t *port, stmf_state_change_info_t *ssci)
+ {
+ qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
+ qlt_dmp_template_t *template_buff;
+ uint32_t tsize, dsize, len;
+ uint32_t cnt, *dp, *bp;
+ uint8_t *fw;
+ caddr_t sp;
+
+ EL(qlt, "enter...\n");
+
+ mutex_enter(&qlt->qlt_ioctl_lock);
+ /*
+ * To make sure that there's no outstanding dumping task
+ */
+ if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) {
+ mutex_exit(&qlt->qlt_ioctl_lock);
+ EL(qlt, "qlt_ioctl_flags=%xh, inprogress\n",
+ qlt->qlt_ioctl_flags);
+ return (FCT_FAILURE);
+ }
+
+ /*
+ * To make sure not to overwrite existing dump
+ */
+ if ((qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID) &&
+ !(qlt->qlt_ioctl_flags & QLT_FWDUMP_TRIGGERED_BY_USER) &&
+ !(qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER)) {
+ /*
+ * If we have already one dump, but it's not triggered by user
+ * and the user hasn't fetched it, we shouldn't dump again.
+ * But if qlt force a fw dump, then we need to overwrite the
+ * previous one anyway.
+ */
+ mutex_exit(&qlt->qlt_ioctl_lock);
+ EL(qlt, "qlt_ioctl_flags=%xh, already done\n",
+ qlt->qlt_ioctl_flags);
+ cmn_err(CE_NOTE, "qlt(%d): Skipping firmware dump as there "
+ "is one already outstanding.", qlt->instance);
+ return (FCT_FAILURE);
+ }
+
+ if (qlt->dmp_template_addr == NULL) {
+ mutex_exit(&qlt->qlt_ioctl_lock);
+ EL(qlt, "dmp_template_addr is NULL, can't "
+ "perform firmware dump\n");
+ cmn_err(CE_WARN, "!qlt(%d) dmp_template_addr is NULL, can't "
+ "perform firmware dump", qlt->instance);
+ return (FCT_FAILURE);
+ }
+
+ qlt->qlt_ioctl_flags |= QLT_FWDUMP_INPROGRESS;
+ if (ssci != NULL && (ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) {
+ qlt->qlt_ioctl_flags |= QLT_FWDUMP_TRIGGERED_BY_USER;
+ } else {
+ qlt->qlt_ioctl_flags &= ~QLT_FWDUMP_TRIGGERED_BY_USER;
+ }
+ mutex_exit(&qlt->qlt_ioctl_lock);
+
+ template_buff = (qlt_dmp_template_t *)qlt->dmp_template_addr;
+ tsize = template_buff->hdr.size_of_template;
+
+ if (qlt->fw_bin_dump_size == 0) {
+ qlt->fw_bin_dump_buf = kmem_zalloc(tsize, KM_NOSLEEP);
+ if (qlt->fw_bin_dump_buf == NULL) {
+ cmn_err(CE_WARN, "!qlt(%d) cannot alloc bin dump buf",
+ qlt->instance);
+ return (FCT_FAILURE);
+ }
+ cnt = (uint32_t)(tsize / sizeof (uint32_t));
+ dp = (uint32_t *)qlt->fw_bin_dump_buf;
+ bp = (uint32_t *)&template_buff->hdr;
+ while (cnt--) {
+ *dp++ = ddi_get32(qlt->dmp_template_acc_handle, bp++);
+ }
+ qlt->fw_bin_dump_size = qlt_27xx_dmp_parse_template(qlt,
+ (qlt_dt_hdr_t *)qlt->fw_bin_dump_buf, NULL, 0);
+ kmem_free(qlt->fw_bin_dump_buf, tsize);
+ qlt->fw_bin_dump_buf = NULL;
+
+ if (qlt->fw_bin_dump_size == 0) {
+ return (FCT_FAILURE);
+ }
+
+ /*
+ * Determine ascii dump file size
+ * 2 ascii bytes per binary byte + a space and
+ * a newline every 16 binary bytes
+ */
+ qlt->fw_ascii_dump_size = qlt->fw_bin_dump_size << 1;
+ qlt->fw_ascii_dump_size += qlt->fw_bin_dump_size;
+ qlt->fw_ascii_dump_size += qlt->fw_bin_dump_size / 16 + 1;
+
+ EL(qlt, "fw_bin_dump_size=%xh, "
+ "fw_acsii_dump_size=%xh\n", qlt->fw_bin_dump_size,
+ qlt->fw_ascii_dump_size);
+ }
+
+ if (qlt->fw_bin_dump_buf != NULL) {
+ /* overwrite the previous fw dump by qlt forced fw dump */
+ bzero((void *) qlt->fw_bin_dump_buf, qlt->fw_bin_dump_size);
+ } else {
+ qlt->fw_bin_dump_buf = kmem_zalloc(qlt->fw_bin_dump_size,
+ KM_NOSLEEP);
+ if (qlt->fw_bin_dump_buf == NULL) {
+ qlt->fw_bin_dump_size = 0;
+ EL(qlt, "done, failed alloc bin dump buf\n");
+ return (FCT_FAILURE);
+ }
+ }
+
+ if ((qlt->fw_dump_size != 0) &&
+ (qlt->fw_dump_size != qlt->fw_ascii_dump_size)) {
+ if (qlt->qlt_fwdump_buf != NULL) {
+ /* Release previously allocated buffer */
+ kmem_free(qlt->qlt_fwdump_buf, qlt->fw_dump_size);
+ qlt->qlt_fwdump_buf = NULL;
+ }
+ }
+
+ if (qlt->qlt_fwdump_buf == NULL) {
+ qlt->qlt_fwdump_buf = kmem_zalloc(qlt->fw_ascii_dump_size,
+ KM_NOSLEEP);
+ if (qlt->qlt_fwdump_buf == NULL) {
+ EL(qlt, "done, failed alloc ascii fw dump buf\n");
+ return (FCT_FAILURE);
+ }
+ qlt->fw_dump_size = qlt->fw_ascii_dump_size;
+ }
+
+ /* Disable ISP interrupts. */
+ REG_WR32(qlt, 0xc, 0);
+
+ cnt = (uint32_t)(tsize / sizeof (uint32_t));
+ dp = (uint32_t *)qlt->fw_bin_dump_buf;
+ bp = (uint32_t *)&template_buff->hdr;
+ while (cnt--) {
+ *dp++ = ddi_get32(qlt->dmp_template_acc_handle, bp++);
+ }
+
+ (void) qlt_27xx_dmp_parse_template(qlt,
+ (qlt_dt_hdr_t *)qlt->fw_bin_dump_buf,
+ (uint8_t *)dp, qlt->fw_bin_dump_size);
+
+ #ifdef _BIG_ENDIAN
+ cnt = (uint32_t)(tsize / sizeof (uint32_t));
+ dp = (uint32_t *)qlt->fw_bin_dump_buf;
+ while (cnt--) {
+ qlt_chg_endian((uint8_t *)dp, 4);
+ dp++;
+ }
+ #endif
+
+ /*
+ * Build ascii dump
+ */
+ len = qlt->fw_ascii_dump_size;
+ dsize = qlt->fw_bin_dump_size;
+ fw = (uint8_t *)qlt->fw_bin_dump_buf;
+ sp = qlt->qlt_fwdump_buf;
+
+ EL(qlt, "fw_dump_buffer=%ph, fw=%ph, fw_ascii_dump_size=%xh, "
+ "dsize=%xh\n", (void *)qlt->qlt_fwdump_buf, (void *)fw,
+ len, dsize);
+
+ /*
+ * 2 ascii bytes per binary byte + a space and
+ * a newline every 16 binary bytes
+ */
+ cnt = 0;
+ while (cnt < dsize) {
+ (void) snprintf(sp, len, "%02x ", *fw++);
+ if ((sp = qlt_str_ptr(qlt, sp, &len)) == NULL) {
+ break;
+ }
+ if (++cnt % 16 == 0) {
+ (void) snprintf(sp, len, "\n");
+ if ((sp = qlt_str_ptr(qlt, sp, &len)) == NULL) {
+ break;
+ }
+ }
+ }
+ if (cnt % 16 != 0) {
+ (void) snprintf(sp, len, "\n");
+ sp = qlt_str_ptr(qlt, sp, &len);
+ }
+
+ mutex_enter(&qlt->qlt_ioctl_lock);
+ qlt->qlt_ioctl_flags &=
+ ~(QLT_FWDUMP_INPROGRESS | QLT_FWDUMP_FETCHED_BY_USER);
+ qlt->qlt_ioctl_flags |= QLT_FWDUMP_ISVALID;
+ mutex_exit(&qlt->qlt_ioctl_lock);
+
+ EL(qlt, "done...\n");
+ return (FCT_SUCCESS);
+ }
+
/*
* All QLT_FIRMWARE_* will mainly be handled in this function
* It can not be called in interrupt context
*
* FWDUMP's purpose is to serve ioctl, so we will use qlt_ioctl_flags
*** 4970,4988 ****
char c = ' ';
uint32_t addr, endaddr, words_to_read;
caddr_t buf;
fct_status_t ret;
mutex_enter(&qlt->qlt_ioctl_lock);
/*
* To make sure that there's no outstanding dumping task
*/
if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) {
mutex_exit(&qlt->qlt_ioctl_lock);
EL(qlt, "qlt_ioctl_flags=%xh, inprogress\n",
qlt->qlt_ioctl_flags);
- EL(qlt, "outstanding\n");
return (FCT_FAILURE);
}
/*
* To make sure not to overwrite existing dump
--- 7739,7759 ----
char c = ' ';
uint32_t addr, endaddr, words_to_read;
caddr_t buf;
fct_status_t ret;
+ if (qlt->qlt_27xx_chip) {
+ return (qlt_27xx_fw_dump(port, ssci));
+ }
mutex_enter(&qlt->qlt_ioctl_lock);
/*
* To make sure that there's no outstanding dumping task
*/
if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) {
mutex_exit(&qlt->qlt_ioctl_lock);
EL(qlt, "qlt_ioctl_flags=%xh, inprogress\n",
qlt->qlt_ioctl_flags);
return (FCT_FAILURE);
}
/*
* To make sure not to overwrite existing dump
*** 4989,4999 ****
*/
if ((qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID) &&
!(qlt->qlt_ioctl_flags & QLT_FWDUMP_TRIGGERED_BY_USER) &&
!(qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER)) {
/*
! * If we have alreay one dump, but it's not triggered by user
* and the user hasn't fetched it, we shouldn't dump again.
*/
mutex_exit(&qlt->qlt_ioctl_lock);
EL(qlt, "qlt_ioctl_flags=%xh, already done\n",
qlt->qlt_ioctl_flags);
--- 7760,7770 ----
*/
if ((qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID) &&
!(qlt->qlt_ioctl_flags & QLT_FWDUMP_TRIGGERED_BY_USER) &&
!(qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER)) {
/*
! * If we have already one dump, but it's not triggered by user
* and the user hasn't fetched it, we shouldn't dump again.
*/
mutex_exit(&qlt->qlt_ioctl_lock);
EL(qlt, "qlt_ioctl_flags=%xh, already done\n",
qlt->qlt_ioctl_flags);
*** 5000,5026 ****
cmn_err(CE_NOTE, "qlt(%d): Skipping firmware dump as there "
"is one already outstanding.", qlt->instance);
return (FCT_FAILURE);
}
qlt->qlt_ioctl_flags |= QLT_FWDUMP_INPROGRESS;
! if (ssci->st_rflags & STMF_RFLAG_USER_REQUEST) {
qlt->qlt_ioctl_flags |= QLT_FWDUMP_TRIGGERED_BY_USER;
} else {
qlt->qlt_ioctl_flags &= ~QLT_FWDUMP_TRIGGERED_BY_USER;
}
mutex_exit(&qlt->qlt_ioctl_lock);
size_left = QLT_FWDUMP_BUFSIZE;
if (!qlt->qlt_fwdump_buf) {
ASSERT(!(qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID));
/*
* It's the only place that we allocate buf for dumping. After
* it's allocated, we will use it until the port is detached.
*/
! qlt->qlt_fwdump_buf = kmem_zalloc(size_left, KM_SLEEP);
}
/*
* Start to dump firmware
*/
buf = (caddr_t)qlt->qlt_fwdump_buf;
--- 7771,7811 ----
cmn_err(CE_NOTE, "qlt(%d): Skipping firmware dump as there "
"is one already outstanding.", qlt->instance);
return (FCT_FAILURE);
}
qlt->qlt_ioctl_flags |= QLT_FWDUMP_INPROGRESS;
! if ((ssci != NULL) && (ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) {
qlt->qlt_ioctl_flags |= QLT_FWDUMP_TRIGGERED_BY_USER;
} else {
qlt->qlt_ioctl_flags &= ~QLT_FWDUMP_TRIGGERED_BY_USER;
}
mutex_exit(&qlt->qlt_ioctl_lock);
size_left = QLT_FWDUMP_BUFSIZE;
+ if (qlt->qlt_mq_enabled && qlt->qlt_queue_cnt >= 8) {
+ size_left += 512 * 1024;
+ }
+ qlt->fw_dump_size = size_left;
if (!qlt->qlt_fwdump_buf) {
ASSERT(!(qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID));
/*
* It's the only place that we allocate buf for dumping. After
* it's allocated, we will use it until the port is detached.
*/
! qlt->qlt_fwdump_buf = kmem_zalloc(size_left, KM_NOSLEEP);
! if (qlt->qlt_fwdump_buf == NULL) {
! EL(qlt, "cannot alloc fwdump buffer\n");
! cmn_err(CE_WARN, "!qlt(%d): cannot alloc fwdump buf",
! qlt->instance);
! return (FCT_FAILURE);
}
+ }
+ EL(qlt, "starting firmware dump...\n");
+ cmn_err(CE_WARN, "!qlt(%d) starting firmware dump...",
+ qlt->instance);
+
/*
* Start to dump firmware
*/
buf = (caddr_t)qlt->qlt_fwdump_buf;
*** 5027,5046 ****
/*
* Print the ISP firmware revision number and attributes information
* Read the RISC to Host Status register
*/
n = (int)snprintf(buf, size_left, "ISP FW Version %d.%02d.%02d "
! "Attributes %04x\n\nR2H Status Register\n%08x",
qlt->fw_major, qlt->fw_minor,
qlt->fw_subminor, qlt->fw_attr, REG_RD32(qlt, REG_RISC_STATUS));
buf += n; size_left -= n;
/*
* Before pausing the RISC, make sure no mailbox can execute
*/
mutex_enter(&qlt->mbox_lock);
! if (qlt->mbox_io_state != MBOX_STATE_UNKNOWN) {
/*
* Wait to grab the mailboxes
*/
for (retries = 0; (qlt->mbox_io_state != MBOX_STATE_READY) &&
(qlt->mbox_io_state != MBOX_STATE_UNKNOWN); retries++) {
--- 7812,7832 ----
/*
* Print the ISP firmware revision number and attributes information
* Read the RISC to Host Status register
*/
n = (int)snprintf(buf, size_left, "ISP FW Version %d.%02d.%02d "
! "Attributes %04x\n\nR2H Status register\n%08x",
qlt->fw_major, qlt->fw_minor,
qlt->fw_subminor, qlt->fw_attr, REG_RD32(qlt, REG_RISC_STATUS));
buf += n; size_left -= n;
/*
* Before pausing the RISC, make sure no mailbox can execute
*/
mutex_enter(&qlt->mbox_lock);
! if ((qlt->mbox_io_state != MBOX_STATE_UNKNOWN) &&
! (qlt->qlt_intr_enabled)) {
/*
* Wait to grab the mailboxes
*/
for (retries = 0; (qlt->mbox_io_state != MBOX_STATE_READY) &&
(qlt->mbox_io_state != MBOX_STATE_UNKNOWN); retries++) {
*** 5074,5084 ****
if (i == 200) {
EL(qlt, "can't pause\n");
return (FCT_FAILURE);
}
! if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip)) {
goto over_25xx_specific_dump;
}
n = (int)snprintf(buf, size_left, "\n\nHostRisc registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x7000);
--- 7860,7884 ----
if (i == 200) {
EL(qlt, "can't pause\n");
return (FCT_FAILURE);
}
! if (qlt->qlt_83xx_chip) {
! /* Disable ECC checks in FB registers */
! REG_WR32(qlt, 0x54, 0x6000);
! REG_WR32(qlt, 0xC0, 0); /* 6000h */
! REG_WR32(qlt, 0xCC, 0); /* 6003h */
! REG_WR32(qlt, 0x54, 0x6010);
! REG_WR32(qlt, 0xD4, 0); /* 6015h */
!
! /* disable ECC detection in PCR whilst dumping */
! REG_WR32(qlt, 0x54, 0xF70);
! REG_WR32(qlt, 0xF0, 0x60000000);
! }
!
! if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip) &&
! (!qlt->qlt_83xx_chip) && (!qlt->qlt_27xx_chip)) {
goto over_25xx_specific_dump;
}
n = (int)snprintf(buf, size_left, "\n\nHostRisc registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x7000);
*** 5085,5094 ****
--- 7885,7899 ----
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x7010);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ REG_WR32(qlt, 0x54, 0x7040);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
REG_WR32(qlt, 0x54, 0x7C00);
n = (int)snprintf(buf, size_left, "\nPCIe registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0xC0, 0x1);
*** 5096,5130 ****
buf += n; size_left -= n;
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 1, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0xC0, 0x0);
over_25xx_specific_dump:;
! n = (int)snprintf(buf, size_left, "\n\nHost Interface Registers\n");
buf += n; size_left -= n;
/*
! * Capture data from 32 regsiters
*/
n = qlt_fwdump_dump_regs(qlt, buf, 0, 32, size_left);
buf += n; size_left -= n;
/*
* Disable interrupts
*/
REG_WR32(qlt, 0xc, 0);
/*
* Shadow registers
*/
! n = (int)snprintf(buf, size_left, "\nShadow Registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xF70);
addr = 0xb0000000;
for (i = 0; i < 0xb; i++) {
if ((!qlt->qlt_25xx_chip) &&
(!qlt->qlt_81xx_chip) &&
(i >= 7)) {
break;
}
if (i && ((i & 7) == 0)) {
n = (int)snprintf(buf, size_left, "\n");
--- 7901,7966 ----
buf += n; size_left -= n;
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 1, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0xC0, 0x0);
+ /* don't need to do this for 83xx */
+ if ((!qlt->qlt_83xx_chip) && (qlt->qlt_mq_enabled)) {
+ uint16_t qi;
+
+ for (qi = 0; qi < qlt->qlt_queue_cnt; qi++) {
+
+ n = (int)snprintf(buf, size_left,
+ "\n\nQueue Pointers #%x\n", qi);
+ buf += n; size_left -= n;
+
+ n = (int)snprintf(buf, size_left, "%08x ",
+ MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_IN));
+ buf += n; size_left -= n;
+ n = (int)snprintf(buf, size_left, "%08x ",
+ MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT));
+ buf += n; size_left -= n;
+ n = (int)snprintf(buf, size_left, "%08x ",
+ MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN));
+ buf += n; size_left -= n;
+ n = (int)snprintf(buf, size_left, "%08x",
+ MQBAR_RD32(qlt,
+ (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_OUT));
+ buf += n; size_left -= n;
+ }
+ }
+
over_25xx_specific_dump:;
! n = (int)snprintf(buf, size_left, "\n\nHost Interface registers\n");
buf += n; size_left -= n;
/*
! * Capture data from 32 registers
*/
n = qlt_fwdump_dump_regs(qlt, buf, 0, 32, size_left);
buf += n; size_left -= n;
/*
* Disable interrupts
*/
REG_WR32(qlt, 0xc, 0);
+ EL(qlt, "Disable interrupt\n");
/*
* Shadow registers
*/
! n = (int)snprintf(buf, size_left, "\nShadow registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xF70);
addr = 0xb0000000;
for (i = 0; i < 0xb; i++) {
if ((!qlt->qlt_25xx_chip) &&
(!qlt->qlt_81xx_chip) &&
+ (!qlt->qlt_83xx_chip) &&
(i >= 7)) {
break;
}
if (i && ((i & 7) == 0)) {
n = (int)snprintf(buf, size_left, "\n");
*** 5134,5154 ****
n = (int)snprintf(buf, size_left, "%08x ", REG_RD32(qlt, 0xFC));
buf += n; size_left -= n;
addr += 0x100000;
}
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
REG_WR32(qlt, 0x54, 0x10);
n = (int)snprintf(buf, size_left,
! "\n\nRISC IO Register\n%08x", REG_RD32(qlt, 0xC0));
buf += n; size_left -= n;
}
/*
* Mailbox registers
*/
! n = (int)snprintf(buf, size_left, "\n\nMailbox Registers\n");
buf += n; size_left -= n;
for (i = 0; i < 32; i += 2) {
if ((i + 2) & 15) {
c = ' ';
} else {
--- 7970,7991 ----
n = (int)snprintf(buf, size_left, "%08x ", REG_RD32(qlt, 0xFC));
buf += n; size_left -= n;
addr += 0x100000;
}
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_83xx_chip)) {
REG_WR32(qlt, 0x54, 0x10);
n = (int)snprintf(buf, size_left,
! "\n\nRISC IO register\n%08x", REG_RD32(qlt, 0xC0));
buf += n; size_left -= n;
}
/*
* Mailbox registers
*/
! n = (int)snprintf(buf, size_left, "\n\nMailbox registers\n");
buf += n; size_left -= n;
for (i = 0; i < 32; i += 2) {
if ((i + 2) & 15) {
c = ' ';
} else {
*** 5161,5173 ****
}
/*
* Transfer sequence registers
*/
! n = (int)snprintf(buf, size_left, "\nXSEQ GP Registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xBF00);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xBF10);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
--- 7998,8036 ----
}
/*
* Transfer sequence registers
*/
! n = (int)snprintf(buf, size_left, "\nXSEQ GP registers\n");
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ REG_WR32(qlt, 0x54, 0xBE00);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xBE10);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xBE20);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xBE30);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xBE40);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xBE50);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xBE60);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xBE70);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
REG_WR32(qlt, 0x54, 0xBF00);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xBF10);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
*** 5190,5200 ****
REG_WR32(qlt, 0x54, 0xBF70);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
n = (int)snprintf(buf, size_left, "\nXSEQ-0 registers\n");
buf += n; size_left -= n;
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
REG_WR32(qlt, 0x54, 0xBFC0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xBFD0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
--- 8053,8064 ----
REG_WR32(qlt, 0x54, 0xBF70);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
n = (int)snprintf(buf, size_left, "\nXSEQ-0 registers\n");
buf += n; size_left -= n;
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_83xx_chip)) {
REG_WR32(qlt, 0x54, 0xBFC0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xBFD0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
*** 5207,5221 ****
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xBFF0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
/*
* Receive sequence registers
*/
! n = (int)snprintf(buf, size_left, "\nRSEQ GP Registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xFF00);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xFF10);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
--- 8071,8119 ----
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xBFF0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ n = (int)snprintf(buf, size_left, "\nXSEQ-2 registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xBEF0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
+
/*
* Receive sequence registers
*/
! n = (int)snprintf(buf, size_left, "\nRSEQ GP registers\n");
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ REG_WR32(qlt, 0x54, 0xFE00);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xFE10);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xFE20);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xFE30);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xFE40);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xFE50);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xFE60);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xFE70);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
REG_WR32(qlt, 0x54, 0xFF00);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xFF10);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
*** 5238,5248 ****
REG_WR32(qlt, 0x54, 0xFF70);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
n = (int)snprintf(buf, size_left, "\nRSEQ-0 registers\n");
buf += n; size_left -= n;
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
REG_WR32(qlt, 0x54, 0xFFC0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
REG_WR32(qlt, 0x54, 0xFFD0);
--- 8136,8147 ----
REG_WR32(qlt, 0x54, 0xFF70);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
n = (int)snprintf(buf, size_left, "\nRSEQ-0 registers\n");
buf += n; size_left -= n;
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_83xx_chip)) {
REG_WR32(qlt, 0x54, 0xFFC0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
REG_WR32(qlt, 0x54, 0xFFD0);
*** 5256,5273 ****
n = (int)snprintf(buf, size_left, "\nRSEQ-2 registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xFFF0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
! if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip))
goto over_aseq_regs;
/*
* Auxiliary sequencer registers
*/
! n = (int)snprintf(buf, size_left, "\nASEQ GP Registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xB000);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xB010);
--- 8155,8180 ----
n = (int)snprintf(buf, size_left, "\nRSEQ-2 registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xFFF0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ n = (int)snprintf(buf, size_left, "\nRSEQ-3 registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xFEF0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
! if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip) &&
! (!qlt->qlt_83xx_chip))
goto over_aseq_regs;
/*
* Auxiliary sequencer registers
*/
! n = (int)snprintf(buf, size_left, "\nASEQ GP registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xB000);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xB010);
*** 5289,5298 ****
--- 8196,8231 ----
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xB070);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ REG_WR32(qlt, 0x54, 0xB100);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xB110);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xB120);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xB130);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xB140);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xB150);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xB160);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xB170);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
n = (int)snprintf(buf, size_left, "\nASEQ-0 registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xB0C0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
*** 5307,5316 ****
--- 8240,8256 ----
n = (int)snprintf(buf, size_left, "\nASEQ-2 registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0xB0F0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ n = (int)snprintf(buf, size_left, "\nASEQ-3 registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0xB1F0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
over_aseq_regs:;
/*
* Command DMA registers
*** 5318,5327 ****
--- 8258,8278 ----
n = (int)snprintf(buf, size_left, "\nCommand DMA registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x7100);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ REG_WR32(qlt, 0x54, 0x7120);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x7130);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x71F0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
/*
* Queues
*/
n = (int)snprintf(buf, size_left,
*** 5477,5494 ****
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x3060);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
REG_WR32(qlt, 0x54, 0x3070);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
/*
! * Fibre protocol module regsiters
*/
n = (int)snprintf(buf, size_left, "\nFPM hardware registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x4000);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
--- 8428,8446 ----
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x3060);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_83xx_chip)) {
REG_WR32(qlt, 0x54, 0x3070);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
/*
! * Fibre protocol module registers
*/
n = (int)snprintf(buf, size_left, "\nFPM hardware registers\n");
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x4000);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
*** 5524,5542 ****
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x40B0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
! if (qlt->qlt_81xx_chip) {
REG_WR32(qlt, 0x54, 0x40C0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x40D0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
/*
* Fibre buffer registers
*/
n = (int)snprintf(buf, size_left, "\nFB hardware registers\n");
buf += n; size_left -= n;
--- 8476,8713 ----
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x40B0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
! if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip)) {
REG_WR32(qlt, 0x54, 0x40C0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x40D0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
+ if (qlt->qlt_83xx_chip) {
+ REG_WR32(qlt, 0x54, 0x40E0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x40F0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ n = (int)snprintf(buf, size_left, "\nRQ0 Array registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C00);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C10);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C20);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C30);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C40);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C50);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C60);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C70);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C80);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5C90);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5CA0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5CB0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5CC0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5CD0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5CE0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5CF0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+
+ n = (int)snprintf(buf, size_left, "\nRQ1 Array registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D00);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D10);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D20);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D30);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D40);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D50);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D60);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D70);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D80);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5D90);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5DA0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5DB0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5DC0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5DD0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5DE0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5DF0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+
+ n = (int)snprintf(buf, size_left, "\nRP0 Array registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E00);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E10);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E20);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E30);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E40);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E50);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E60);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E70);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E80);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5E90);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5EA0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5EB0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5EC0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5ED0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5EE0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5EF0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+
+ n = (int)snprintf(buf, size_left, "\nRP1 Array registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F00);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F10);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F20);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F30);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F40);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F50);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F60);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F70);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F80);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5F90);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5FA0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5FB0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5FC0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5FD0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5FE0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x5FF0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+
+ n = (int)snprintf(buf,
+ size_left, "\nQueue Control Registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x7800);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
+
/*
* Fibre buffer registers
*/
n = (int)snprintf(buf, size_left, "\nFB hardware registers\n");
buf += n; size_left -= n;
*** 5553,5562 ****
--- 8724,8741 ----
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x6040);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
+ if (qlt->qlt_83xx_chip) {
+ REG_WR32(qlt, 0x54, 0x6060);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x6070);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
REG_WR32(qlt, 0x54, 0x6100);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x6130);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
*** 5571,5606 ****
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x61B0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
! if (qlt->qlt_81xx_chip) {
REG_WR32(qlt, 0x54, 0x61C0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
REG_WR32(qlt, 0x54, 0x6F00);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
qlt->intr_sneak_counter = 10;
mutex_enter(&qlt->intr_lock);
(void) qlt_reset_chip(qlt);
drv_usecwait(20);
qlt->intr_sneak_counter = 0;
mutex_exit(&qlt->intr_lock);
/*
* Memory
*/
n = (int)snprintf(buf, size_left, "\nCode RAM\n");
buf += n; size_left -= n;
addr = 0x20000;
! endaddr = 0x22000;
words_to_read = 0;
while (addr < endaddr) {
words_to_read = MBOX_DMA_MEM_SIZE >> 2;
if ((words_to_read + addr) > endaddr) {
words_to_read = endaddr - addr;
--- 8750,8865 ----
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
REG_WR32(qlt, 0x54, 0x61B0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
! if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip)) {
REG_WR32(qlt, 0x54, 0x61C0);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
! if (qlt->qlt_83xx_chip) {
! REG_WR32(qlt, 0x54, 0x6530);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x6540);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x6550);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x6560);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x6570);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x6580);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x6590);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x65A0);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x65B0);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x65C0);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x65D0);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! REG_WR32(qlt, 0x54, 0x65E0);
! n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
! buf += n; size_left -= n;
! }
! if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
! (qlt->qlt_83xx_chip)) {
REG_WR32(qlt, 0x54, 0x6F00);
n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
buf += n; size_left -= n;
}
+ if (qlt->qlt_83xx_chip) {
+ n = (int)snprintf(buf, size_left, "\nAT0 Array registers\n");
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x7080);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x7090);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x70A0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x70B0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x70C0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x70D0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x70E0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ REG_WR32(qlt, 0x54, 0x70F0);
+ n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
+ buf += n; size_left -= n;
+ }
+
+ EL(qlt, "reset chip\n");
qlt->intr_sneak_counter = 10;
mutex_enter(&qlt->intr_lock);
+ if (qlt->qlt_mq_enabled) {
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ mutex_enter(&qlt->mq_resp[i].mq_lock);
+ }
+ }
(void) qlt_reset_chip(qlt);
drv_usecwait(20);
qlt->intr_sneak_counter = 0;
+ if (qlt->qlt_mq_enabled) {
+ for (i = 1; i < qlt->qlt_queue_cnt; i++) {
+ mutex_exit(&qlt->mq_resp[i].mq_lock);
+ }
+ }
mutex_exit(&qlt->intr_lock);
+ EL(qlt, "reset chip, done\n");
/*
* Memory
*/
n = (int)snprintf(buf, size_left, "\nCode RAM\n");
buf += n; size_left -= n;
addr = 0x20000;
! endaddr = (qlt->qlt_83xx_chip) ? 0x22400 : 0x22000;
words_to_read = 0;
while (addr < endaddr) {
words_to_read = MBOX_DMA_MEM_SIZE >> 2;
if ((words_to_read + addr) > endaddr) {
words_to_read = endaddr - addr;
*** 5663,5704 ****
/*
* Queue dumping
*/
n = (int)snprintf(buf, size_left, "\nRequest Queue\n");
buf += n; size_left -= n;
! n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET,
REQUEST_QUEUE_ENTRIES, buf, size_left);
buf += n; size_left -= n;
n = (int)snprintf(buf, size_left, "\nPriority Queue\n");
buf += n; size_left -= n;
! n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET,
PRIORITY_QUEUE_ENTRIES, buf, size_left);
buf += n; size_left -= n;
n = (int)snprintf(buf, size_left, "\nResponse Queue\n");
buf += n; size_left -= n;
! n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET,
RESPONSE_QUEUE_ENTRIES, buf, size_left);
buf += n; size_left -= n;
! n = (int)snprintf(buf, size_left, "\nATIO queue\n");
buf += n; size_left -= n;
n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET,
ATIO_QUEUE_ENTRIES, buf, size_left);
buf += n; size_left -= n;
/*
* Label dump reason
*/
! n = (int)snprintf(buf, size_left, "\nFirmware dump reason: %s-%s\n",
qlt->qlt_port_alias, ssci->st_additional_info);
buf += n; size_left -= n;
dump_ok:
EL(qlt, "left-%d\n", size_left);
-
mutex_enter(&qlt->qlt_ioctl_lock);
qlt->qlt_ioctl_flags &=
~(QLT_FWDUMP_INPROGRESS | QLT_FWDUMP_FETCHED_BY_USER);
qlt->qlt_ioctl_flags |= QLT_FWDUMP_ISVALID;
mutex_exit(&qlt->qlt_ioctl_lock);
--- 8922,9010 ----
/*
* Queue dumping
*/
n = (int)snprintf(buf, size_left, "\nRequest Queue\n");
buf += n; size_left -= n;
!
! if (qlt->qlt_mq_enabled) {
! for (i = 0; i < qlt->qlt_queue_cnt; i++) {
! if (qlt->mq_req[i].queue_mem_mq_base_addr) {
! n = (int)snprintf(buf, size_left,
! "\nQueue %d:\n", i);
! buf += n; size_left -= n;
! n = qlt_dump_queue(qlt,
! qlt->mq_req[i].queue_mem_mq_base_addr,
! REQUEST_QUEUE_MQ_ENTRIES,
! buf, size_left);
! buf += n; size_left -= n;
! }
! }
! } else {
! n = (int)snprintf(buf, size_left, "\nQueue 0:\n");
! buf += n; size_left -= n;
! n = qlt_dump_queue(qlt,
! qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET,
REQUEST_QUEUE_ENTRIES, buf, size_left);
buf += n; size_left -= n;
+ }
+ if (!qlt->qlt_83xx_chip) {
n = (int)snprintf(buf, size_left, "\nPriority Queue\n");
buf += n; size_left -= n;
! n = qlt_dump_queue(qlt,
! qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET,
PRIORITY_QUEUE_ENTRIES, buf, size_left);
buf += n; size_left -= n;
+ }
n = (int)snprintf(buf, size_left, "\nResponse Queue\n");
buf += n; size_left -= n;
!
! if (qlt->qlt_mq_enabled) {
! for (i = 0; i < qlt->qlt_queue_cnt; i++) {
! if (qlt->mq_resp[i].queue_mem_mq_base_addr) {
! n = (int)snprintf(buf, size_left,
! "\nQueue %d:\n", i);
! buf += n; size_left -= n;
! n = qlt_dump_queue(qlt,
! qlt->mq_resp[i].queue_mem_mq_base_addr,
! RESPONSE_QUEUE_MQ_ENTRIES,
! buf, size_left);
! buf += n; size_left -= n;
! }
! }
! } else {
! n = (int)snprintf(buf, size_left, "\nQueue 0:\n");
! buf += n; size_left -= n;
! n = qlt_dump_queue(qlt,
! qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET,
RESPONSE_QUEUE_ENTRIES, buf, size_left);
buf += n; size_left -= n;
+ }
! n = (int)snprintf(buf, size_left, "\nATIO Queue\nQueue 0:\n");
buf += n; size_left -= n;
n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET,
ATIO_QUEUE_ENTRIES, buf, size_left);
buf += n; size_left -= n;
/*
* Label dump reason
*/
! if (ssci != NULL) {
! n = (int)snprintf(buf, size_left,
! "\nFirmware dump reason: %s-%s\n",
qlt->qlt_port_alias, ssci->st_additional_info);
+ } else {
+ n = (int)snprintf(buf, size_left,
+ "\nFirmware dump reason: %s-%s\n",
+ qlt->qlt_port_alias, "no additional infor");
+ }
buf += n; size_left -= n;
dump_ok:
EL(qlt, "left-%d\n", size_left);
mutex_enter(&qlt->qlt_ioctl_lock);
qlt->qlt_ioctl_flags &=
~(QLT_FWDUMP_INPROGRESS | QLT_FWDUMP_FETCHED_BY_USER);
qlt->qlt_ioctl_flags |= QLT_FWDUMP_ISVALID;
mutex_exit(&qlt->qlt_ioctl_lock);
*** 5764,5778 ****
{
int i;
int n;
char c = ' ';
int words;
! uint16_t *ptr;
! uint16_t w;
! words = entries * 32;
! ptr = (uint16_t *)qadr;
for (i = 0, n = 0; i < words; i++) {
if ((i & 7) == 0) {
n = (int)(n + (int)snprintf(&buf[n],
(uint_t)(size_left - n), "%05x: ", i));
}
--- 9070,9084 ----
{
int i;
int n;
char c = ' ';
int words;
! uint32_t *ptr;
! uint32_t w;
! words = entries * 16;
! ptr = (uint32_t *)qadr;
for (i = 0, n = 0; i < words; i++) {
if ((i & 7) == 0) {
n = (int)(n + (int)snprintf(&buf[n],
(uint_t)(size_left - n), "%05x: ", i));
}
*** 5779,5790 ****
if ((i + 1) & 7) {
c = ' ';
} else {
c = '\n';
}
! w = QMEM_RD16(qlt, &ptr[i]);
! n = (int)(n + (int)snprintf(&buf[n], (size_left - n), "%04x%c",
w, c));
}
return (n);
}
--- 9085,9096 ----
if ((i + 1) & 7) {
c = ' ';
} else {
c = '\n';
}
! w = QMEM_RD32(qlt, &ptr[i]);
! n = (int)(n + (int)snprintf(&buf[n], (size_left - n), "%08x%c",
w, c));
}
return (n);
}
*** 5821,5845 ****
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
if (ret == QLT_SUCCESS) {
(void) ddi_dma_sync(qlt->queue_mem_dma_handle,
MBOX_DMA_MEM_OFFSET, words << 2, DDI_DMA_SYNC_FORCPU);
} else {
! EL(qlt, "qlt_raw_mailbox_command=ch status=%llxh\n", ret);
}
return (ret);
}
static void
qlt_verify_fw(qlt_state_t *qlt)
{
caddr_t req;
/* Just put it on the request queue */
! mutex_enter(&qlt->req_lock);
! req = qlt_get_req_entries(qlt, 1);
if (req == NULL) {
! mutex_exit(&qlt->req_lock);
! /* XXX handle this */
return;
}
bzero(req, IOCB_SIZE);
--- 9127,9190 ----
REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
if (ret == QLT_SUCCESS) {
(void) ddi_dma_sync(qlt->queue_mem_dma_handle,
MBOX_DMA_MEM_OFFSET, words << 2, DDI_DMA_SYNC_FORCPU);
} else {
! EL(qlt, "qlt_raw_mailbox_command=0x0ch status=%llxh\n", ret);
}
return (ret);
}
+ static fct_status_t
+ qlt_mbx_mpi_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words,
+ uint16_t direction)
+ {
+ uint64_t da;
+ fct_status_t ret;
+
+ REG_WR16(qlt, REG_MBOX(0), MBC_MPI_RAM);
+ da = qlt->queue_mem_cookie.dmac_laddress;
+ da += MBOX_DMA_MEM_OFFSET;
+
+ /* System destination address */
+ REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da)));
+ REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da)));
+ REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
+ REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
+
+ /* Length */
+ REG_WR16(qlt, REG_MBOX(5), LSW(words));
+ REG_WR16(qlt, REG_MBOX(4), MSW(words));
+
+ /* RISC source address */
+ REG_WR16(qlt, REG_MBOX(1), LSW(addr));
+ REG_WR16(qlt, REG_MBOX(8), MSW(addr));
+
+ REG_WR16(qlt, REG_MBOX(9), direction);
+ ret = qlt_raw_mailbox_command(qlt);
+ REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
+ if (ret == QLT_SUCCESS) {
+ (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
+ MBOX_DMA_MEM_OFFSET, words << 2, DDI_DMA_SYNC_FORCPU);
+ } else {
+ EL(qlt, "qlt_raw_mailbox_command=0x05h status=%llxh\n", ret);
+ }
+ return (ret);
+ }
+
static void
qlt_verify_fw(qlt_state_t *qlt)
{
caddr_t req;
+ uint16_t qi = 0;
+
/* Just put it on the request queue */
! mutex_enter(&qlt->mq_req[qi].mq_lock);
! req = qlt_get_req_entries(qlt, 1, qi);
if (req == NULL) {
! EL(qlt, "req = NULL\n");
! mutex_exit(&qlt->mq_req[qi].mq_lock);
return;
}
bzero(req, IOCB_SIZE);
*** 5848,5879 ****
QMEM_WR32(qlt, (&req[4]), 0xffffffff);
QMEM_WR16(qlt, (&req[0x8]), 1); /* options - don't update */
QMEM_WR32(qlt, (&req[0x14]), 0x80010300);
! qlt_submit_req_entries(qlt, 1);
! mutex_exit(&qlt->req_lock);
}
static void
qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp)
{
uint16_t status;
! char info[QLT_INFO_LEN];
status = QMEM_RD16(qlt, rsp+8);
if (status != 0) {
! (void) snprintf(info, sizeof (info),
! "qlt_handle_verify_fw_completion: "
"status:%x, rsp:%p", status, (void *)rsp);
if (status == 3) {
uint16_t error_code;
error_code = QMEM_RD16(qlt, rsp+0xA);
! (void) snprintf(info, sizeof (info),
! "qlt_handle_verify_fw_completion: error code:%x",
! error_code);
}
}
}
/*
--- 9193,9349 ----
QMEM_WR32(qlt, (&req[4]), 0xffffffff);
QMEM_WR16(qlt, (&req[0x8]), 1); /* options - don't update */
QMEM_WR32(qlt, (&req[0x14]), 0x80010300);
! qlt_submit_req_entries(qlt, 1, qi);
! mutex_exit(&qlt->mq_req[qi].mq_lock);
}
+ static fct_status_t
+ qlt_mq_destroy(qlt_state_t *qlt)
+ {
+ int idx;
+
+ for (idx = 1; idx < qlt->qlt_queue_cnt; idx++) {
+ (void) ddi_dma_unbind_handle(
+ qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ (void) ddi_dma_unbind_handle(
+ qlt->mq_resp[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_resp[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_resp[idx].queue_mem_mq_dma_handle);
+ }
+ return (QLT_SUCCESS);
+ }
+
+ static fct_status_t
+ qlt_mq_create(qlt_state_t *qlt, int idx)
+ {
+ ddi_device_acc_attr_t dev_acc_attr;
+ size_t discard;
+ uint_t ncookies;
+
+ dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
+ dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
+ dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
+
+ /*
+ * MQ Request queue
+ */
+ if (ddi_dma_alloc_handle(qlt->dip, &qlt_queue_dma_attr_mq_req1,
+ DDI_DMA_SLEEP, 0,
+ &qlt->mq_req[idx].queue_mem_mq_dma_handle) != DDI_SUCCESS) {
+ return (QLT_FAILURE);
+ }
+ if (ddi_dma_mem_alloc(qlt->mq_req[idx].queue_mem_mq_dma_handle,
+ REQUEST_QUEUE_MQ_SIZE,
+ &dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
+ &qlt->mq_req[idx].queue_mem_mq_base_addr, &discard,
+ &qlt->mq_req[idx].queue_mem_mq_acc_handle) != DDI_SUCCESS) {
+ ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ return (QLT_FAILURE);
+ }
+ if (ddi_dma_addr_bind_handle(
+ qlt->mq_req[idx].queue_mem_mq_dma_handle,
+ NULL, qlt->mq_req[idx].queue_mem_mq_base_addr,
+ REQUEST_QUEUE_MQ_SIZE,
+ DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
+ &qlt->mq_req[idx].queue_mem_mq_cookie,
+ &ncookies) != DDI_SUCCESS) {
+ ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ return (QLT_FAILURE);
+ }
+ if (ncookies != 1) {
+ (void) ddi_dma_unbind_handle(
+ qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ return (QLT_FAILURE);
+ }
+
+ /*
+ * MQ Response queue
+ */
+ if (ddi_dma_alloc_handle(qlt->dip, &qlt_queue_dma_attr_mq_rsp1,
+ DDI_DMA_SLEEP, 0,
+ &qlt->mq_resp[idx].queue_mem_mq_dma_handle) != DDI_SUCCESS) {
+ (void) ddi_dma_unbind_handle(
+ qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ return (QLT_FAILURE);
+ }
+ if (ddi_dma_mem_alloc(qlt->mq_resp[idx].queue_mem_mq_dma_handle,
+ RESPONSE_QUEUE_MQ_SIZE,
+ &dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
+ &qlt->mq_resp[idx].queue_mem_mq_base_addr, &discard,
+ &qlt->mq_resp[idx].queue_mem_mq_acc_handle) != DDI_SUCCESS) {
+ (void) ddi_dma_unbind_handle(
+ qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ ddi_dma_free_handle(&qlt->mq_resp[idx].queue_mem_mq_dma_handle);
+ return (QLT_FAILURE);
+ }
+ if (ddi_dma_addr_bind_handle(
+ qlt->mq_resp[idx].queue_mem_mq_dma_handle,
+ NULL, qlt->mq_resp[idx].queue_mem_mq_base_addr,
+ RESPONSE_QUEUE_MQ_SIZE,
+ DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
+ &qlt->mq_resp[idx].queue_mem_mq_cookie,
+ &ncookies) != DDI_SUCCESS) {
+ (void) ddi_dma_unbind_handle(
+ qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_resp[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_resp[idx].queue_mem_mq_dma_handle);
+ return (QLT_FAILURE);
+ }
+ if (ncookies != 1) {
+ (void) ddi_dma_unbind_handle(
+ qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
+ (void) ddi_dma_unbind_handle(
+ qlt->mq_resp[idx].queue_mem_mq_dma_handle);
+ ddi_dma_mem_free(&qlt->mq_resp[idx].queue_mem_mq_acc_handle);
+ ddi_dma_free_handle(&qlt->mq_resp[idx].queue_mem_mq_dma_handle);
+ return (QLT_FAILURE);
+ }
+
+ qlt->mq_req[idx].mq_ptr = qlt->mq_req[idx].queue_mem_mq_base_addr;
+ qlt->mq_req[idx].mq_ndx_to_fw = qlt->mq_req[idx].mq_ndx_from_fw = 0;
+ qlt->mq_req[idx].mq_available = REQUEST_QUEUE_MQ_ENTRIES - 1;
+ bzero(qlt->mq_req[idx].mq_ptr, REQUEST_QUEUE_MQ_SIZE);
+
+ qlt->mq_resp[idx].mq_ptr = qlt->mq_resp[idx].queue_mem_mq_base_addr;
+ qlt->mq_resp[idx].mq_ndx_to_fw = qlt->mq_resp[idx].mq_ndx_from_fw = 0;
+ bzero(qlt->mq_resp[idx].mq_ptr, RESPONSE_QUEUE_MQ_SIZE);
+
+ return (QLT_SUCCESS);
+ }
+
static void
qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp)
{
uint16_t status;
! char info[80];
status = QMEM_RD16(qlt, rsp+8);
if (status != 0) {
! (void) snprintf(info, 80, "qlt_handle_verify_fw_completion: "
"status:%x, rsp:%p", status, (void *)rsp);
if (status == 3) {
uint16_t error_code;
error_code = QMEM_RD16(qlt, rsp+0xA);
! (void) snprintf(info, 80, "qlt_handle_verify_fw_"
! "completion: error code:%x", error_code);
}
}
}
/*
*** 5884,5923 ****
* Context: Kernel context.
*/
static int
qlt_el_trace_desc_ctor(qlt_state_t *qlt)
{
! int rval = DDI_SUCCESS;
! qlt->el_trace_desc = (qlt_el_trace_desc_t *)
! kmem_zalloc(sizeof (qlt_el_trace_desc_t), KM_SLEEP);
! if (qlt->el_trace_desc == NULL) {
! cmn_err(CE_WARN, "qlt(%d): can't construct trace descriptor",
! qlt->instance);
! rval = DDI_FAILURE;
! } else {
! qlt->el_trace_desc->next = 0;
! qlt->el_trace_desc->trace_buffer =
! (char *)kmem_zalloc(EL_TRACE_BUF_SIZE, KM_SLEEP);
! if (qlt->el_trace_desc->trace_buffer == NULL) {
! cmn_err(CE_WARN, "qlt(%d): can't get trace buffer",
! qlt->instance);
! kmem_free(qlt->el_trace_desc,
! sizeof (qlt_el_trace_desc_t));
! qlt->el_trace_desc = NULL;
! rval = DDI_FAILURE;
! } else {
! qlt->el_trace_desc->trace_buffer_size =
! EL_TRACE_BUF_SIZE;
! mutex_init(&qlt->el_trace_desc->mutex, NULL,
MUTEX_DRIVER, NULL);
- }
- }
! return (rval);
}
/*
* qlt_el_trace_desc_dtor - Destroy an extended logging trace descriptor.
*
--- 9354,9387 ----
* Context: Kernel context.
*/
static int
qlt_el_trace_desc_ctor(qlt_state_t *qlt)
{
! qlt_trace_entry_t *entry;
! size_t maxsize;
! qlt->qlt_trace_desc =
! (qlt_trace_desc_t *)kmem_zalloc(
! sizeof (qlt_trace_desc_t), KM_SLEEP);
! qlt->qlt_log_entries = QL_LOG_ENTRIES;
! maxsize = qlt->qlt_log_entries * sizeof (qlt_trace_entry_t);
! entry = kmem_zalloc(maxsize, KM_SLEEP);
! mutex_init(&qlt->qlt_trace_desc->mutex, NULL,
MUTEX_DRIVER, NULL);
! qlt->qlt_trace_desc->trace_buffer = entry;
! qlt->qlt_trace_desc->trace_buffer_size = maxsize;
! qlt->qlt_trace_desc->nindex = 0;
!
! qlt->qlt_trace_desc->nentries = qlt->qlt_log_entries;
! qlt->qlt_trace_desc->start = qlt->qlt_trace_desc->end = 0;
! qlt->qlt_trace_desc->csize = 0;
! qlt->qlt_trace_desc->count = 0;
!
! return (DDI_SUCCESS);
}
/*
* qlt_el_trace_desc_dtor - Destroy an extended logging trace descriptor.
*
*** 5928,5949 ****
static int
qlt_el_trace_desc_dtor(qlt_state_t *qlt)
{
int rval = DDI_SUCCESS;
! if (qlt->el_trace_desc == NULL) {
! cmn_err(CE_WARN, "qlt(%d): can't destroy el trace descriptor",
! qlt->instance);
! rval = DDI_FAILURE;
! } else {
! if (qlt->el_trace_desc->trace_buffer != NULL) {
! kmem_free(qlt->el_trace_desc->trace_buffer,
! qlt->el_trace_desc->trace_buffer_size);
}
! mutex_destroy(&qlt->el_trace_desc->mutex);
! kmem_free(qlt->el_trace_desc, sizeof (qlt_el_trace_desc_t));
! qlt->el_trace_desc = NULL;
}
return (rval);
}
--- 9392,9408 ----
static int
qlt_el_trace_desc_dtor(qlt_state_t *qlt)
{
int rval = DDI_SUCCESS;
! if (qlt->qlt_trace_desc != NULL) {
! if (qlt->qlt_trace_desc->trace_buffer != NULL) {
! kmem_free(qlt->qlt_trace_desc->trace_buffer,
! qlt->qlt_trace_desc->trace_buffer_size);
}
! mutex_destroy(&qlt->qlt_trace_desc->mutex);
! kmem_free(qlt->qlt_trace_desc, sizeof (qlt_trace_desc_t));
}
return (rval);
}
*** 5962,6154 ****
*/
void
qlt_el_msg(qlt_state_t *qlt, const char *fn, int ce, ...)
{
char *s, *fmt = 0, *fmt1 = 0;
! char fmt2[EL_BUFFER_RESERVE];
! int rval, tmp;
! int tracing = 0;
va_list vl;
! /* Tracing is the default but it can be disabled. */
! if ((rval = qlt_validate_trace_desc(qlt)) == DDI_SUCCESS) {
! tracing = 1;
! mutex_enter(&qlt->el_trace_desc->mutex);
/*
! * Ensure enough space for the string. Wrap to
! * start when default message allocation size
! * would overrun the end.
*/
! if ((qlt->el_trace_desc->next + EL_BUFFER_RESERVE) >=
! qlt->el_trace_desc->trace_buffer_size) {
! fmt = qlt->el_trace_desc->trace_buffer;
! qlt->el_trace_desc->next = 0;
! } else {
! fmt = qlt->el_trace_desc->trace_buffer +
! qlt->el_trace_desc->next;
}
- }
! /* if no buffer use the stack */
! if (fmt == NULL) {
! fmt = fmt2;
! }
! va_start(vl, ce);
! s = va_arg(vl, char *);
! rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE,
! "QEL qlt(%d): %s, ", qlt->instance, fn);
! fmt1 = fmt + rval;
! tmp = (int)vsnprintf(fmt1,
(size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
rval += tmp;
/*
! * Calculate the offset where the next message will go,
! * skipping the NULL.
*/
! if (tracing) {
! uint16_t next = (uint16_t)(rval += 1);
! qlt->el_trace_desc->next += next;
! mutex_exit(&qlt->el_trace_desc->mutex);
}
! if (enable_extended_logging) {
! cmn_err(ce, fmt);
}
! va_end(vl);
! }
! /*
! * qlt_dump_el_trace_buffer
! * Outputs extended logging trace buffer.
! *
! * Input:
! * qlt: adapter state pointer.
! */
! void
! qlt_dump_el_trace_buffer(qlt_state_t *qlt)
! {
! char *dump_start = NULL;
! char *dump_current = NULL;
! char *trace_start;
! char *trace_end;
! int wrapped = 0;
! int rval;
! mutex_enter(&qlt->el_trace_desc->mutex);
!
! rval = qlt_validate_trace_desc(qlt);
! if (rval != NULL) {
! cmn_err(CE_CONT, "qlt(%d) Dump EL trace - invalid desc\n",
! qlt->instance);
! } else if ((dump_start = qlt_find_trace_start(qlt)) != NULL) {
! dump_current = dump_start;
! trace_start = qlt->el_trace_desc->trace_buffer;
! trace_end = trace_start +
! qlt->el_trace_desc->trace_buffer_size;
!
! cmn_err(CE_CONT, "qlt(%d) Dump EL trace - start %p %p\n",
! qlt->instance,
! (void *)dump_start, (void *)trace_start);
!
! while (((uintptr_t)dump_current - (uintptr_t)trace_start) <=
! (uintptr_t)qlt->el_trace_desc->trace_buffer_size) {
! /* Show it... */
! cmn_err(CE_CONT, "%p - %s", (void *)dump_current,
! dump_current);
! /* Make the next the current */
! dump_current += (strlen(dump_current) + 1);
! /* check for wrap */
! if ((dump_current + EL_BUFFER_RESERVE) >= trace_end) {
! dump_current = trace_start;
! wrapped = 1;
! } else if (wrapped) {
! /* Don't go past next. */
! if ((trace_start + qlt->el_trace_desc->next) <=
! dump_current) {
! break;
}
- } else if (*dump_current == NULL) {
- break;
- }
- }
- }
- mutex_exit(&qlt->el_trace_desc->mutex);
- }
! /*
! * qlt_validate_trace_desc
! * Ensures the extended logging trace descriptor is good.
! *
! * Input:
! * qlt: adapter state pointer.
! *
! * Returns:
! * ql local function return status code.
! */
! static int
! qlt_validate_trace_desc(qlt_state_t *qlt)
! {
! int rval = DDI_SUCCESS;
! if (qlt->el_trace_desc == NULL) {
! rval = DDI_FAILURE;
! } else if (qlt->el_trace_desc->trace_buffer == NULL) {
! rval = DDI_FAILURE;
}
- return (rval);
- }
! /*
! * qlt_find_trace_start
! * Locate the oldest extended logging trace entry.
! *
! * Input:
! * qlt: adapter state pointer.
! *
! * Returns:
! * Pointer to a string.
! *
! * Context:
! * Kernel/Interrupt context.
! */
! static char *
! qlt_find_trace_start(qlt_state_t *qlt)
! {
! char *trace_start = 0;
! char *trace_next = 0;
! trace_next = qlt->el_trace_desc->trace_buffer +
! qlt->el_trace_desc->next;
! /*
! * If the buffer has not wrapped next will point at a null so
! * start is the beginning of the buffer. If next points at a char
! * then we must traverse the buffer until a null is detected and
! * that will be the beginning of the oldest whole object in the buffer
! * which is the start.
! */
! if ((trace_next + EL_BUFFER_RESERVE) >=
! (qlt->el_trace_desc->trace_buffer +
! qlt->el_trace_desc->trace_buffer_size)) {
! trace_start = qlt->el_trace_desc->trace_buffer;
! } else if (*trace_next != NULL) {
! trace_start = trace_next + (strlen(trace_next) + 1);
! } else {
! trace_start = qlt->el_trace_desc->trace_buffer;
}
- return (trace_start);
}
-
static int
qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval)
{
return (ddi_getprop(DDI_DEV_T_ANY, qlt->dip,
DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, prop, defval));
--- 9421,9552 ----
*/
void
qlt_el_msg(qlt_state_t *qlt, const char *fn, int ce, ...)
{
char *s, *fmt = 0, *fmt1 = 0;
!
! /*
! * EL_BUFFER_RESERVE 256 is the max # of bytes
! * that driver's log could be collected.
! * add 3 more buytes for safely maniplulation.
! */
! char buf[EL_BUFFER_RESERVE + 3];
! char buf1[QL_LOG_LENGTH];
! size_t tmp;
! size_t rval, rval1;
va_list vl;
+ qlt_trace_desc_t *desc = qlt->qlt_trace_desc;
+ qlt_trace_entry_t *entry;
+ uint32_t cindex;
+ timespec_t time;
+ uint32_t count;
+ size_t left;
! (void) bzero((void *)&buf[0], EL_BUFFER_RESERVE + 3);
! fmt1 = &buf[0];
! TRACE_BUFFER_LOCK(qlt);
+ /* locate the entry to be filled out */
+ cindex = desc->nindex;
+ entry = &desc->trace_buffer[cindex];
+
+ count = desc->count;
+
+ desc->end = desc->nindex;
+ desc->nindex++;
+ if (desc->nindex == desc->nentries) {
+ desc->nindex = 0;
+ }
+
+ if (desc->csize < desc->nentries) {
+ desc->csize ++;
+ } else {
/*
! * once wrapped, csize is fixed.
! * so we have to adjust start point
*/
! desc->start = desc->nindex;
}
! gethrestime(&time);
! rval = snprintf(fmt1, (size_t)EL_BUFFER_RESERVE,
! QL_BANG "%d=>QEL %s(%d,%d):: %s, ", count, QL_NAME,
! qlt->instance, 0, fn);
! rval1 = rval;
! va_start(vl, ce);
! s = va_arg(vl, char *);
! fmt = fmt1 + rval;
! tmp = vsnprintf(fmt,
(size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
+ va_end(vl);
+
rval += tmp;
+ if (rval > QL_LOG_LENGTH - 1) {
+ left = rval - (QL_LOG_LENGTH - 1);
+ /* store the remaining string */
+ (void) strncpy(buf1, fmt1 + (QL_LOG_LENGTH - 1), left);
+ (void) strncpy(entry->buf, fmt1, (QL_LOG_LENGTH - 1));
+ entry->buf[QL_LOG_LENGTH - 1] = '\n';
+
+ bcopy((void *)&time, (void *)&entry->hs_time,
+ sizeof (timespec_t));
+
/*
! * remaining msg will be stored in the nex entry
! * with same timestamp and same sequence number
*/
! cindex = desc->nindex;
! entry = &desc->trace_buffer[cindex];
!
! desc->end = desc->nindex;
! desc->nindex++;
! if (desc->nindex == desc->nentries) {
! desc->nindex = 0;
}
! if (desc->csize < desc->nentries) {
! desc->csize ++;
! } else {
! desc->start = desc->nindex;
}
! (void) strncpy(&entry->buf[0], fmt1, rval1);
! (void) strncpy(&entry->buf[rval1], &buf1[0], left);
! entry->buf[rval1 + left] = 0;
! bcopy((void *)&time, (void *)&entry->hs_time,
! sizeof (timespec_t));
! if (qlt->qlt_eel_level == 1) {
! cmn_err(ce, fmt1);
}
! desc->count++;
! TRACE_BUFFER_UNLOCK(qlt);
! return;
}
! desc->count ++;
! bcopy((void *)&time, (void *)&entry->hs_time,
! sizeof (timespec_t));
! (void) strcpy(entry->buf, fmt1);
! entry->buf[rval] = 0;
! TRACE_BUFFER_UNLOCK(qlt);
! if (qlt->qlt_eel_level == 1) {
! cmn_err(ce, fmt1);
}
}
static int
qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval)
{
return (ddi_getprop(DDI_DEV_T_ANY, qlt->dip,
DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, prop, defval));
*** 6306,6320 ****
--- 9704,9722 ----
uint32_t data, dctl = 1000;
do {
if (dctl-- == 0 || qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 1) !=
QLT_SUCCESS) {
+ EL(qlt, "qlt_mps_reset: semaphore request fail,"
+ " cnt=%d\n", dctl);
return;
}
if (qlt_raw_rd_risc_ram_word(qlt, 0x7c00, &data) !=
QLT_SUCCESS) {
(void) qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 0);
+ EL(qlt, "qlt_mps_reset: semaphore read fail,"
+ " cnt=%d\n", dctl);
return;
}
} while (!(data & BIT_0));
if (qlt_raw_rd_risc_ram_word(qlt, 0x7A15, &data) == QLT_SUCCESS) {
*** 6322,6331 ****
--- 9724,9735 ----
if ((data & 0xe0) != (dctl & 0xe0)) {
data &= 0xff1f;
data |= dctl & 0xe0;
(void) qlt_raw_wrt_risc_ram_word(qlt, 0x7A15, data);
}
+ } else {
+ EL(qlt, "qlt_mps_reset: read 0x7a15 failed.\n");
}
(void) qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 0);
}
/*
*** 6400,6409 ****
--- 9804,9820 ----
if (qlt_wwn_overload_prop(qlt) == TRUE) {
EL(qlt, "wwnn overloaded.\n");
}
+ /* configure extended logging from conf file */
+ if ((cnt = qlt_read_int_instance_prop(qlt, "extended-logging",
+ defval)) != defval) {
+ qlt->qlt_eel_level = (uint8_t)(cnt & 0xff);
+ EL(qlt, "extended error logging=%d\n", cnt);
+ }
+
if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt2k", defval)) !=
defval) {
qlt->qlt_bucketcnt[0] = cnt;
EL(qlt, "2k bucket o/l=%d\n", cnt);
}
*** 6429,6434 ****
--- 9840,10840 ----
if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt256", defval)) !=
defval) {
qlt->qlt_bucketcnt[4] = cnt;
EL(qlt, "256k bucket o/l=%d\n", cnt);
}
+ }
+
+ /* ******************************************************************* */
+ /* ****************** 27xx Dump Template Functions ******************* */
+ /* ******************************************************************* */
+
+ /*
+ * qlt_get_dmp_template
+ * Get dump template from firmware module
+ *
+ * Input:
+ * qlt: qlt_state_t pointer.
+ *
+ * Returns:
+ * qlt local function return status code.
+ *
+ * Context:
+ * Kernel context.
+ */
+ static fct_status_t
+ qlt_27xx_get_dmp_template(qlt_state_t *qlt)
+ {
+ ddi_device_acc_attr_t dev_acc_attr;
+ dev_info_t *dip = qlt->dip;
+ uint_t ncookies;
+ size_t discard;
+ uint32_t word_count, cnt, *bp, *dp;
+
+ if (qlt->dmp_template_dma_handle != NULL) {
+ (void) ddi_dma_unbind_handle(qlt->dmp_template_dma_handle);
+ if (qlt->dmp_template_acc_handle != NULL) {
+ ddi_dma_mem_free(&qlt->dmp_template_acc_handle);
+ }
+ ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
+ }
+
+ if ((word_count = tmplt2700_length01) == 0) {
+ EL(qlt, "No dump template, length=0\n");
+ return (QLT_FAILURE);
+ }
+
+ dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
+ dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
+ dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
+
+ if (ddi_dma_alloc_handle(dip, &qlt_queue_dma_attr,
+ DDI_DMA_SLEEP, 0, &qlt->dmp_template_dma_handle) !=
+ DDI_SUCCESS) {
+ EL(qlt, "Unable to allocate template handle");
+ return (QLT_FAILURE);
+ }
+
+ if (ddi_dma_mem_alloc(qlt->dmp_template_dma_handle,
+ (word_count << 2), &dev_acc_attr, DDI_DMA_CONSISTENT,
+ DDI_DMA_SLEEP, 0, &qlt->dmp_template_addr, &discard,
+ &qlt->dmp_template_acc_handle) != DDI_SUCCESS) {
+ ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
+ EL(qlt, "Unable to allocate template buffer");
+ return (QLT_FAILURE);
+ }
+
+ if (ddi_dma_addr_bind_handle(qlt->dmp_template_dma_handle, NULL,
+ qlt->dmp_template_addr, (word_count << 2),
+ DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
+ &qlt->dmp_template_cookie, &ncookies) != DDI_SUCCESS) {
+ ddi_dma_mem_free(&qlt->dmp_template_acc_handle);
+ ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
+ EL(qlt, "Unable to bind template handle");
+ return (QLT_FAILURE);
+ }
+
+ if (ncookies != 1) {
+ (void) ddi_dma_unbind_handle(qlt->dmp_template_dma_handle);
+ ddi_dma_mem_free(&qlt->dmp_template_acc_handle);
+ ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
+ EL(qlt, "cookies (%d) > 1.\n", ncookies);
+ return (QLT_FAILURE);
+ }
+
+ /* Get big endian template. */
+ bp = (uint32_t *)qlt->dmp_template_addr;
+ dp = (uint32_t *)tmplt2700_code01;
+ for (cnt = 0; cnt < word_count; cnt++) {
+ ddi_put32(qlt->dmp_template_acc_handle, bp, *dp++);
+ if (cnt > 6) {
+ qlt_chg_endian((uint8_t *)bp, 4);
+ }
+ bp++;
+ }
+
+ return (QLT_SUCCESS);
+ }
+
+ static int
+ qlt_27xx_dt_riob1(qlt_state_t *qlt, qlt_dt_riob1_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ int esize;
+ uint32_t i, cnt;
+ uint8_t *bp = dbuff;
+ uint32_t addr = entry->addr;
+ uint32_t reg = entry->pci_offset;
+
+ cnt = CHAR_TO_SHORT(entry->reg_count_l, entry->reg_count_h);
+ esize = cnt * 4; /* addr */
+ esize += cnt * entry->reg_size; /* data */
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+
+ REG_WR32(qlt, REG_IOBUS_BASE_ADDR, addr);
+ while (cnt--) {
+ *bp++ = LSB(LSW(addr));
+ *bp++ = MSB(LSW(addr));
+ *bp++ = LSB(MSW(addr));
+ *bp++ = MSB(MSW(addr));
+ for (i = 0; i < entry->reg_size; i++) {
+ *bp++ = REG_RD8(qlt, reg++);
+ }
+ addr++;
+ }
+
+ return (esize);
+ }
+
+ static void
+ qlt_27xx_dt_wiob1(qlt_state_t *qlt, qlt_dt_wiob1_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ uint32_t reg = entry->pci_offset;
+
+ if (dbuff == NULL) {
+ return;
+ }
+ if (dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=0\n");
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return;
+ }
+
+ REG_WR32(qlt, REG_IOBUS_BASE_ADDR, entry->addr);
+ REG_WR32(qlt, reg, entry->data);
+ }
+
+ static int
+ qlt_27xx_dt_riob2(qlt_state_t *qlt, qlt_dt_riob2_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ int esize;
+ uint32_t i, cnt;
+ uint8_t *bp = dbuff;
+ uint32_t reg = entry->pci_offset;
+ uint32_t addr = entry->addr;
+
+ cnt = CHAR_TO_SHORT(entry->reg_count_l, entry->reg_count_h);
+ esize = cnt * 4; /* addr */
+ esize += cnt * entry->reg_size; /* data */
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+
+ REG_WR32(qlt, REG_IOBUS_BASE_ADDR, addr);
+ REG_WR32(qlt, entry->bank_sel_offset, entry->reg_bank);
+ while (cnt--) {
+ *bp++ = LSB(LSW(addr));
+ *bp++ = MSB(LSW(addr));
+ *bp++ = LSB(MSW(addr));
+ *bp++ = MSB(MSW(addr));
+ for (i = 0; i < entry->reg_size; i++) {
+ *bp++ = REG_RD8(qlt, reg++);
+ }
+ addr++;
+ }
+
+ return (esize);
+ }
+
+ static void
+ qlt_27xx_dt_wiob2(qlt_state_t *qlt, qlt_dt_wiob2_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ uint16_t data;
+ uint32_t reg = entry->pci_offset;
+
+ if (dbuff == NULL) {
+ return;
+ }
+ if (dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=0\n");
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return;
+ }
+
+ data = CHAR_TO_SHORT(entry->data_l, entry->data_h);
+
+ REG_WR32(qlt, REG_IOBUS_BASE_ADDR, entry->addr);
+ REG_WR32(qlt, entry->bank_sel_offset, entry->reg_bank);
+ REG_WR16(qlt, reg, data);
+ }
+
+ static int
+ qlt_27xx_dt_rpci(qlt_state_t *qlt, qlt_dt_rpci_t *entry, uint8_t *dbuff,
+ uint8_t *dbuff_end)
+ {
+ int esize;
+ uint32_t i;
+ uint8_t *bp = dbuff;
+ uint32_t reg = entry->addr;
+
+ esize = 4; /* addr */
+ esize += 4; /* data */
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+
+ *bp++ = LSB(LSW(entry->addr));
+ *bp++ = MSB(LSW(entry->addr));
+ *bp++ = LSB(MSW(entry->addr));
+ *bp++ = MSB(MSW(entry->addr));
+ for (i = 0; i < 4; i++) {
+ *bp++ = REG_RD8(qlt, reg++);
+ }
+
+ return (esize);
+ }
+
+ static void
+ qlt_27xx_dt_wpci(qlt_state_t *qlt, qlt_dt_wpci_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ uint32_t reg = entry->addr;
+
+ if (dbuff == NULL) {
+ return;
+ }
+ if (dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=0\n");
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return;
+ }
+
+ REG_WR32(qlt, reg, entry->data);
+ }
+
+ static int
+ qlt_27xx_dt_rram(qlt_state_t *qlt, qlt_dt_rram_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ int esize, rval;
+ uint32_t start = entry->start_addr;
+ uint32_t end = entry->end_addr;
+
+ if (entry->ram_area == 2) {
+ end = qlt->fw_ext_memory_end;
+ } else if (entry->ram_area == 3) {
+ start = qlt->fw_shared_ram_start;
+ end = qlt->fw_shared_ram_end;
+ } else if (entry->ram_area == 4) {
+ start = qlt->fw_ddr_ram_start;
+ end = qlt->fw_ddr_ram_end;
+ } else if (entry->ram_area != 1) {
+ EL(qlt, "skipped, unknown RAM_AREA %d\n", entry->ram_area);
+ start = 0;
+ end = 0;
+ }
+ esize = end > start ? end - start : 0;
+ if (esize) {
+ esize = (esize + 1) * 4;
+ }
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize == 0 || esize + dbuff >= dbuff_end) {
+ if (esize != 0) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n",
+ esize);
+ } else {
+ EL(qlt, "skipped, no ram_area=%xh, start=%xh "
+ "end=%xh\n", entry->ram_area, start, end);
+ }
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+ entry->end_addr = end;
+ entry->start_addr = start;
+
+ if ((rval = qlt_27xx_dump_ram(qlt, MBC_DUMP_RAM_EXTENDED,
+ start, esize / 4, dbuff)) != QLT_SUCCESS) {
+ EL(qlt, "dump_ram failed, rval=%xh, addr=%xh, len=%xh, "
+ "esize=0\n", rval, start, esize / 4);
+ return (0);
+ }
+
+ return (esize);
+ }
+
+ static int
+ qlt_27xx_dt_gque(qlt_state_t *qlt, qlt_dt_gque_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ int esize;
+ uint32_t cnt, q_cnt, e_cnt, i;
+ uint8_t *bp = dbuff, *dp;
+
+ if (entry->queue_type == 1) {
+ e_cnt = qlt->qlt_queue_cnt;
+ esize = e_cnt * 2; /* queue number */
+ esize += e_cnt * 2; /* queue entries */
+
+ /* queue size */
+ esize += REQUEST_QUEUE_ENTRIES * IOCB_SIZE;
+ for (q_cnt = 1; q_cnt < qlt->qlt_queue_cnt; q_cnt++) {
+ esize += REQUEST_QUEUE_MQ_ENTRIES * IOCB_SIZE;
+ }
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n",
+ esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+ entry->num_queues = e_cnt;
+
+ for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
+ e_cnt = q_cnt == 0 ?
+ REQUEST_QUEUE_ENTRIES : REQUEST_QUEUE_MQ_ENTRIES;
+ dp = (uint8_t *)qlt->mq_req[q_cnt].mq_ptr;
+ *bp++ = LSB(q_cnt);
+ *bp++ = MSB(q_cnt);
+ *bp++ = LSB(e_cnt);
+ *bp++ = MSB(e_cnt);
+ for (cnt = 0; cnt < e_cnt; cnt++) {
+ for (i = 0; i < IOCB_SIZE; i++) {
+ *bp++ = *dp++;
+ }
+ }
+ }
+ } else if (entry->queue_type == 2) {
+
+ e_cnt = qlt->qlt_queue_cnt;
+ esize = e_cnt * 2; /* queue number */
+ esize += e_cnt * 2; /* queue entries */
+
+ /* queue size */
+ esize += RESPONSE_QUEUE_ENTRIES * IOCB_SIZE;
+ for (q_cnt = 1; q_cnt < qlt->qlt_queue_cnt; q_cnt++) {
+ esize += RESPONSE_QUEUE_MQ_ENTRIES * IOCB_SIZE;
+ }
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped2, no buffer space, needed=%xh\n",
+ esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+ entry->num_queues = e_cnt;
+
+ for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
+ e_cnt = q_cnt == 0 ?
+ RESPONSE_QUEUE_ENTRIES : RESPONSE_QUEUE_MQ_ENTRIES;
+ dp = (uint8_t *)qlt->mq_resp[q_cnt].mq_ptr;
+ *bp++ = LSB(q_cnt);
+ *bp++ = MSB(q_cnt);
+ *bp++ = LSB(e_cnt);
+ *bp++ = MSB(e_cnt);
+ for (cnt = 0; cnt < e_cnt; cnt++) {
+ for (i = 0; i < IOCB_SIZE; i++) {
+ *bp++ = *dp++;
+ }
+ }
+ }
+ } else if (entry->queue_type == 3) {
+ e_cnt = 1;
+ esize = e_cnt * 2; /* queue number */
+ esize += e_cnt * 2; /* queue entries */
+
+ /* queue size */
+ esize += RESPONSE_QUEUE_ENTRIES * IOCB_SIZE;
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped2, no buffer space, needed=%xh\n",
+ esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+ entry->num_queues = e_cnt;
+
+ for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
+ e_cnt = ATIO_QUEUE_ENTRIES;
+ dp = (uint8_t *)qlt->atio_ptr;
+ *bp++ = LSB(q_cnt);
+ *bp++ = MSB(q_cnt);
+ *bp++ = LSB(e_cnt);
+ *bp++ = MSB(e_cnt);
+ for (cnt = 0; cnt < e_cnt; cnt++) {
+ for (i = 0; i < IOCB_SIZE; i++) {
+ *bp++ = *dp++;
+ }
+ }
+ }
+ } else {
+ EL(qlt, "skipped, unknown queue_type %d, esize=0\n",
+ entry->queue_type);
+ if (dbuff != NULL) {
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+ return (0);
+ }
+
+ return (esize);
+ }
+
+ /*ARGSUSED*/
+ static int
+ qlt_27xx_dt_gfce(qlt_state_t *qlt, qlt_dt_gfce_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ if (dbuff != NULL) {
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+
+ return (0);
+ }
+
+ static void
+ qlt_27xx_dt_prisc(qlt_state_t *qlt, qlt_dt_prisc_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ clock_t timer;
+
+ if (dbuff == NULL) {
+ return;
+ }
+ if (dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=0\n");
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return;
+ }
+
+ /* Pause RISC. */
+ if ((REG_RD32(qlt, REG_RISC_STATUS) & BIT_8) == 0) {
+ REG_WR32(qlt, REG_HCCR, 0x30000000);
+ for (timer = 30000;
+ (REG_RD32(qlt, REG_RISC_STATUS) & BIT_8) == 0;
+ timer--) {
+ if (timer) {
+ drv_usecwait(100);
+ if (timer % 10000 == 0) {
+ EL(qlt, "risc pause %d\n", timer);
+ }
+ } else {
+ EL(qlt, "risc pause timeout\n");
+ break;
+ }
+ }
+ }
+ }
+
+ static void
+ qlt_27xx_dt_rrisc(qlt_state_t *qlt, qlt_dt_rrisc_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ clock_t timer;
+ uint16_t rom_status;
+
+ if (dbuff == NULL) {
+ return;
+ }
+ if (dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=0\n");
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return;
+ }
+
+ /* Shutdown DMA. */
+ REG_WR32(qlt, REG_CTRL_STATUS, DMA_SHUTDOWN_CTRL);
+
+ /* Wait for DMA to stop. */
+ for (timer = 0; timer < 30000; timer++) {
+ if (!(REG_RD32(qlt, REG_CTRL_STATUS) & DMA_ACTIVE_STATUS)) {
+ break;
+ }
+ drv_usecwait(100);
+ }
+
+ /* Reset the chip. */
+ REG_WR32(qlt, REG_CTRL_STATUS, CHIP_SOFT_RESET);
+ drv_usecwait(200);
+
+ /* Wait for RISC to recover from reset. */
+ for (timer = 30000; timer; timer--) {
+ rom_status = REG_RD16(qlt, REG_MBOX0);
+ if ((rom_status & MBS_ROM_STATUS_MASK) != MBS_ROM_BUSY) {
+ break;
+ }
+ drv_usecwait(100);
+ }
+
+ /* Wait for reset to finish. */
+ for (timer = 30000; timer; timer--) {
+ if (!(REG_RD32(qlt, REG_CTRL_STATUS) & CHIP_SOFT_RESET)) {
+ break;
+ }
+ drv_usecwait(100);
+ }
+
+ /* XXX: Disable Interrupts (Probably not needed) */
+ REG_WR32(qlt, REG_INTR_CTRL, 0);
+
+ qlt->qlt_intr_enabled = 0;
+ }
+
+ static void
+ qlt_27xx_dt_dint(qlt_state_t *qlt, qlt_dt_dint_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ if (dbuff == NULL) {
+ return;
+ }
+ if (dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=0\n");
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return;
+ }
+
+ PCICFG_WR32(qlt, entry->pci_offset, entry->data);
+ }
+
+ /*ARGSUSED*/
+ static int
+ qlt_27xx_dt_ghbd(qlt_state_t *qlt, qlt_dt_ghbd_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ if (dbuff != NULL) {
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+
+ return (0);
+ }
+
+ /*ARGSUSED*/
+ static int
+ qlt_27xx_dt_scra(qlt_state_t *qlt, qlt_dt_scra_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ if (dbuff != NULL) {
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+
+ return (0);
+ }
+
+ static int
+ qlt_27xx_dt_rrreg(qlt_state_t *qlt, qlt_dt_rrreg_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ int esize;
+ uint32_t i;
+ uint8_t *bp = dbuff;
+ uint32_t addr = entry->addr;
+ uint32_t cnt = entry->count;
+
+ esize = cnt * 4; /* addr */
+ esize += cnt * 4; /* data */
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+
+ REG_WR32(qlt, REG_IOBUS_BASE_ADDR, 0x40);
+ while (cnt--) {
+ REG_WR32(qlt, 0xc0, addr | 0x80000000);
+ *bp++ = LSB(LSW(addr));
+ *bp++ = MSB(LSW(addr));
+ *bp++ = LSB(MSW(addr));
+ *bp++ = MSB(MSW(addr));
+ for (i = 0; i < 4; i++) {
+ *bp++ = REG_RD8(qlt, i);
+ }
+ addr += 4;
+ }
+
+ return (esize);
+ }
+
+ static void
+ qlt_27xx_dt_wrreg(qlt_state_t *qlt, qlt_dt_wrreg_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ if (dbuff == NULL) {
+ return;
+ }
+ if (dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=0\n");
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return;
+ }
+
+ REG_WR32(qlt, REG_IOBUS_BASE_ADDR, 0x40);
+ REG_WR32(qlt, 0xc4, entry->data);
+ REG_WR32(qlt, 0xc0, entry->addr);
+ }
+
+ static int
+ qlt_27xx_dt_rrram(qlt_state_t *qlt, qlt_dt_rrram_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ int rval, esize;
+
+ esize = entry->count * 4; /* data */
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+
+ if ((rval = qlt_27xx_dump_ram(qlt, MBC_MPI_RAM, entry->addr,
+ entry->count, dbuff)) != QLT_SUCCESS) {
+ EL(qlt, "dump_ram failed, rval=%xh, addr=%xh, len=%xh, "
+ "esize=0\n", rval, entry->addr, entry->count);
+ return (0);
+ }
+
+ return (esize);
+ }
+
+ static int
+ qlt_27xx_dt_rpcic(qlt_state_t *qlt, qlt_dt_rpcic_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ int esize;
+ uint32_t i;
+ uint8_t *bp = dbuff;
+ uint32_t addr = entry->addr;
+ uint32_t cnt = entry->count;
+
+ esize = cnt * 4; /* addr */
+ esize += cnt * 4; /* data */
+
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+
+ while (cnt--) {
+ *bp++ = LSB(LSW(addr));
+ *bp++ = MSB(LSW(addr));
+ *bp++ = LSB(MSW(addr));
+ *bp++ = MSB(MSW(addr));
+ for (i = 0; i < 4; i++) {
+ *bp++ = PCICFG_RD8(qlt, addr++);
+ }
+ }
+
+ return (esize);
+ }
+
+ /*ARGSUSED*/
+ static int
+ qlt_27xx_dt_gques(qlt_state_t *qlt, qlt_dt_gques_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ if (entry->queue_type == 1) {
+ EL(qlt, "skipped, no request queue shadowing, esize=0\n");
+ if (dbuff != NULL) {
+ entry->num_queues = 0;
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+ return (0);
+ } else if (entry->queue_type == 2) {
+ EL(qlt, "skipped, no response queue shadowing, esize=0\n");
+ if (dbuff != NULL) {
+ entry->num_queues = 0;
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+ return (0);
+ } else if (entry->queue_type == 3) {
+ EL(qlt, "skipped, no ATIO queue, esize=0\n");
+ if (dbuff != NULL) {
+ entry->num_queues = 0;
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+ return (0);
+ } else {
+ EL(qlt, "skipped, unknown queue_type %d, esize=0\n",
+ entry->queue_type);
+ if (dbuff != NULL) {
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+ return (0);
+ }
+ }
+
+ static int
+ qlt_27xx_dt_wdmp(qlt_state_t *qlt, qlt_dt_wdmp_t *entry,
+ uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+ int esize;
+ uint8_t *bp = dbuff;
+ uint32_t data, cnt = entry->length, *dp = entry->data;
+
+ esize = cnt;
+ if (dbuff == NULL) {
+ return (esize);
+ }
+ if (esize + dbuff >= dbuff_end) {
+ EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ return (0);
+ }
+
+ while (cnt--) {
+ data = *dp++;
+ *bp++ = LSB(LSW(data));
+ *bp++ = MSB(LSW(data));
+ *bp++ = LSB(MSW(data));
+ *bp++ = MSB(MSW(data));
+ }
+
+ return (esize);
+ }
+
+ /*
+ * qlt_27xx_dump_ram
+ * Dumps RAM.
+ * Risc interrupts must be disabled when this routine is called.
+ *
+ * Input:
+ * pi: port info pointer.
+ * cmd: MBC_DUMP_RAM_EXTENDED/MBC_MPI_RAM.
+ * risc_address: RISC code start address.
+ * len: Number of words.
+ * bp: buffer pointer.
+ *
+ * Returns:
+ * qlt local function return status code.
+ *
+ * Context:
+ * Interrupt or Kernel context, no mailbox commands allowed.
+ */
+ /*ARGSUSED*/
+ static int
+ qlt_27xx_dump_ram(qlt_state_t *qlt, uint16_t cmd, uint32_t risc_address,
+ uint32_t len, uint8_t *bp)
+ {
+ uint8_t *dp;
+ uint32_t words_to_read, endaddr;
+ uint32_t i;
+ int rval = QLT_SUCCESS;
+
+ endaddr = risc_address + len;
+ words_to_read = 0;
+ while (risc_address < endaddr) {
+ words_to_read = MBOX_DMA_MEM_SIZE >> 2;
+ if ((words_to_read + risc_address) > endaddr) {
+ words_to_read = endaddr - risc_address;
+ }
+
+ if (cmd == MBC_DUMP_RAM_EXTENDED) {
+ rval = qlt_read_risc_ram(qlt, risc_address,
+ words_to_read);
+ } else {
+ rval = qlt_mbx_mpi_ram(qlt, risc_address,
+ words_to_read, 0);
+ }
+
+ if (rval != QLT_SUCCESS) {
+ EL(qlt, "Error reading risc ram = %xh len = %x\n",
+ risc_address, words_to_read);
+ return (rval);
+ }
+
+ dp = (uint8_t *)(qlt->queue_mem_ptr + MBOX_DMA_MEM_OFFSET);
+ for (i = 0; i < (words_to_read * 4); i++) {
+ *bp++ = *dp++;
+ }
+ risc_address += words_to_read;
+ }
+
+ return (rval);
+ }
+
+ static uint32_t
+ qlt_27xx_dmp_parse_template(qlt_state_t *qlt, qlt_dt_hdr_t *template_hdr,
+ uint8_t *dump_buff, uint32_t buff_size)
+ {
+ int e_cnt, esize, num_of_entries;
+ uint32_t bsize;
+ time_t time;
+ uint8_t *dbuff, *dbuff_end;
+ qlt_dt_entry_t *entry;
+ int sane_end = 0;
+
+ dbuff = dump_buff; /* dbuff = NULL size determination. */
+ dbuff_end = dump_buff + buff_size;
+
+ if (template_hdr->type != DT_THDR) {
+ EL(qlt, "Template header not found\n");
+ return (0);
+ }
+ if (dbuff != NULL) {
+ (void) drv_getparm(TIME, &time);
+ template_hdr->driver_timestamp = LSD(time);
+ }
+
+ num_of_entries = template_hdr->num_of_entries;
+ entry = (qlt_dt_entry_t *)((caddr_t)template_hdr +
+ template_hdr->first_entry_offset);
+
+ bsize = template_hdr->size_of_template;
+ for (e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
+ /*
+ * Decode the entry type and process it accordingly
+ */
+ esize = 0;
+ switch (entry->h.type) {
+ case DT_NOP:
+ if (dbuff != NULL) {
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+ break;
+ case DT_TEND:
+ if (dbuff != NULL) {
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ }
+ sane_end++;
+ break;
+ case DT_RIOB1:
+ esize = qlt_27xx_dt_riob1(qlt, (qlt_dt_riob1_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_WIOB1:
+ qlt_27xx_dt_wiob1(qlt, (qlt_dt_wiob1_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_RIOB2:
+ esize = qlt_27xx_dt_riob2(qlt, (qlt_dt_riob2_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_WIOB2:
+ qlt_27xx_dt_wiob2(qlt, (qlt_dt_wiob2_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_RPCI:
+ esize = qlt_27xx_dt_rpci(qlt, (qlt_dt_rpci_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_WPCI:
+ qlt_27xx_dt_wpci(qlt, (qlt_dt_wpci_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_RRAM:
+ esize = qlt_27xx_dt_rram(qlt, (qlt_dt_rram_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_GQUE:
+ esize = qlt_27xx_dt_gque(qlt, (qlt_dt_gque_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_GFCE:
+ esize = qlt_27xx_dt_gfce(qlt, (qlt_dt_gfce_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_PRISC:
+ qlt_27xx_dt_prisc(qlt, (qlt_dt_prisc_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_RRISC:
+ qlt_27xx_dt_rrisc(qlt, (qlt_dt_rrisc_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_DINT:
+ qlt_27xx_dt_dint(qlt, (qlt_dt_dint_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_GHBD:
+ esize = qlt_27xx_dt_ghbd(qlt, (qlt_dt_ghbd_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_SCRA:
+ esize = qlt_27xx_dt_scra(qlt, (qlt_dt_scra_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_RRREG:
+ esize = qlt_27xx_dt_rrreg(qlt, (qlt_dt_rrreg_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_WRREG:
+ qlt_27xx_dt_wrreg(qlt, (qlt_dt_wrreg_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_RRRAM:
+ esize = qlt_27xx_dt_rrram(qlt, (qlt_dt_rrram_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_RPCIC:
+ esize = qlt_27xx_dt_rpcic(qlt, (qlt_dt_rpcic_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_GQUES:
+ esize = qlt_27xx_dt_gques(qlt, (qlt_dt_gques_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ case DT_WDMP:
+ esize = qlt_27xx_dt_wdmp(qlt, (qlt_dt_wdmp_t *)entry,
+ dbuff, dbuff_end);
+ break;
+ default:
+ entry->h.driver_flags = (uint8_t)
+ (entry->h.driver_flags | SKIPPED_FLAG);
+ EL(qlt, "Entry ID=%d, type=%d unknown\n", e_cnt,
+ entry->h.type);
+ break;
+ }
+ if (dbuff != NULL && esize) {
+ dbuff += esize;
+ }
+ bsize += esize;
+ /* next entry in the template */
+ entry = (qlt_dt_entry_t *)((caddr_t)entry + entry->h.size);
+ }
+ if (sane_end > 1) {
+ EL(qlt, "Template configuration error. Check Template\n");
+ }
+
+ return (bsize);
}