svn commit: r234429 - in stable/9/sys: conf dev/mfi modules/mfi
Doug Ambrisko
ambrisko at FreeBSD.org
Wed Apr 18 18:31:12 UTC 2012
Author: ambrisko
Date: Wed Apr 18 18:31:11 2012
New Revision: 234429
URL: http://svn.freebsd.org/changeset/base/234429
Log:
MFC r233711:
Major update to driver to support for Drake Skinny and ThunderBolt cards.
MFC r233768:
Change typedef atomic_t to struct mfi_atomic to avoid name space
collision and some couple more style changes.
MFC r233805:
Move struct megasas_sge from mfi_ioctl.h to mfivar.h so we can
remove including machine/bus.h. Add some more mfi_ prefixes to
avoid name space pollution.
MFC r233877:
- Do not include machine/atomic.h. It is no longer necessary since r233768.
- Remove bogus "atomic" macros and a read-only variable from softc.
Added:
stable/9/sys/dev/mfi/mfi_syspd.c
- copied unchanged from r233711, head/sys/dev/mfi/mfi_syspd.c
stable/9/sys/dev/mfi/mfi_tbolt.c
- copied, changed from r233711, head/sys/dev/mfi/mfi_tbolt.c
Modified:
stable/9/sys/conf/files
stable/9/sys/dev/mfi/mfi.c
stable/9/sys/dev/mfi/mfi_cam.c
stable/9/sys/dev/mfi/mfi_debug.c
stable/9/sys/dev/mfi/mfi_disk.c
stable/9/sys/dev/mfi/mfi_ioctl.h
stable/9/sys/dev/mfi/mfi_linux.c
stable/9/sys/dev/mfi/mfi_pci.c
stable/9/sys/dev/mfi/mfireg.h
stable/9/sys/dev/mfi/mfivar.h
stable/9/sys/modules/mfi/Makefile
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/conf/ (props changed)
Modified: stable/9/sys/conf/files
==============================================================================
--- stable/9/sys/conf/files Wed Apr 18 18:11:32 2012 (r234428)
+++ stable/9/sys/conf/files Wed Apr 18 18:31:11 2012 (r234429)
@@ -1414,6 +1414,8 @@ dev/mfi/mfi.c optional mfi
dev/mfi/mfi_debug.c optional mfi
dev/mfi/mfi_pci.c optional mfi pci
dev/mfi/mfi_disk.c optional mfi
+dev/mfi/mfi_syspd.c optional mfi
+dev/mfi/mfi_tbolt.c optional mfi
dev/mfi/mfi_linux.c optional mfi compat_linux
dev/mfi/mfi_cam.c optional mfip scbus
dev/mii/acphy.c optional miibus | acphy
Modified: stable/9/sys/dev/mfi/mfi.c
==============================================================================
--- stable/9/sys/dev/mfi/mfi.c Wed Apr 18 18:11:32 2012 (r234428)
+++ stable/9/sys/dev/mfi/mfi.c Wed Apr 18 18:31:11 2012 (r234429)
@@ -53,6 +53,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_compat.h"
#include "opt_mfi.h"
#include <sys/param.h>
@@ -72,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
+#include <sys/taskqueue.h>
#include <machine/bus.h>
#include <machine/resource.h>
@@ -79,10 +81,11 @@ __FBSDID("$FreeBSD$");
#include <dev/mfi/mfireg.h>
#include <dev/mfi/mfi_ioctl.h>
#include <dev/mfi/mfivar.h>
+#include <sys/interrupt.h>
+#include <sys/priority.h>
static int mfi_alloc_commands(struct mfi_softc *);
static int mfi_comms_init(struct mfi_softc *);
-static int mfi_wait_command(struct mfi_softc *, struct mfi_command *);
static int mfi_get_controller_info(struct mfi_softc *);
static int mfi_get_log_state(struct mfi_softc *,
struct mfi_evt_log_state **);
@@ -93,29 +96,39 @@ static void mfi_data_cb(void *, bus_dma_
static void mfi_startup(void *arg);
static void mfi_intr(void *arg);
static void mfi_ldprobe(struct mfi_softc *sc);
+static void mfi_syspdprobe(struct mfi_softc *sc);
+static void mfi_handle_evt(void *context, int pending);
static int mfi_aen_register(struct mfi_softc *sc, int seq, int locale);
static void mfi_aen_complete(struct mfi_command *);
-static int mfi_aen_setup(struct mfi_softc *, uint32_t);
static int mfi_add_ld(struct mfi_softc *sc, int);
static void mfi_add_ld_complete(struct mfi_command *);
+static int mfi_add_sys_pd(struct mfi_softc *sc, int);
+static void mfi_add_sys_pd_complete(struct mfi_command *);
static struct mfi_command * mfi_bio_command(struct mfi_softc *);
static void mfi_bio_complete(struct mfi_command *);
-static int mfi_mapcmd(struct mfi_softc *, struct mfi_command *);
+static struct mfi_command *mfi_build_ldio(struct mfi_softc *,struct bio*);
+static struct mfi_command *mfi_build_syspdio(struct mfi_softc *,struct bio*);
static int mfi_send_frame(struct mfi_softc *, struct mfi_command *);
-static void mfi_complete(struct mfi_softc *, struct mfi_command *);
static int mfi_abort(struct mfi_softc *, struct mfi_command *);
static int mfi_linux_ioctl_int(struct cdev *, u_long, caddr_t, int, struct thread *);
static void mfi_timeout(void *);
static int mfi_user_command(struct mfi_softc *,
struct mfi_ioc_passthru *);
-static void mfi_enable_intr_xscale(struct mfi_softc *sc);
-static void mfi_enable_intr_ppc(struct mfi_softc *sc);
-static int32_t mfi_read_fw_status_xscale(struct mfi_softc *sc);
-static int32_t mfi_read_fw_status_ppc(struct mfi_softc *sc);
-static int mfi_check_clear_intr_xscale(struct mfi_softc *sc);
-static int mfi_check_clear_intr_ppc(struct mfi_softc *sc);
-static void mfi_issue_cmd_xscale(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
-static void mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
+static void mfi_enable_intr_xscale(struct mfi_softc *sc);
+static void mfi_enable_intr_ppc(struct mfi_softc *sc);
+static int32_t mfi_read_fw_status_xscale(struct mfi_softc *sc);
+static int32_t mfi_read_fw_status_ppc(struct mfi_softc *sc);
+static int mfi_check_clear_intr_xscale(struct mfi_softc *sc);
+static int mfi_check_clear_intr_ppc(struct mfi_softc *sc);
+static void mfi_issue_cmd_xscale(struct mfi_softc *sc, bus_addr_t bus_add,
+ uint32_t frame_cnt);
+static void mfi_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add,
+ uint32_t frame_cnt);
+static int mfi_config_lock(struct mfi_softc *sc, uint32_t opcode);
+static void mfi_config_unlock(struct mfi_softc *sc, int locked);
+static int mfi_check_command_pre(struct mfi_softc *sc, struct mfi_command *cm);
+static void mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm);
+static int mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm);
SYSCTL_NODE(_hw, OID_AUTO, mfi, CTLFLAG_RD, 0, "MFI driver parameters");
static int mfi_event_locale = MFI_EVT_LOCALE_ALL;
@@ -133,6 +146,11 @@ TUNABLE_INT("hw.mfi.max_cmds", &mfi_max_
SYSCTL_INT(_hw_mfi, OID_AUTO, max_cmds, CTLFLAG_RD, &mfi_max_cmds,
0, "Max commands");
+static int mfi_detect_jbod_change = 1;
+TUNABLE_INT("hw.mfi.detect_jbod_change", &mfi_detect_jbod_change);
+SYSCTL_INT(_hw_mfi, OID_AUTO, detect_jbod_change, CTLFLAG_RW,
+ &mfi_detect_jbod_change, 0, "Detect a change to a JBOD");
+
/* Management interface */
static d_open_t mfi_open;
static d_close_t mfi_close;
@@ -152,6 +170,7 @@ static struct cdevsw mfi_cdevsw = {
MALLOC_DEFINE(M_MFIBUF, "mfibuf", "Buffers for the MFI driver");
#define MFI_INQ_LENGTH SHORT_INQUIRY_LENGTH
+struct mfi_skinny_dma_info mfi_skinny;
static void
mfi_enable_intr_xscale(struct mfi_softc *sc)
@@ -162,12 +181,17 @@ mfi_enable_intr_xscale(struct mfi_softc
static void
mfi_enable_intr_ppc(struct mfi_softc *sc)
{
- MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF);
if (sc->mfi_flags & MFI_FLAGS_1078) {
+ MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF);
MFI_WRITE4(sc, MFI_OMSK, ~MFI_1078_EIM);
- } else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+ }
+ else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+ MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF);
MFI_WRITE4(sc, MFI_OMSK, ~MFI_GEN2_EIM);
}
+ else if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+ MFI_WRITE4(sc, MFI_OMSK, ~0x00000001);
+ }
}
static int32_t
@@ -205,35 +229,51 @@ mfi_check_clear_intr_ppc(struct mfi_soft
if (!(status & MFI_1078_RM)) {
return 1;
}
- } else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+ }
+ else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
if (!(status & MFI_GEN2_RM)) {
return 1;
}
}
-
- MFI_WRITE4(sc, MFI_ODCR0, status);
+ else if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+ if (!(status & MFI_SKINNY_RM)) {
+ return 1;
+ }
+ }
+ if (sc->mfi_flags & MFI_FLAGS_SKINNY)
+ MFI_WRITE4(sc, MFI_OSTS, status);
+ else
+ MFI_WRITE4(sc, MFI_ODCR0, status);
return 0;
}
static void
-mfi_issue_cmd_xscale(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
+mfi_issue_cmd_xscale(struct mfi_softc *sc, bus_addr_t bus_add, uint32_t frame_cnt)
{
MFI_WRITE4(sc, MFI_IQP,(bus_add >>3)|frame_cnt);
}
static void
-mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
+mfi_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add, uint32_t frame_cnt)
{
- MFI_WRITE4(sc, MFI_IQP, (bus_add |frame_cnt <<1)|1 );
+ if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+ MFI_WRITE4(sc, MFI_IQPL, (bus_add | frame_cnt <<1)|1 );
+ MFI_WRITE4(sc, MFI_IQPH, 0x00000000);
+ } else {
+ MFI_WRITE4(sc, MFI_IQP, (bus_add | frame_cnt <<1)|1 );
+ }
}
-static int
+int
mfi_transition_firmware(struct mfi_softc *sc)
{
uint32_t fw_state, cur_state;
int max_wait, i;
+ uint32_t cur_abs_reg_val = 0;
+ uint32_t prev_abs_reg_val = 0;
- fw_state = sc->mfi_read_fw_status(sc)& MFI_FWSTATE_MASK;
+ cur_abs_reg_val = sc->mfi_read_fw_status(sc);
+ fw_state = cur_abs_reg_val & MFI_FWSTATE_MASK;
while (fw_state != MFI_FWSTATE_READY) {
if (bootverbose)
device_printf(sc->mfi_dev, "Waiting for firmware to "
@@ -244,38 +284,60 @@ mfi_transition_firmware(struct mfi_softc
device_printf(sc->mfi_dev, "Firmware fault\n");
return (ENXIO);
case MFI_FWSTATE_WAIT_HANDSHAKE:
- MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_CLEAR_HANDSHAKE);
- max_wait = 2;
+ if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+ MFI_WRITE4(sc, MFI_SKINNY_IDB, MFI_FWINIT_CLEAR_HANDSHAKE);
+ else
+ MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_CLEAR_HANDSHAKE);
+ max_wait = MFI_RESET_WAIT_TIME;
break;
case MFI_FWSTATE_OPERATIONAL:
- MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_READY);
- max_wait = 10;
+ if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+ MFI_WRITE4(sc, MFI_SKINNY_IDB, 7);
+ else
+ MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_READY);
+ max_wait = MFI_RESET_WAIT_TIME;
break;
case MFI_FWSTATE_UNDEFINED:
case MFI_FWSTATE_BB_INIT:
- max_wait = 2;
+ max_wait = MFI_RESET_WAIT_TIME;
+ break;
+ case MFI_FWSTATE_FW_INIT_2:
+ max_wait = MFI_RESET_WAIT_TIME;
break;
case MFI_FWSTATE_FW_INIT:
- case MFI_FWSTATE_DEVICE_SCAN:
case MFI_FWSTATE_FLUSH_CACHE:
- max_wait = 20;
+ max_wait = MFI_RESET_WAIT_TIME;
+ break;
+ case MFI_FWSTATE_DEVICE_SCAN:
+ max_wait = MFI_RESET_WAIT_TIME; /* wait for 180 seconds */
+ prev_abs_reg_val = cur_abs_reg_val;
break;
case MFI_FWSTATE_BOOT_MESSAGE_PENDING:
- MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_HOTPLUG);
- max_wait = 10;
+ if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+ MFI_WRITE4(sc, MFI_SKINNY_IDB, MFI_FWINIT_HOTPLUG);
+ else
+ MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_HOTPLUG);
+ max_wait = MFI_RESET_WAIT_TIME;
break;
default:
- device_printf(sc->mfi_dev,"Unknown firmware state %#x\n",
+ device_printf(sc->mfi_dev, "Unknown firmware state %#x\n",
fw_state);
return (ENXIO);
}
for (i = 0; i < (max_wait * 10); i++) {
- fw_state = sc->mfi_read_fw_status(sc) & MFI_FWSTATE_MASK;
+ cur_abs_reg_val = sc->mfi_read_fw_status(sc);
+ fw_state = cur_abs_reg_val & MFI_FWSTATE_MASK;
if (fw_state == cur_state)
DELAY(100000);
else
break;
}
+ if (fw_state == MFI_FWSTATE_DEVICE_SCAN) {
+ /* Check the device scanning progress */
+ if (prev_abs_reg_val != cur_abs_reg_val) {
+ continue;
+ }
+ }
if (fw_state == cur_state) {
device_printf(sc->mfi_dev, "Firmware stuck in state "
"%#x\n", fw_state);
@@ -286,26 +348,35 @@ mfi_transition_firmware(struct mfi_softc
}
static void
-mfi_addr32_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+mfi_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
- uint32_t *addr;
+ bus_addr_t *addr;
addr = arg;
*addr = segs[0].ds_addr;
}
+
int
mfi_attach(struct mfi_softc *sc)
{
uint32_t status;
int error, commsz, framessz, sensesz;
int frames, unit, max_fw_sge;
+ uint32_t tb_mem_size = 0;
+
+ if (sc == NULL)
+ return EINVAL;
- device_printf(sc->mfi_dev, "Megaraid SAS driver Ver 3.00 \n");
+ device_printf(sc->mfi_dev, "Megaraid SAS driver Ver %s \n",
+ MEGASAS_VERSION);
mtx_init(&sc->mfi_io_lock, "MFI I/O lock", NULL, MTX_DEF);
sx_init(&sc->mfi_config_lock, "MFI config");
TAILQ_INIT(&sc->mfi_ld_tqh);
+ TAILQ_INIT(&sc->mfi_syspd_tqh);
+ TAILQ_INIT(&sc->mfi_evt_queue);
+ TASK_INIT(&sc->mfi_evt_task, 0, mfi_handle_evt, sc);
TAILQ_INIT(&sc->mfi_aen_pids);
TAILQ_INIT(&sc->mfi_cam_ccbq);
@@ -314,15 +385,29 @@ mfi_attach(struct mfi_softc *sc)
mfi_initq_busy(sc);
mfi_initq_bio(sc);
+ sc->adpreset = 0;
+ sc->last_seq_num = 0;
+ sc->disableOnlineCtrlReset = 1;
+ sc->issuepend_done = 1;
+ sc->hw_crit_error = 0;
+
if (sc->mfi_flags & MFI_FLAGS_1064R) {
sc->mfi_enable_intr = mfi_enable_intr_xscale;
sc->mfi_read_fw_status = mfi_read_fw_status_xscale;
sc->mfi_check_clear_intr = mfi_check_clear_intr_xscale;
sc->mfi_issue_cmd = mfi_issue_cmd_xscale;
- }
- else {
+ } else if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+ sc->mfi_enable_intr = mfi_tbolt_enable_intr_ppc;
+ sc->mfi_disable_intr = mfi_tbolt_disable_intr_ppc;
+ sc->mfi_read_fw_status = mfi_tbolt_read_fw_status_ppc;
+ sc->mfi_check_clear_intr = mfi_tbolt_check_clear_intr_ppc;
+ sc->mfi_issue_cmd = mfi_tbolt_issue_cmd_ppc;
+ sc->mfi_adp_reset = mfi_tbolt_adp_reset;
+ sc->mfi_tbolt = 1;
+ TAILQ_INIT(&sc->mfi_cmd_tbolt_tqh);
+ } else {
sc->mfi_enable_intr = mfi_enable_intr_ppc;
- sc->mfi_read_fw_status = mfi_read_fw_status_ppc;
+ sc->mfi_read_fw_status = mfi_read_fw_status_ppc;
sc->mfi_check_clear_intr = mfi_check_clear_intr_ppc;
sc->mfi_issue_cmd = mfi_issue_cmd_ppc;
}
@@ -335,6 +420,32 @@ mfi_attach(struct mfi_softc *sc)
return (ENXIO);
}
+ /* Start: LSIP200113393 */
+ if (bus_dma_tag_create( sc->mfi_parent_dmat, /* parent */
+ 1, 0, /* algnmnt, boundary */
+ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MEGASAS_MAX_NAME*sizeof(bus_addr_t), /* maxsize */
+ 1, /* msegments */
+ MEGASAS_MAX_NAME*sizeof(bus_addr_t), /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->verbuf_h_dmat)) {
+ device_printf(sc->mfi_dev, "Cannot allocate verbuf_h_dmat DMA tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->verbuf_h_dmat, (void **)&sc->verbuf,
+ BUS_DMA_NOWAIT, &sc->verbuf_h_dmamap)) {
+ device_printf(sc->mfi_dev, "Cannot allocate verbuf_h_dmamap memory\n");
+ return (ENOMEM);
+ }
+ bzero(sc->verbuf, MEGASAS_MAX_NAME*sizeof(bus_addr_t));
+ bus_dmamap_load(sc->verbuf_h_dmat, sc->verbuf_h_dmamap,
+ sc->verbuf, MEGASAS_MAX_NAME*sizeof(bus_addr_t),
+ mfi_addr_cb, &sc->verbuf_h_busaddr, 0);
+ /* End: LSIP200113393 */
+
/*
* Get information needed for sizing the contiguous memory for the
* frame pool. Size down the sgl parameter since we know that
@@ -347,6 +458,100 @@ mfi_attach(struct mfi_softc *sc)
max_fw_sge = (status & MFI_FWSTATE_MAXSGL_MASK) >> 16;
sc->mfi_max_sge = min(max_fw_sge, ((MFI_MAXPHYS / PAGE_SIZE) + 1));
+ /* ThunderBolt Support get the contiguous memory */
+
+ if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+ mfi_tbolt_init_globals(sc);
+ device_printf(sc->mfi_dev, "MaxCmd = %x MaxSgl = %x state = %x \n",
+ sc->mfi_max_fw_cmds, sc->mfi_max_sge, status);
+ tb_mem_size = mfi_tbolt_get_memory_requirement(sc);
+
+ if (bus_dma_tag_create( sc->mfi_parent_dmat, /* parent */
+ 1, 0, /* algnmnt, boundary */
+ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ tb_mem_size, /* maxsize */
+ 1, /* msegments */
+ tb_mem_size, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->mfi_tb_dmat)) {
+ device_printf(sc->mfi_dev, "Cannot allocate comms DMA tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->mfi_tb_dmat, (void **)&sc->request_message_pool,
+ BUS_DMA_NOWAIT, &sc->mfi_tb_dmamap)) {
+ device_printf(sc->mfi_dev, "Cannot allocate comms memory\n");
+ return (ENOMEM);
+ }
+ bzero(sc->request_message_pool, tb_mem_size);
+ bus_dmamap_load(sc->mfi_tb_dmat, sc->mfi_tb_dmamap,
+ sc->request_message_pool, tb_mem_size, mfi_addr_cb, &sc->mfi_tb_busaddr, 0);
+
+ /* For ThunderBolt memory init */
+ if (bus_dma_tag_create( sc->mfi_parent_dmat, /* parent */
+ 0x100, 0, /* alignmnt, boundary */
+ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MFI_FRAME_SIZE, /* maxsize */
+ 1, /* msegments */
+ MFI_FRAME_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->mfi_tb_init_dmat)) {
+ device_printf(sc->mfi_dev, "Cannot allocate init DMA tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->mfi_tb_init_dmat, (void **)&sc->mfi_tb_init,
+ BUS_DMA_NOWAIT, &sc->mfi_tb_init_dmamap)) {
+ device_printf(sc->mfi_dev, "Cannot allocate init memory\n");
+ return (ENOMEM);
+ }
+ bzero(sc->mfi_tb_init, MFI_FRAME_SIZE);
+ bus_dmamap_load(sc->mfi_tb_init_dmat, sc->mfi_tb_init_dmamap,
+ sc->mfi_tb_init, MFI_FRAME_SIZE, mfi_addr_cb,
+ &sc->mfi_tb_init_busaddr, 0);
+ if (mfi_tbolt_init_desc_pool(sc, sc->request_message_pool,
+ tb_mem_size)) {
+ device_printf(sc->mfi_dev,
+ "Thunderbolt pool preparation error\n");
+ return 0;
+ }
+
+ /*
+ Allocate DMA memory mapping for MPI2 IOC Init descriptor,
+ we are taking it diffrent from what we have allocated for Request
+ and reply descriptors to avoid confusion later
+ */
+ tb_mem_size = sizeof(struct MPI2_IOC_INIT_REQUEST);
+ if (bus_dma_tag_create( sc->mfi_parent_dmat, /* parent */
+ 1, 0, /* algnmnt, boundary */
+ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ tb_mem_size, /* maxsize */
+ 1, /* msegments */
+ tb_mem_size, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->mfi_tb_ioc_init_dmat)) {
+ device_printf(sc->mfi_dev,
+ "Cannot allocate comms DMA tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->mfi_tb_ioc_init_dmat,
+ (void **)&sc->mfi_tb_ioc_init_desc,
+ BUS_DMA_NOWAIT, &sc->mfi_tb_ioc_init_dmamap)) {
+ device_printf(sc->mfi_dev, "Cannot allocate comms memory\n");
+ return (ENOMEM);
+ }
+ bzero(sc->mfi_tb_ioc_init_desc, tb_mem_size);
+ bus_dmamap_load(sc->mfi_tb_ioc_init_dmat, sc->mfi_tb_ioc_init_dmamap,
+ sc->mfi_tb_ioc_init_desc, tb_mem_size, mfi_addr_cb,
+ &sc->mfi_tb_ioc_init_busaddr, 0);
+ }
/*
* Create the dma tag for data buffers. Used both for block I/O
* and for various internal data queries.
@@ -396,8 +601,7 @@ mfi_attach(struct mfi_softc *sc)
}
bzero(sc->mfi_comms, commsz);
bus_dmamap_load(sc->mfi_comms_dmat, sc->mfi_comms_dmamap,
- sc->mfi_comms, commsz, mfi_addr32_cb, &sc->mfi_comms_busaddr, 0);
-
+ sc->mfi_comms, commsz, mfi_addr_cb, &sc->mfi_comms_busaddr, 0);
/*
* Allocate DMA memory for the command frames. Keep them in the
* lower 4GB for efficiency. Calculate the size of the commands at
@@ -414,6 +618,8 @@ mfi_attach(struct mfi_softc *sc)
} else {
sc->mfi_sge_size = sizeof(struct mfi_sg32);
}
+ if (sc->mfi_flags & MFI_FLAGS_SKINNY)
+ sc->mfi_sge_size = sizeof(struct mfi_sg_skinny);
frames = (sc->mfi_sge_size * sc->mfi_max_sge - 1) / MFI_FRAME_SIZE + 2;
sc->mfi_cmd_size = frames * MFI_FRAME_SIZE;
framessz = sc->mfi_cmd_size * sc->mfi_max_fw_cmds;
@@ -438,8 +644,7 @@ mfi_attach(struct mfi_softc *sc)
}
bzero(sc->mfi_frames, framessz);
bus_dmamap_load(sc->mfi_frames_dmat, sc->mfi_frames_dmamap,
- sc->mfi_frames, framessz, mfi_addr32_cb, &sc->mfi_frames_busaddr,0);
-
+ sc->mfi_frames, framessz, mfi_addr_cb, &sc->mfi_frames_busaddr,0);
/*
* Allocate DMA memory for the frame sense data. Keep them in the
* lower 4GB for efficiency
@@ -465,32 +670,47 @@ mfi_attach(struct mfi_softc *sc)
return (ENOMEM);
}
bus_dmamap_load(sc->mfi_sense_dmat, sc->mfi_sense_dmamap,
- sc->mfi_sense, sensesz, mfi_addr32_cb, &sc->mfi_sense_busaddr, 0);
-
+ sc->mfi_sense, sensesz, mfi_addr_cb, &sc->mfi_sense_busaddr, 0);
if ((error = mfi_alloc_commands(sc)) != 0)
return (error);
- if ((error = mfi_comms_init(sc)) != 0)
- return (error);
+ /* Before moving the FW to operational state, check whether
+ * hostmemory is required by the FW or not
+ */
- if ((error = mfi_get_controller_info(sc)) != 0)
- return (error);
+ /* ThunderBolt MFI_IOC2 INIT */
+ if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+ sc->mfi_disable_intr(sc);
+ if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0) {
+ device_printf(sc->mfi_dev,
+ "TB Init has failed with error %d\n",error);
+ return error;
+ }
- mtx_lock(&sc->mfi_io_lock);
- if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
- mtx_unlock(&sc->mfi_io_lock);
- return (error);
- }
- mtx_unlock(&sc->mfi_io_lock);
+ if ((error = mfi_tbolt_alloc_cmd(sc)) != 0)
+ return error;
+ if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq,
+ INTR_MPSAFE|INTR_TYPE_BIO, NULL, mfi_intr_tbolt, sc,
+ &sc->mfi_intr)) {
+ device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
+ return (EINVAL);
+ }
+ sc->mfi_enable_intr(sc);
+ sc->map_id = 0;
+ } else {
+ if ((error = mfi_comms_init(sc)) != 0)
+ return (error);
- /*
- * Set up the interrupt handler.
- */
- if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq, INTR_MPSAFE|INTR_TYPE_BIO,
- NULL, mfi_intr, sc, &sc->mfi_intr)) {
- device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
- return (EINVAL);
+ if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq,
+ INTR_MPSAFE|INTR_TYPE_BIO, NULL, mfi_intr, sc, &sc->mfi_intr)) {
+ device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
+ return (EINVAL);
+ }
+ sc->mfi_enable_intr(sc);
}
+ if ((error = mfi_get_controller_info(sc)) != 0)
+ return (error);
+ sc->disableOnlineCtrlReset = 0;
/* Register a config hook to probe the bus for arrays */
sc->mfi_ich.ich_func = mfi_startup;
@@ -500,6 +720,10 @@ mfi_attach(struct mfi_softc *sc)
"hook\n");
return (EINVAL);
}
+ if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
+ mtx_unlock(&sc->mfi_io_lock);
+ return (error);
+ }
/*
* Register a shutdown handler.
@@ -571,8 +795,11 @@ mfi_alloc_commands(struct mfi_softc *sc)
cm->cm_sc = sc;
cm->cm_index = i;
if (bus_dmamap_create(sc->mfi_buffer_dmat, 0,
- &cm->cm_dmamap) == 0)
+ &cm->cm_dmamap) == 0) {
+ mtx_lock(&sc->mfi_io_lock);
mfi_release_command(cm);
+ mtx_unlock(&sc->mfi_io_lock);
+ }
else
break;
sc->mfi_total_cmds++;
@@ -587,6 +814,8 @@ mfi_release_command(struct mfi_command *
struct mfi_frame_header *hdr;
uint32_t *hdr_data;
+ mtx_assert(&cm->cm_sc->mfi_io_lock, MA_OWNED);
+
/*
* Zero out the important fields of the frame, but make sure the
* context field is preserved. For efficiency, handle the fields
@@ -611,24 +840,31 @@ mfi_release_command(struct mfi_command *
cm->cm_data = NULL;
cm->cm_sg = 0;
cm->cm_total_frame_size = 0;
+ cm->retry_for_fw_reset = 0;
mfi_enqueue_free(cm);
}
static int
-mfi_dcmd_command(struct mfi_softc *sc, struct mfi_command **cmp, uint32_t opcode,
- void **bufp, size_t bufsize)
+mfi_dcmd_command(struct mfi_softc *sc, struct mfi_command **cmp,
+ uint32_t opcode, void **bufp, size_t bufsize)
{
struct mfi_command *cm;
struct mfi_dcmd_frame *dcmd;
void *buf = NULL;
-
+ uint32_t context = 0;
+
mtx_assert(&sc->mfi_io_lock, MA_OWNED);
-
+
cm = mfi_dequeue_free(sc);
if (cm == NULL)
return (EBUSY);
+ /* Zero out the MFI frame */
+ context = cm->cm_frame->header.context;
+ bzero(cm->cm_frame, sizeof(union mfi_frame));
+ cm->cm_frame->header.context = context;
+
if ((bufsize > 0) && (bufp != NULL)) {
if (*bufp == NULL) {
buf = malloc(bufsize, M_MFIBUF, M_NOWAIT|M_ZERO);
@@ -648,6 +884,7 @@ mfi_dcmd_command(struct mfi_softc *sc, s
dcmd->header.timeout = 0;
dcmd->header.flags = 0;
dcmd->header.data_len = bufsize;
+ dcmd->header.scsi_status = 0;
dcmd->opcode = opcode;
cm->cm_sg = &dcmd->sgl;
cm->cm_total_frame_size = MFI_DCMD_FRAME_SIZE;
@@ -669,11 +906,17 @@ mfi_comms_init(struct mfi_softc *sc)
struct mfi_init_frame *init;
struct mfi_init_qinfo *qinfo;
int error;
+ uint32_t context = 0;
mtx_lock(&sc->mfi_io_lock);
if ((cm = mfi_dequeue_free(sc)) == NULL)
return (EBUSY);
+ /* Zero out the MFI frame */
+ context = cm->cm_frame->header.context;
+ bzero(cm->cm_frame, sizeof(union mfi_frame));
+ cm->cm_frame->header.context = context;
+
/*
* Abuse the SG list area of the frame to hold the init_qinfo
* object;
@@ -734,9 +977,11 @@ mfi_get_controller_info(struct mfi_softc
BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
- max_sectors_1 = (1 << ci->stripe_sz_ops.min) * ci->max_strips_per_io;
+ max_sectors_1 = (1 << ci->stripe_sz_ops.max) * ci->max_strips_per_io;
max_sectors_2 = ci->max_request_size;
sc->mfi_max_io = min(max_sectors_1, max_sectors_2);
+ sc->disableOnlineCtrlReset =
+ ci->properties.OnOffProperties.disableOnlineCtrlReset;
out:
if (ci)
@@ -753,6 +998,7 @@ mfi_get_log_state(struct mfi_softc *sc,
struct mfi_command *cm = NULL;
int error;
+ mtx_lock(&sc->mfi_io_lock);
error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_GETINFO,
(void **)log_state, sizeof(**log_state));
if (error)
@@ -771,11 +1017,12 @@ mfi_get_log_state(struct mfi_softc *sc,
out:
if (cm)
mfi_release_command(cm);
+ mtx_unlock(&sc->mfi_io_lock);
return (error);
}
-static int
+int
mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
{
struct mfi_evt_log_state *log_state = NULL;
@@ -789,6 +1036,7 @@ mfi_aen_setup(struct mfi_softc *sc, uint
if (seq_start == 0) {
error = mfi_get_log_state(sc, &log_state);
+ sc->mfi_boot_seq_num = log_state->boot_seq_num;
if (error) {
if (log_state)
free(log_state, M_MFIBUF);
@@ -810,7 +1058,7 @@ mfi_aen_setup(struct mfi_softc *sc, uint
return 0;
}
-static int
+int
mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm)
{
@@ -883,6 +1131,64 @@ mfi_free(struct mfi_softc *sc)
if (sc->mfi_comms_dmat != NULL)
bus_dma_tag_destroy(sc->mfi_comms_dmat);
+ /* ThunderBolt contiguous memory free here */
+ if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+ if (sc->mfi_tb_busaddr != 0)
+ bus_dmamap_unload(sc->mfi_tb_dmat, sc->mfi_tb_dmamap);
+ if (sc->request_message_pool != NULL)
+ bus_dmamem_free(sc->mfi_tb_dmat, sc->request_message_pool,
+ sc->mfi_tb_dmamap);
+ if (sc->mfi_tb_dmat != NULL)
+ bus_dma_tag_destroy(sc->mfi_tb_dmat);
+
+ /* Version buffer memory free */
+ /* Start LSIP200113393 */
+ if (sc->verbuf_h_busaddr != 0)
+ bus_dmamap_unload(sc->verbuf_h_dmat, sc->verbuf_h_dmamap);
+ if (sc->verbuf != NULL)
+ bus_dmamem_free(sc->verbuf_h_dmat, sc->verbuf,
+ sc->verbuf_h_dmamap);
+ if (sc->verbuf_h_dmat != NULL)
+ bus_dma_tag_destroy(sc->verbuf_h_dmat);
+
+ /* End LSIP200113393 */
+ /* ThunderBolt INIT packet memory Free */
+ if (sc->mfi_tb_init_busaddr != 0)
+ bus_dmamap_unload(sc->mfi_tb_init_dmat, sc->mfi_tb_init_dmamap);
+ if (sc->mfi_tb_init != NULL)
+ bus_dmamem_free(sc->mfi_tb_init_dmat, sc->mfi_tb_init,
+ sc->mfi_tb_init_dmamap);
+ if (sc->mfi_tb_init_dmat != NULL)
+ bus_dma_tag_destroy(sc->mfi_tb_init_dmat);
+
+ /* ThunderBolt IOC Init Desc memory free here */
+ if (sc->mfi_tb_ioc_init_busaddr != 0)
+ bus_dmamap_unload(sc->mfi_tb_ioc_init_dmat,
+ sc->mfi_tb_ioc_init_dmamap);
+ if (sc->mfi_tb_ioc_init_desc != NULL)
+ bus_dmamem_free(sc->mfi_tb_ioc_init_dmat,
+ sc->mfi_tb_ioc_init_desc,
+ sc->mfi_tb_ioc_init_dmamap);
+ if (sc->mfi_tb_ioc_init_dmat != NULL)
+ bus_dma_tag_destroy(sc->mfi_tb_ioc_init_dmat);
+ for (int i = 0; i < sc->mfi_max_fw_cmds; i++) {
+ if (sc->mfi_cmd_pool_tbolt != NULL) {
+ if (sc->mfi_cmd_pool_tbolt[i] != NULL) {
+ free(sc->mfi_cmd_pool_tbolt[i],
+ M_MFIBUF);
+ sc->mfi_cmd_pool_tbolt[i] = NULL;
+ }
+ }
+ }
+ if (sc->mfi_cmd_pool_tbolt != NULL) {
+ free(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
+ sc->mfi_cmd_pool_tbolt = NULL;
+ }
+ if (sc->request_desc_pool != NULL) {
+ free(sc->request_desc_pool, M_MFIBUF);
+ sc->request_desc_pool = NULL;
+ }
+ }
if (sc->mfi_buffer_dmat != NULL)
bus_dma_tag_destroy(sc->mfi_buffer_dmat);
if (sc->mfi_parent_dmat != NULL)
@@ -909,6 +1215,8 @@ mfi_startup(void *arg)
sx_xlock(&sc->mfi_config_lock);
mtx_lock(&sc->mfi_io_lock);
mfi_ldprobe(sc);
+ if (sc->mfi_flags & MFI_FLAGS_SKINNY)
+ mfi_syspdprobe(sc);
mtx_unlock(&sc->mfi_io_lock);
sx_xunlock(&sc->mfi_config_lock);
}
@@ -925,12 +1233,7 @@ mfi_intr(void *arg)
if (sc->mfi_check_clear_intr(sc))
return;
- /*
- * Do a dummy read to flush the interrupt ACK that we just performed,
- * ensuring that everything is really, truly consistent.
- */
- (void)sc->mfi_read_fw_status(sc);
-
+restart:
pi = sc->mfi_comms->hw_pi;
ci = sc->mfi_comms->hw_ci;
mtx_lock(&sc->mfi_io_lock);
@@ -955,6 +1258,14 @@ mfi_intr(void *arg)
mfi_startio(sc);
mtx_unlock(&sc->mfi_io_lock);
+ /*
+ * Dummy read to flush the bus; this ensures that the indexes are up
+ * to date. Restart processing if more commands have come it.
+ */
+ (void)sc->mfi_read_fw_status(sc);
+ if (pi != sc->mfi_comms->hw_pi)
+ goto restart;
+
return;
}
@@ -975,6 +1286,9 @@ mfi_shutdown(struct mfi_softc *sc)
if (sc->mfi_aen_cm != NULL)
mfi_abort(sc, sc->mfi_aen_cm);
+ if (sc->map_update_cmd != NULL)
+ mfi_abort(sc, sc->map_update_cmd);
+
dcmd = &cm->cm_frame->dcmd;
dcmd->header.flags = MFI_FRAME_DIR_NONE;
cm->cm_flags = MFI_CMD_POLLED;
@@ -990,6 +1304,81 @@ mfi_shutdown(struct mfi_softc *sc)
}
static void
+mfi_syspdprobe(struct mfi_softc *sc)
+{
+ struct mfi_frame_header *hdr;
+ struct mfi_command *cm = NULL;
+ struct mfi_pd_list *pdlist = NULL;
+ struct mfi_system_pd *syspd, *tmp;
+ int error, i, found;
+
+ sx_assert(&sc->mfi_config_lock, SA_XLOCKED);
+ mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+ /* Add SYSTEM PD's */
+ error = mfi_dcmd_command(sc, &cm, MFI_DCMD_PD_LIST_QUERY,
+ (void **)&pdlist, sizeof(*pdlist));
+ if (error){
+ device_printf(sc->mfi_dev,
+ "Error while forming SYSTEM PD list\n");
+ goto out;
+ }
+
+ cm->cm_flags = MFI_CMD_DATAIN | MFI_CMD_POLLED;
+ cm->cm_frame->dcmd.mbox[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
+ cm->cm_frame->dcmd.mbox[1] = 0;
+ if (mfi_mapcmd(sc, cm) != 0) {
+ device_printf(sc->mfi_dev,
+ "Failed to get syspd device listing\n");
+ goto out;
+ }
+ bus_dmamap_sync(sc->mfi_buffer_dmat,cm->cm_dmamap,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
+ hdr = &cm->cm_frame->header;
+ if (hdr->cmd_status != MFI_STAT_OK) {
+ device_printf(sc->mfi_dev,
+ "MFI_DCMD_PD_LIST_QUERY failed %x\n", hdr->cmd_status);
+ goto out;
+ }
+ /* Get each PD and add it to the system */
+ for (i = 0; i < pdlist->count; i++) {
+ if (pdlist->addr[i].device_id ==
+ pdlist->addr[i].encl_device_id)
+ continue;
+ found = 0;
+ TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh, pd_link) {
+ if (syspd->pd_id == pdlist->addr[i].device_id)
+ found = 1;
+ }
+ if (found == 0)
+ mfi_add_sys_pd(sc, pdlist->addr[i].device_id);
+ }
+ /* Delete SYSPD's whose state has been changed */
+ TAILQ_FOREACH_SAFE(syspd, &sc->mfi_syspd_tqh, pd_link, tmp) {
+ found = 0;
+ for (i = 0; i < pdlist->count; i++) {
+ if (syspd->pd_id == pdlist->addr[i].device_id)
+ found = 1;
+ }
+ if (found == 0) {
+ printf("DELETE\n");
+ mtx_unlock(&sc->mfi_io_lock);
+ mtx_lock(&Giant);
+ device_delete_child(sc->mfi_dev, syspd->pd_dev);
+ mtx_unlock(&Giant);
+ mtx_lock(&sc->mfi_io_lock);
+ }
+ }
+out:
+ if (pdlist)
+ free(pdlist, M_MFIBUF);
+ if (cm)
+ mfi_release_command(cm);
+
+ return;
+}
+
+static void
mfi_ldprobe(struct mfi_softc *sc)
{
struct mfi_frame_header *hdr;
@@ -1083,10 +1472,124 @@ format_class(int8_t class)
static void
mfi_decode_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail)
{
+ struct mfi_system_pd *syspd = NULL;
device_printf(sc->mfi_dev, "%d (%s/0x%04x/%s) - %s\n", detail->seq,
format_timestamp(detail->time), detail->evt_class.members.locale,
- format_class(detail->evt_class.members.evt_class), detail->description);
+ format_class(detail->evt_class.members.evt_class),
+ detail->description);
+
+ /* Don't act on old AEN's or while shutting down */
+ if (detail->seq < sc->mfi_boot_seq_num || sc->mfi_detaching)
+ return;
+
+ switch (detail->arg_type) {
+ case MR_EVT_ARGS_NONE:
+ if (detail->code == MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED) {
+ device_printf(sc->mfi_dev, "HostBus scan raised\n");
+ if (mfi_detect_jbod_change) {
+ /*
+ * Probe for new SYSPD's and Delete
+ * invalid SYSPD's
+ */
+ sx_xlock(&sc->mfi_config_lock);
+ mtx_lock(&sc->mfi_io_lock);
+ mfi_syspdprobe(sc);
+ mtx_unlock(&sc->mfi_io_lock);
+ sx_xunlock(&sc->mfi_config_lock);
+ }
+ }
+ break;
+ case MR_EVT_ARGS_LD_STATE:
+ /* During load time driver reads all the events starting
+ * from the one that has been logged after shutdown. Avoid
+ * these old events.
+ */
+ if (detail->args.ld_state.new_state == MFI_LD_STATE_OFFLINE ) {
+ /* Remove the LD */
+ struct mfi_disk *ld;
+ TAILQ_FOREACH(ld, &sc->mfi_ld_tqh, ld_link) {
+ if (ld->ld_id ==
+ detail->args.ld_state.ld.target_id)
+ break;
+ }
+ /*
+ Fix: for kernel panics when SSCD is removed
+ KASSERT(ld != NULL, ("volume dissappeared"));
+ */
+ if (ld != NULL) {
+ mtx_lock(&Giant);
+ device_delete_child(sc->mfi_dev, ld->ld_dev);
+ mtx_unlock(&Giant);
+ }
+ }
+ break;
+ case MR_EVT_ARGS_PD:
+ if (detail->code == MR_EVT_PD_REMOVED) {
+ if (mfi_detect_jbod_change) {
+ /*
+ * If the removed device is a SYSPD then
+ * delete it
+ */
+ TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh,
+ pd_link) {
+ if (syspd->pd_id ==
+ detail->args.pd.device_id) {
+ mtx_lock(&Giant);
+ device_delete_child(
+ sc->mfi_dev,
+ syspd->pd_dev);
+ mtx_unlock(&Giant);
+ break;
+ }
+ }
+ }
+ }
+ if (detail->code == MR_EVT_PD_INSERTED) {
+ if (mfi_detect_jbod_change) {
+ /* Probe for new SYSPD's */
+ sx_xlock(&sc->mfi_config_lock);
+ mtx_lock(&sc->mfi_io_lock);
+ mfi_syspdprobe(sc);
+ mtx_unlock(&sc->mfi_io_lock);
+ sx_xunlock(&sc->mfi_config_lock);
+ }
+ }
+ break;
+ }
+}
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-9
mailing list