[Midnightbsd-cvs] src [10094] trunk/sys/dev/mps: sync mps
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun May 27 19:35:40 EDT 2018
Revision: 10094
http://svnweb.midnightbsd.org/src/?rev=10094
Author: laffer1
Date: 2018-05-27 19:35:39 -0400 (Sun, 27 May 2018)
Log Message:
-----------
sync mps
Modified Paths:
--------------
trunk/sys/dev/mps/mpi/mpi2.h
trunk/sys/dev/mps/mpi/mpi2_cnfg.h
trunk/sys/dev/mps/mpi/mpi2_hbd.h
trunk/sys/dev/mps/mpi/mpi2_history.txt
trunk/sys/dev/mps/mpi/mpi2_init.h
trunk/sys/dev/mps/mpi/mpi2_ioc.h
trunk/sys/dev/mps/mpi/mpi2_ra.h
trunk/sys/dev/mps/mpi/mpi2_raid.h
trunk/sys/dev/mps/mpi/mpi2_sas.h
trunk/sys/dev/mps/mpi/mpi2_targ.h
trunk/sys/dev/mps/mpi/mpi2_tool.h
trunk/sys/dev/mps/mpi/mpi2_type.h
trunk/sys/dev/mps/mps.c
trunk/sys/dev/mps/mps_config.c
trunk/sys/dev/mps/mps_ioctl.h
trunk/sys/dev/mps/mps_mapping.c
trunk/sys/dev/mps/mps_mapping.h
trunk/sys/dev/mps/mps_pci.c
trunk/sys/dev/mps/mps_sas.c
trunk/sys/dev/mps/mps_sas.h
trunk/sys/dev/mps/mps_sas_lsi.c
trunk/sys/dev/mps/mps_table.c
trunk/sys/dev/mps/mps_table.h
trunk/sys/dev/mps/mps_user.c
trunk/sys/dev/mps/mpsvar.h
Property Changed:
----------------
trunk/sys/dev/mps/mpi/mpi2_history.txt
Modified: trunk/sys/dev/mps/mpi/mpi2.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2006-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2006-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2.h
Modified: trunk/sys/dev/mps/mpi/mpi2_cnfg.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_cnfg.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_cnfg.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2006-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_cnfg.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2006-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_cnfg.h
Modified: trunk/sys/dev/mps/mpi/mpi2_hbd.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_hbd.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_hbd.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2009-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_hbd.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2009-2012 LSI Corporation.
+ * Copyright (c) 2009-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_hbd.h
Modified: trunk/sys/dev/mps/mpi/mpi2_history.txt
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_history.txt 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_history.txt 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2000-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,9 +24,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_history.txt 281564 2015-04-15 21:47:15Z slm $
*/
==============================
@@ -32,7 +33,8 @@
Fusion-MPT MPI 2.0 Header File Change History
==============================
- Copyright (c) 2000-2012 LSI Corporation.
+ Copyright (c) 2000-2015 LSI Corporation.
+ Copyright (c) 2013-2015 Avago Technologies
---------------------------------------
Header Set Release Version: 02.00.18
Property changes on: trunk/sys/dev/mps/mpi/mpi2_history.txt
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/sys/dev/mps/mpi/mpi2_init.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_init.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_init.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2006-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_init.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2006-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_init.h
Modified: trunk/sys/dev/mps/mpi/mpi2_ioc.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_ioc.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_ioc.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2006-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_ioc.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2006-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_ioc.h
Modified: trunk/sys/dev/mps/mpi/mpi2_ra.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_ra.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_ra.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2009-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_ra.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2012 LSI Corporation.
+ * Copyright (c) 2009-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_ra.h
Modified: trunk/sys/dev/mps/mpi/mpi2_raid.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_raid.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_raid.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2007-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_raid.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2007-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_raid.h
Modified: trunk/sys/dev/mps/mpi/mpi2_sas.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_sas.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_sas.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2007-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_sas.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2007-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_sas.h
Modified: trunk/sys/dev/mps/mpi/mpi2_targ.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_targ.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_targ.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2006-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_targ.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2006-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_targ.h
Modified: trunk/sys/dev/mps/mpi/mpi2_tool.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_tool.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_tool.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2007-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_tool.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2007-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_tool.h
Modified: trunk/sys/dev/mps/mpi/mpi2_type.h
===================================================================
--- trunk/sys/dev/mps/mpi/mpi2_type.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpi/mpi2_type.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2006-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpi/mpi2_type.h 281564 2015-04-15 21:47:15Z slm $
*/
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2006-2015 LSI Corporation.
+ * Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_type.h
Modified: trunk/sys/dev/mps/mps.c
===================================================================
--- trunk/sys/dev/mps/mps.c 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps.c 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,6 +1,8 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009 Yahoo! Inc.
- * Copyright (c) 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,15 +26,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mps.c 322661 2017-08-18 15:38:08Z ken $
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/mps/mps.c 322661 2017-08-18 15:38:08Z ken $");
-/* Communications core for LSI MPT2 */
+/* Communications core for Avago Technologies (LSI) MPT2 */
/* TODO Move headers to mpsvar */
#include <sys/types.h>
@@ -51,6 +53,7 @@
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/kthread.h>
+#include <sys/taskqueue.h>
#include <sys/endian.h>
#include <sys/eventhandler.h>
@@ -61,6 +64,7 @@
#include <dev/pci/pcivar.h>
+#include <cam/cam.h>
#include <cam/scsi/scsi_all.h>
#include <dev/mps/mpi/mpi2_type.h>
@@ -78,10 +82,16 @@
static int mps_init_queues(struct mps_softc *sc);
static int mps_message_unit_reset(struct mps_softc *sc, int sleep_flag);
static int mps_transition_operational(struct mps_softc *sc);
+static int mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching);
+static void mps_iocfacts_free(struct mps_softc *sc);
static void mps_startup(void *arg);
static int mps_send_iocinit(struct mps_softc *sc);
+static int mps_alloc_queues(struct mps_softc *sc);
+static int mps_alloc_replies(struct mps_softc *sc);
+static int mps_alloc_requests(struct mps_softc *sc);
static int mps_attach_log(struct mps_softc *sc);
-static __inline void mps_complete_command(struct mps_command *cm);
+static __inline void mps_complete_command(struct mps_softc *sc,
+ struct mps_command *cm);
static void mps_dispatch_event(struct mps_softc *sc, uintptr_t data,
MPI2_EVENT_NOTIFICATION_REPLY *reply);
static void mps_config_complete(struct mps_softc *sc, struct mps_command *cm);
@@ -88,6 +98,7 @@
static void mps_periodic(void *);
static int mps_reregister_events(struct mps_softc *sc);
static void mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm);
+static int mps_get_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts);
static int mps_wait_db_ack(struct mps_softc *sc, int timeout, int sleep_flag);
SYSCTL_NODE(_hw, OID_AUTO, mps, CTLFLAG_RD, 0, "MPS Driver Parameters");
@@ -113,6 +124,9 @@
} u;
}reply_descriptor,address_descriptor;
+/* Rate limit chain-fail messages to 1 per minute */
+static struct timeval mps_chainfail_interval = { 60, 0 };
+
/*
* sleep_flag can be either CAN_SLEEP or NO_SLEEP.
* If this function is called from process context, it can sleep
@@ -128,6 +142,7 @@
{
uint32_t reg;
int i, error, tries = 0;
+ uint8_t first_wait_done = FALSE;
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
@@ -136,8 +151,8 @@
/*Force NO_SLEEP for threads prohibited to sleep
* e.a Thread from interrupt handler are prohibited to sleep.
- */
- if(curthread->td_pflags & TDP_NOSLEEPING)
+ */
+ if (curthread->td_no_sleeping != 0)
sleep_flag = NO_SLEEP;
/* Push the magic sequence */
@@ -148,7 +163,8 @@
mpt2_reset_magic[i]);
/* wait 100 msec */
if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
- msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, "mpsdiag", hz/10);
+ msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
+ "mpsdiag", hz/10);
else if (sleep_flag == CAN_SLEEP)
pause("mpsdiag", hz/10);
else
@@ -169,14 +185,32 @@
/* Wait up to 300 seconds in 50ms intervals */
error = ETIMEDOUT;
- for (i = 0; i < 60000; i++) {
- /* wait 50 msec */
- if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
- msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, "mpsdiag", hz/20);
- else if (sleep_flag == CAN_SLEEP)
- pause("mpsdiag", hz/20);
- else
- DELAY(50 * 1000);
+ for (i = 0; i < 6000; i++) {
+ /*
+ * Wait 50 msec. If this is the first time through, wait 256
+ * msec to satisfy Diag Reset timing requirements.
+ */
+ if (first_wait_done) {
+ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
+ msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
+ "mpsdiag", hz/20);
+ else if (sleep_flag == CAN_SLEEP)
+ pause("mpsdiag", hz/20);
+ else
+ DELAY(50 * 1000);
+ } else {
+ DELAY(256 * 1000);
+ first_wait_done = TRUE;
+ }
+ /*
+ * Check for the RESET_ADAPTER bit to be cleared first, then
+ * wait for the RESET state to be cleared, which takes a little
+ * longer.
+ */
+ reg = mps_regread(sc, MPI2_HOST_DIAGNOSTIC_OFFSET);
+ if (reg & MPI2_DIAG_RESET_ADAPTER) {
+ continue;
+ }
reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
if ((reg & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_RESET) {
error = 0;
@@ -195,7 +229,7 @@
mps_message_unit_reset(struct mps_softc *sc, int sleep_flag)
{
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
mps_regwrite(sc, MPI2_DOORBELL_OFFSET,
MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET <<
@@ -217,14 +251,14 @@
int error, tries = 0;
int sleep_flags;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
/* If we are in attach call, do not sleep */
sleep_flags = (sc->mps_flags & MPS_FLAGS_ATTACH_DONE)
? CAN_SLEEP:NO_SLEEP;
error = 0;
- while (tries++ < 5) {
+ while (tries++ < 1200) {
reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
- mps_dprint(sc, MPS_INFO, "Doorbell= 0x%x\n", reg);
+ mps_dprint(sc, MPS_INIT, "Doorbell= 0x%x\n", reg);
/*
* Ensure the IOC is ready to talk. If it's not, try
@@ -250,7 +284,7 @@
error = 0;
break;
} else if (state == MPI2_IOC_STATE_FAULT) {
- mps_dprint(sc, MPS_INFO, "IOC in fault state 0x%x\n",
+ mps_dprint(sc, MPS_FAULT, "IOC in fault state 0x%x, resetting\n",
state & MPI2_DOORBELL_FAULT_CODE_MASK);
mps_diag_reset(sc, sleep_flags);
} else if (state == MPI2_IOC_STATE_OPERATIONAL) {
@@ -283,11 +317,11 @@
uint32_t reg, state;
int error;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
error = 0;
reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
- mps_dprint(sc, MPS_INFO, "Doorbell= 0x%x\n", reg);
+ mps_dprint(sc, MPS_INIT, "Doorbell= 0x%x\n", reg);
state = reg & MPI2_IOC_STATE_MASK;
if (state != MPI2_IOC_STATE_READY) {
@@ -302,9 +336,341 @@
return (error);
}
+/*
+ * This is called during attach and when re-initializing due to a Diag Reset.
+ * IOC Facts is used to allocate many of the structures needed by the driver.
+ * If called from attach, de-allocation is not required because the driver has
+ * not allocated any structures yet, but if called from a Diag Reset, previously
+ * allocated structures based on IOC Facts will need to be freed and re-
+ * allocated bases on the latest IOC Facts.
+ */
+static int
+mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching)
+{
+ int error;
+ Mpi2IOCFactsReply_t saved_facts;
+ uint8_t saved_mode, reallocating;
+
+ mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+ /* Save old IOC Facts and then only reallocate if Facts have changed */
+ if (!attaching) {
+ bcopy(sc->facts, &saved_facts, sizeof(MPI2_IOC_FACTS_REPLY));
+ }
+
+ /*
+ * Get IOC Facts. In all cases throughout this function, panic if doing
+ * a re-initialization and only return the error if attaching so the OS
+ * can handle it.
+ */
+ if ((error = mps_get_iocfacts(sc, sc->facts)) != 0) {
+ if (attaching) {
+ mps_dprint(sc, MPS_FAULT, "%s failed to get IOC Facts "
+ "with error %d\n", __func__, error);
+ return (error);
+ } else {
+ panic("%s failed to get IOC Facts with error %d\n",
+ __func__, error);
+ }
+ }
+
+ MPS_DPRINT_PAGE(sc, MPS_XINFO, iocfacts, sc->facts);
+
+ snprintf(sc->fw_version, sizeof(sc->fw_version),
+ "%02d.%02d.%02d.%02d",
+ sc->facts->FWVersion.Struct.Major,
+ sc->facts->FWVersion.Struct.Minor,
+ sc->facts->FWVersion.Struct.Unit,
+ sc->facts->FWVersion.Struct.Dev);
+
+ mps_printf(sc, "Firmware: %s, Driver: %s\n", sc->fw_version,
+ MPS_DRIVER_VERSION);
+ mps_printf(sc, "IOCCapabilities: %b\n", sc->facts->IOCCapabilities,
+ "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf"
+ "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR"
+ "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc");
+
+ /*
+ * If the chip doesn't support event replay then a hard reset will be
+ * required to trigger a full discovery. Do the reset here then
+ * retransition to Ready. A hard reset might have already been done,
+ * but it doesn't hurt to do it again. Only do this if attaching, not
+ * for a Diag Reset.
+ */
+ if (attaching) {
+ if ((sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) {
+ mps_diag_reset(sc, NO_SLEEP);
+ if ((error = mps_transition_ready(sc)) != 0) {
+ mps_dprint(sc, MPS_FAULT, "%s failed to "
+ "transition to ready with error %d\n",
+ __func__, error);
+ return (error);
+ }
+ }
+ }
+
+ /*
+ * Set flag if IR Firmware is loaded. If the RAID Capability has
+ * changed from the previous IOC Facts, log a warning, but only if
+ * checking this after a Diag Reset and not during attach.
+ */
+ saved_mode = sc->ir_firmware;
+ if (sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)
+ sc->ir_firmware = 1;
+ if (!attaching) {
+ if (sc->ir_firmware != saved_mode) {
+ mps_dprint(sc, MPS_FAULT, "%s new IR/IT mode in IOC "
+ "Facts does not match previous mode\n", __func__);
+ }
+ }
+
+ /* Only deallocate and reallocate if relevant IOC Facts have changed */
+ reallocating = FALSE;
+ sc->mps_flags &= ~MPS_FLAGS_REALLOCATED;
+
+ if ((!attaching) &&
+ ((saved_facts.MsgVersion != sc->facts->MsgVersion) ||
+ (saved_facts.HeaderVersion != sc->facts->HeaderVersion) ||
+ (saved_facts.MaxChainDepth != sc->facts->MaxChainDepth) ||
+ (saved_facts.RequestCredit != sc->facts->RequestCredit) ||
+ (saved_facts.ProductID != sc->facts->ProductID) ||
+ (saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) ||
+ (saved_facts.IOCRequestFrameSize !=
+ sc->facts->IOCRequestFrameSize) ||
+ (saved_facts.MaxTargets != sc->facts->MaxTargets) ||
+ (saved_facts.MaxSasExpanders != sc->facts->MaxSasExpanders) ||
+ (saved_facts.MaxEnclosures != sc->facts->MaxEnclosures) ||
+ (saved_facts.HighPriorityCredit != sc->facts->HighPriorityCredit) ||
+ (saved_facts.MaxReplyDescriptorPostQueueDepth !=
+ sc->facts->MaxReplyDescriptorPostQueueDepth) ||
+ (saved_facts.ReplyFrameSize != sc->facts->ReplyFrameSize) ||
+ (saved_facts.MaxVolumes != sc->facts->MaxVolumes) ||
+ (saved_facts.MaxPersistentEntries !=
+ sc->facts->MaxPersistentEntries))) {
+ reallocating = TRUE;
+
+ /* Record that we reallocated everything */
+ sc->mps_flags |= MPS_FLAGS_REALLOCATED;
+ }
+
+ /*
+ * Some things should be done if attaching or re-allocating after a Diag
+ * Reset, but are not needed after a Diag Reset if the FW has not
+ * changed.
+ */
+ if (attaching || reallocating) {
+ /*
+ * Check if controller supports FW diag buffers and set flag to
+ * enable each type.
+ */
+ if (sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
+ sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].
+ enabled = TRUE;
+ if (sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
+ sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].
+ enabled = TRUE;
+ if (sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
+ sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].
+ enabled = TRUE;
+
+ /*
+ * Set flag if EEDP is supported and if TLR is supported.
+ */
+ if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP)
+ sc->eedp_enabled = TRUE;
+ if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)
+ sc->control_TLR = TRUE;
+
+ /*
+ * Size the queues. Since the reply queues always need one free
+ * entry, we'll just deduct one reply message here.
+ */
+ sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit);
+ sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES,
+ sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
+
+ /*
+ * Initialize all Tail Queues
+ */
+ TAILQ_INIT(&sc->req_list);
+ TAILQ_INIT(&sc->high_priority_req_list);
+ TAILQ_INIT(&sc->chain_list);
+ TAILQ_INIT(&sc->tm_list);
+ }
+
+ /*
+ * If doing a Diag Reset and the FW is significantly different
+ * (reallocating will be set above in IOC Facts comparison), then all
+ * buffers based on the IOC Facts will need to be freed before they are
+ * reallocated.
+ */
+ if (reallocating) {
+ mps_iocfacts_free(sc);
+ mpssas_realloc_targets(sc, saved_facts.MaxTargets +
+ saved_facts.MaxVolumes);
+ }
+
+ /*
+ * Any deallocation has been completed. Now start reallocating
+ * if needed. Will only need to reallocate if attaching or if the new
+ * IOC Facts are different from the previous IOC Facts after a Diag
+ * Reset. Targets have already been allocated above if needed.
+ */
+ if (attaching || reallocating) {
+ if (((error = mps_alloc_queues(sc)) != 0) ||
+ ((error = mps_alloc_replies(sc)) != 0) ||
+ ((error = mps_alloc_requests(sc)) != 0)) {
+ if (attaching ) {
+ mps_dprint(sc, MPS_FAULT, "%s failed to alloc "
+ "queues with error %d\n", __func__, error);
+ mps_free(sc);
+ return (error);
+ } else {
+ panic("%s failed to alloc queues with error "
+ "%d\n", __func__, error);
+ }
+ }
+ }
+
+ /* Always initialize the queues */
+ bzero(sc->free_queue, sc->fqdepth * 4);
+ mps_init_queues(sc);
+
+ /*
+ * Always get the chip out of the reset state, but only panic if not
+ * attaching. If attaching and there is an error, that is handled by
+ * the OS.
+ */
+ error = mps_transition_operational(sc);
+ if (error != 0) {
+ if (attaching) {
+ mps_printf(sc, "%s failed to transition to operational "
+ "with error %d\n", __func__, error);
+ mps_free(sc);
+ return (error);
+ } else {
+ panic("%s failed to transition to operational with "
+ "error %d\n", __func__, error);
+ }
+ }
+
+ /*
+ * Finish the queue initialization.
+ * These are set here instead of in mps_init_queues() because the
+ * IOC resets these values during the state transition in
+ * mps_transition_operational(). The free index is set to 1
+ * because the corresponding index in the IOC is set to 0, and the
+ * IOC treats the queues as full if both are set to the same value.
+ * Hence the reason that the queue can't hold all of the possible
+ * replies.
+ */
+ sc->replypostindex = 0;
+ mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
+ mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, 0);
+
+ /*
+ * Attach the subsystems so they can prepare their event masks.
+ */
+ /* XXX Should be dynamic so that IM/IR and user modules can attach */
+ if (attaching) {
+ if (((error = mps_attach_log(sc)) != 0) ||
+ ((error = mps_attach_sas(sc)) != 0) ||
+ ((error = mps_attach_user(sc)) != 0)) {
+ mps_printf(sc, "%s failed to attach all subsystems: "
+ "error %d\n", __func__, error);
+ mps_free(sc);
+ return (error);
+ }
+
+ if ((error = mps_pci_setup_interrupts(sc)) != 0) {
+ mps_printf(sc, "%s failed to setup interrupts\n",
+ __func__);
+ mps_free(sc);
+ return (error);
+ }
+ }
+
+ /*
+ * Set flag if this is a WD controller. This shouldn't ever change, but
+ * reset it after a Diag Reset, just in case.
+ */
+ sc->WD_available = FALSE;
+ if (pci_get_device(sc->mps_dev) == MPI2_MFGPAGE_DEVID_SSS6200)
+ sc->WD_available = TRUE;
+
+ return (error);
+}
+
+/*
+ * This is called if memory is being free (during detach for example) and when
+ * buffers need to be reallocated due to a Diag Reset.
+ */
+static void
+mps_iocfacts_free(struct mps_softc *sc)
+{
+ struct mps_command *cm;
+ int i;
+
+ mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+ if (sc->free_busaddr != 0)
+ bus_dmamap_unload(sc->queues_dmat, sc->queues_map);
+ if (sc->free_queue != NULL)
+ bus_dmamem_free(sc->queues_dmat, sc->free_queue,
+ sc->queues_map);
+ if (sc->queues_dmat != NULL)
+ bus_dma_tag_destroy(sc->queues_dmat);
+
+ if (sc->chain_busaddr != 0)
+ bus_dmamap_unload(sc->chain_dmat, sc->chain_map);
+ if (sc->chain_frames != NULL)
+ bus_dmamem_free(sc->chain_dmat, sc->chain_frames,
+ sc->chain_map);
+ if (sc->chain_dmat != NULL)
+ bus_dma_tag_destroy(sc->chain_dmat);
+
+ if (sc->sense_busaddr != 0)
+ bus_dmamap_unload(sc->sense_dmat, sc->sense_map);
+ if (sc->sense_frames != NULL)
+ bus_dmamem_free(sc->sense_dmat, sc->sense_frames,
+ sc->sense_map);
+ if (sc->sense_dmat != NULL)
+ bus_dma_tag_destroy(sc->sense_dmat);
+
+ if (sc->reply_busaddr != 0)
+ bus_dmamap_unload(sc->reply_dmat, sc->reply_map);
+ if (sc->reply_frames != NULL)
+ bus_dmamem_free(sc->reply_dmat, sc->reply_frames,
+ sc->reply_map);
+ if (sc->reply_dmat != NULL)
+ bus_dma_tag_destroy(sc->reply_dmat);
+
+ if (sc->req_busaddr != 0)
+ bus_dmamap_unload(sc->req_dmat, sc->req_map);
+ if (sc->req_frames != NULL)
+ bus_dmamem_free(sc->req_dmat, sc->req_frames, sc->req_map);
+ if (sc->req_dmat != NULL)
+ bus_dma_tag_destroy(sc->req_dmat);
+
+ if (sc->chains != NULL)
+ free(sc->chains, M_MPT2);
+ if (sc->commands != NULL) {
+ for (i = 1; i < sc->num_reqs; i++) {
+ cm = &sc->commands[i];
+ bus_dmamap_destroy(sc->buffer_dmat, cm->cm_dmamap);
+ }
+ free(sc->commands, M_MPT2);
+ }
+ if (sc->buffer_dmat != NULL)
+ bus_dma_tag_destroy(sc->buffer_dmat);
+}
+
/*
- * XXX Some of this should probably move to mps.c
- *
* The terms diag reset and hard reset are used interchangeably in the MPI
* docs to mean resetting the controller chip. In this code diag reset
* cleans everything up, and the hard reset function just sends the reset
@@ -316,27 +682,35 @@
mps_reinit(struct mps_softc *sc)
{
int error;
- uint32_t db;
+ struct mpssas_softc *sassc;
- mps_printf(sc, "%s sc %p\n", __func__, sc);
+ sassc = sc->sassc;
+ MPS_FUNCTRACE(sc);
+
mtx_assert(&sc->mps_mtx, MA_OWNED);
if (sc->mps_flags & MPS_FLAGS_DIAGRESET) {
- mps_printf(sc, "%s reset already in progress\n", __func__);
+ mps_dprint(sc, MPS_INIT, "%s reset already in progress\n",
+ __func__);
return 0;
}
+ mps_dprint(sc, MPS_INFO, "Reinitializing controller,\n");
/* make sure the completion callbacks can recognize they're getting
* a NULL cm_reply due to a reset.
*/
sc->mps_flags |= MPS_FLAGS_DIAGRESET;
- mps_printf(sc, "%s mask interrupts\n", __func__);
+ /*
+ * Mask interrupts here.
+ */
+ mps_dprint(sc, MPS_INIT, "%s mask interrupts\n", __func__);
mps_mask_intr(sc);
error = mps_diag_reset(sc, CAN_SLEEP);
if (error != 0) {
+ /* XXXSL No need to panic here */
panic("%s hard reset failed with error %d\n",
__func__, error);
}
@@ -347,48 +721,51 @@
/* Give the I/O subsystem special priority to get itself prepared */
mpssas_handle_reinit(sc);
- /* reinitialize queues after the reset */
- bzero(sc->free_queue, sc->fqdepth * 4);
- mps_init_queues(sc);
-
- /* get the chip out of the reset state */
- error = mps_transition_operational(sc);
- if (error != 0)
- panic("%s transition operational failed with error %d\n",
+ /*
+ * Get IOC Facts and allocate all structures based on this information.
+ * The attach function will also call mps_iocfacts_allocate at startup.
+ * If relevant values have changed in IOC Facts, this function will free
+ * all of the memory based on IOC Facts and reallocate that memory.
+ */
+ if ((error = mps_iocfacts_allocate(sc, FALSE)) != 0) {
+ panic("%s IOC Facts based allocation failed with error %d\n",
__func__, error);
+ }
- /* Reinitialize the reply queue. This is delicate because this
- * function is typically invoked by task mgmt completion callbacks,
- * which are called by the interrupt thread. We need to make sure
- * the interrupt handler loop will exit when we return to it, and
- * that it will recognize the indexes we've changed.
+ /*
+ * Mapping structures will be re-allocated after getting IOC Page8, so
+ * free these structures here.
*/
- sc->replypostindex = 0;
- mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
- mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, sc->replypostindex);
+ mps_mapping_exit(sc);
- db = mps_regread(sc, MPI2_DOORBELL_OFFSET);
- mps_printf(sc, "%s doorbell 0x%08x\n", __func__, db);
-
- mps_printf(sc, "%s unmask interrupts post %u free %u\n", __func__,
- sc->replypostindex, sc->replyfreeindex);
-
+ /*
+ * The static page function currently read is IOC Page8. Others can be
+ * added in future. It's possible that the values in IOC Page8 have
+ * changed after a Diag Reset due to user modification, so always read
+ * these. Interrupts are masked, so unmask them before getting config
+ * pages.
+ */
mps_unmask_intr(sc);
+ sc->mps_flags &= ~MPS_FLAGS_DIAGRESET;
+ mps_base_static_config_pages(sc);
- mps_printf(sc, "%s restarting post %u free %u\n", __func__,
- sc->replypostindex, sc->replyfreeindex);
+ /*
+ * Some mapping info is based in IOC Page8 data, so re-initialize the
+ * mapping tables.
+ */
+ mps_mapping_initialize(sc);
- /* restart will reload the event masks clobbered by the reset, and
+ /*
+ * Restart will reload the event masks clobbered by the reset, and
* then enable the port.
*/
mps_reregister_events(sc);
/* the end of discovery will release the simq, so we're done. */
- mps_printf(sc, "%s finished sc %p post %u free %u\n",
- __func__, sc,
- sc->replypostindex, sc->replyfreeindex);
+ mps_dprint(sc, MPS_INFO, "%s finished sc %p post %u free %u\n",
+ __func__, sc, sc->replypostindex, sc->replyfreeindex);
- sc->mps_flags &= ~MPS_FLAGS_DIAGRESET;
+ mpssas_release_simq_reinit(sassc);
return 0;
}
@@ -411,7 +788,7 @@
do {
int_status = mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET);
if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
- mps_dprint(sc, MPS_INFO,
+ mps_dprint(sc, MPS_INIT,
"%s: successfull count(%d), timeout(%d)\n",
__func__, count, timeout);
return 0;
@@ -469,8 +846,8 @@
uint16_t *data16;
int i, count, ioc_sz, residual;
int sleep_flags = CAN_SLEEP;
-
- if(curthread->td_pflags & TDP_NOSLEEPING)
+
+ if (curthread->td_no_sleeping != 0)
sleep_flags = NO_SLEEP;
/* Step 1 */
@@ -546,7 +923,7 @@
count = MIN((reply_sz / 4), ioc_sz) * 2;
if (count < ioc_sz * 2) {
residual = ioc_sz * 2 - count;
- mps_dprint(sc, MPS_FAULT, "Driver error, throwing away %d "
+ mps_dprint(sc, MPS_ERROR, "Driver error, throwing away %d "
"residual message words\n", residual);
}
@@ -592,7 +969,8 @@
mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm)
{
reply_descriptor rd;
- mps_dprint(sc, MPS_TRACE, "%s SMID %u cm %p ccb %p\n", __func__,
+ MPS_FUNCTRACE(sc);
+ mps_dprint(sc, MPS_TRACE, "SMID %u cm %p ccb %p\n",
cm->cm_desc.Default.SMID, cm, cm->cm_ccb);
if (sc->mps_flags & MPS_FLAGS_ATTACH_DONE && !(sc->mps_flags & MPS_FLAGS_SHUTDOWN))
@@ -620,7 +998,7 @@
MPI2_IOC_FACTS_REQUEST request;
int error, req_sz, reply_sz;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
req_sz = sizeof(MPI2_IOC_FACTS_REQUEST);
reply_sz = sizeof(MPI2_IOC_FACTS_REPLY);
@@ -634,50 +1012,15 @@
}
static int
-mps_get_portfacts(struct mps_softc *sc, MPI2_PORT_FACTS_REPLY *facts, int port)
-{
- MPI2_PORT_FACTS_REQUEST *request;
- MPI2_PORT_FACTS_REPLY *reply;
- struct mps_command *cm;
- int error;
-
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
-
- if ((cm = mps_alloc_command(sc)) == NULL)
- return (EBUSY);
- request = (MPI2_PORT_FACTS_REQUEST *)cm->cm_req;
- request->Function = MPI2_FUNCTION_PORT_FACTS;
- request->PortNumber = port;
- cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
- cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_PORT_FACTS_REPLY *)cm->cm_reply;
- if (reply == NULL) {
- mps_printf(sc, "%s NULL reply\n", __func__);
- goto done;
- }
- if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) {
- mps_printf(sc,
- "%s error %d iocstatus 0x%x iocloginfo 0x%x type 0x%x\n",
- __func__, error, reply->IOCStatus, reply->IOCLogInfo,
- reply->PortType);
- error = ENXIO;
- }
- bcopy(reply, facts, sizeof(MPI2_PORT_FACTS_REPLY));
-done:
- mps_free_command(sc, cm);
-
- return (error);
-}
-
-static int
mps_send_iocinit(struct mps_softc *sc)
{
MPI2_IOC_INIT_REQUEST init;
MPI2_DEFAULT_REPLY reply;
int req_sz, reply_sz, error;
+ struct timeval now;
+ uint64_t time_in_msec;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
req_sz = sizeof(MPI2_IOC_INIT_REQUEST);
reply_sz = sizeof(MPI2_IOC_INIT_REPLY);
@@ -704,14 +1047,16 @@
init.ReplyDescriptorPostQueueAddress.Low = htole32((uint32_t)sc->post_busaddr);
init.ReplyFreeQueueAddress.High = 0;
init.ReplyFreeQueueAddress.Low = htole32((uint32_t)sc->free_busaddr);
- init.TimeStamp.High = 0;
- init.TimeStamp.Low = htole32((uint32_t)time_uptime);
+ getmicrotime(&now);
+ time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000);
+ init.TimeStamp.High = htole32((time_in_msec >> 32) & 0xFFFFFFFF);
+ init.TimeStamp.Low = htole32(time_in_msec & 0xFFFFFFFF);
error = mps_request_sync(sc, &init, &reply, req_sz, reply_sz, 5);
if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
error = ENXIO;
- mps_dprint(sc, MPS_INFO, "IOCInit status= 0x%x\n", reply.IOCStatus);
+ mps_dprint(sc, MPS_INIT, "IOCInit status= 0x%x\n", reply.IOCStatus);
return (error);
}
@@ -924,7 +1269,7 @@
NULL, NULL, /* filter, filterarg */
BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
nsegs, /* nsegments */
- BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
+ BUS_SPACE_MAXSIZE_24BIT,/* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
busdma_lock_mutex, /* lockfunc */
&sc->mps_mtx, /* lockarg */
@@ -1002,16 +1347,20 @@
* Next are the global settings, if they exist. Highest are the per-unit
* settings, if they exist.
*/
-static void
+void
mps_get_tunables(struct mps_softc *sc)
{
char tmpstr[80];
/* XXX default to some debugging for now */
- sc->mps_debug = MPS_FAULT;
+ sc->mps_debug = MPS_INFO|MPS_FAULT;
sc->disable_msix = 0;
sc->disable_msi = 0;
sc->max_chains = MPS_CHAIN_FRAMES;
+ sc->max_io_pages = MPS_MAXIO_PAGES;
+ sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD;
+ sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
+ sc->use_phynum = 1;
/*
* Grab the global variables.
@@ -1020,6 +1369,10 @@
TUNABLE_INT_FETCH("hw.mps.disable_msix", &sc->disable_msix);
TUNABLE_INT_FETCH("hw.mps.disable_msi", &sc->disable_msi);
TUNABLE_INT_FETCH("hw.mps.max_chains", &sc->max_chains);
+ TUNABLE_INT_FETCH("hw.mps.max_io_pages", &sc->max_io_pages);
+ TUNABLE_INT_FETCH("hw.mps.enable_ssu", &sc->enable_ssu);
+ TUNABLE_INT_FETCH("hw.mps.spinup_wait_time", &sc->spinup_wait_time);
+ TUNABLE_INT_FETCH("hw.mps.use_phy_num", &sc->use_phynum);
/* Grab the unit-instance variables */
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level",
@@ -1037,6 +1390,27 @@
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_chains",
device_get_unit(sc->mps_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->max_chains);
+
+ snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_io_pages",
+ device_get_unit(sc->mps_dev));
+ TUNABLE_INT_FETCH(tmpstr, &sc->max_io_pages);
+
+ bzero(sc->exclude_ids, sizeof(sc->exclude_ids));
+ snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.exclude_ids",
+ device_get_unit(sc->mps_dev));
+ TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids));
+
+ snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.enable_ssu",
+ device_get_unit(sc->mps_dev));
+ TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu);
+
+ snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.spinup_wait_time",
+ device_get_unit(sc->mps_dev));
+ TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time);
+
+ snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.use_phy_num",
+ device_get_unit(sc->mps_dev));
+ TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum);
}
static void
@@ -1082,7 +1456,7 @@
"Disable the use of MSI interrupts");
SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "firmware_version", CTLFLAG_RW, &sc->fw_version,
+ OID_AUTO, "firmware_version", CTLFLAG_RW, sc->fw_version,
strlen(sc->fw_version), "firmware version");
SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
@@ -1109,25 +1483,49 @@
OID_AUTO, "max_chains", CTLFLAG_RD,
&sc->max_chains, 0,"maximum chain frames that will be allocated");
-#if __FreeBSD_version >= 900030
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "max_io_pages", CTLFLAG_RD,
+ &sc->max_io_pages, 0,"maximum pages to allow per I/O (if <1 use "
+ "IOCFacts)");
+
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "enable_ssu", CTLFLAG_RW, &sc->enable_ssu, 0,
+ "enable SSU to SATA SSD/HDD at shutdown");
+
SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "chain_alloc_fail", CTLFLAG_RD,
&sc->chain_alloc_fail, "chain allocation failures");
-#endif //FreeBSD_version >= 900030
+
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "spinup_wait_time", CTLFLAG_RD,
+ &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for "
+ "spinup after SATA ID error");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "mapping_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ mps_mapping_dump, "A", "Mapping Table Dump");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ mps_mapping_encl_dump, "A", "Enclosure Table Dump");
+
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0,
+ "Use the phy number for enumeration");
}
int
mps_attach(struct mps_softc *sc)
{
- int i, error;
+ int error;
- mps_get_tunables(sc);
+ MPS_FUNCTRACE(sc);
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
-
mtx_init(&sc->mps_mtx, "MPT2SAS lock", NULL, MTX_DEF);
callout_init_mtx(&sc->periodic, &sc->mps_mtx, 0);
+ callout_init_mtx(&sc->device_check_callout, &sc->mps_mtx, 0);
TAILQ_INIT(&sc->event_list);
+ timevalclear(&sc->lastfail);
if ((error = mps_transition_ready(sc)) != 0) {
mps_printf(sc, "%s failed to transition ready\n", __func__);
@@ -1141,151 +1539,20 @@
__func__, __LINE__);
return (ENOMEM);
}
- if ((error = mps_get_iocfacts(sc, sc->facts)) != 0)
- return (error);
- mps_print_iocfacts(sc, sc->facts);
-
- snprintf(sc->fw_version, sizeof(sc->fw_version),
- "%02d.%02d.%02d.%02d",
- sc->facts->FWVersion.Struct.Major,
- sc->facts->FWVersion.Struct.Minor,
- sc->facts->FWVersion.Struct.Unit,
- sc->facts->FWVersion.Struct.Dev);
-
- mps_printf(sc, "Firmware: %s, Driver: %s\n", sc->fw_version,
- MPS_DRIVER_VERSION);
- mps_printf(sc, "IOCCapabilities: %b\n", sc->facts->IOCCapabilities,
- "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf"
- "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR"
- "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc");
-
/*
- * If the chip doesn't support event replay then a hard reset will be
- * required to trigger a full discovery. Do the reset here then
- * retransition to Ready. A hard reset might have already been done,
- * but it doesn't hurt to do it again.
+ * Get IOC Facts and allocate all structures based on this information.
+ * A Diag Reset will also call mps_iocfacts_allocate and re-read the IOC
+ * Facts. If relevant values have changed in IOC Facts, this function
+ * will free all of the memory based on IOC Facts and reallocate that
+ * memory. If this fails, any allocated memory should already be freed.
*/
- if ((sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) {
- mps_diag_reset(sc, NO_SLEEP);
- if ((error = mps_transition_ready(sc)) != 0)
- return (error);
- }
-
- /*
- * Set flag if IR Firmware is loaded.
- */
- if (sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)
- sc->ir_firmware = 1;
-
- /*
- * Check if controller supports FW diag buffers and set flag to enable
- * each type.
- */
- if (sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
- sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled =
- TRUE;
- if (sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
- sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].enabled =
- TRUE;
- if (sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
- sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].enabled =
- TRUE;
-
- /*
- * Set flag if EEDP is supported and if TLR is supported.
- */
- if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP)
- sc->eedp_enabled = TRUE;
- if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)
- sc->control_TLR = TRUE;
-
- /*
- * Size the queues. Since the reply queues always need one free entry,
- * we'll just deduct one reply message here.
- */
- sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit);
- sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES,
- sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
- TAILQ_INIT(&sc->req_list);
- TAILQ_INIT(&sc->high_priority_req_list);
- TAILQ_INIT(&sc->chain_list);
- TAILQ_INIT(&sc->tm_list);
-
- if (((error = mps_alloc_queues(sc)) != 0) ||
- ((error = mps_alloc_replies(sc)) != 0) ||
- ((error = mps_alloc_requests(sc)) != 0)) {
- mps_printf(sc, "%s failed to alloc\n", __func__);
- mps_free(sc);
+ if ((error = mps_iocfacts_allocate(sc, TRUE)) != 0) {
+ mps_dprint(sc, MPS_FAULT, "%s IOC Facts based allocation "
+ "failed with error %d\n", __func__, error);
return (error);
}
- if (((error = mps_init_queues(sc)) != 0) ||
- ((error = mps_transition_operational(sc)) != 0)) {
- mps_printf(sc, "%s failed to transition operational\n", __func__);
- mps_free(sc);
- return (error);
- }
-
- /*
- * Finish the queue initialization.
- * These are set here instead of in mps_init_queues() because the
- * IOC resets these values during the state transition in
- * mps_transition_operational(). The free index is set to 1
- * because the corresponding index in the IOC is set to 0, and the
- * IOC treats the queues as full if both are set to the same value.
- * Hence the reason that the queue can't hold all of the possible
- * replies.
- */
- sc->replypostindex = 0;
- mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
- mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, 0);
-
- sc->pfacts = malloc(sizeof(MPI2_PORT_FACTS_REPLY) *
- sc->facts->NumberOfPorts, M_MPT2, M_ZERO|M_WAITOK);
- if(!sc->pfacts) {
- device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
- __func__, __LINE__);
- return (ENOMEM);
- }
- for (i = 0; i < sc->facts->NumberOfPorts; i++) {
- if ((error = mps_get_portfacts(sc, &sc->pfacts[i], i)) != 0) {
- mps_printf(sc, "%s failed to get portfacts for port %d\n",
- __func__, i);
- mps_free(sc);
- return (error);
- }
- mps_print_portfacts(sc, &sc->pfacts[i]);
- }
-
- /* Attach the subsystems so they can prepare their event masks. */
- /* XXX Should be dynamic so that IM/IR and user modules can attach */
- if (((error = mps_attach_log(sc)) != 0) ||
- ((error = mps_attach_sas(sc)) != 0) ||
- ((error = mps_attach_user(sc)) != 0)) {
- mps_printf(sc, "%s failed to attach all subsystems: error %d\n",
- __func__, error);
- mps_free(sc);
- return (error);
- }
-
- if ((error = mps_pci_setup_interrupts(sc)) != 0) {
- mps_printf(sc, "%s failed to setup interrupts\n", __func__);
- mps_free(sc);
- return (error);
- }
-
- /*
- * The static page function currently read is ioc page8. Others can be
- * added in future.
- */
- mps_base_static_config_pages(sc);
-
/* Start the periodic watchdog check on the IOC Doorbell */
mps_periodic(sc);
@@ -1297,7 +1564,7 @@
sc->mps_ich.ich_func = mps_startup;
sc->mps_ich.ich_arg = sc;
if (config_intrhook_establish(&sc->mps_ich) != 0) {
- mps_dprint(sc, MPS_FAULT, "Cannot establish MPS config hook\n");
+ mps_dprint(sc, MPS_ERROR, "Cannot establish MPS config hook\n");
error = EINVAL;
}
@@ -1308,7 +1575,7 @@
mpssas_ir_shutdown, sc, SHUTDOWN_PRI_DEFAULT);
if (sc->shutdown_eh == NULL)
- mps_dprint(sc, MPS_FAULT, "shutdown event registration "
+ mps_dprint(sc, MPS_ERROR, "shutdown event registration "
"failed\n");
mps_setup_sysctl(sc);
@@ -1328,7 +1595,9 @@
mps_lock(sc);
mps_unmask_intr(sc);
+
/* initialize device mapping tables */
+ mps_base_static_config_pages(sc);
mps_mapping_initialize(sc);
mpssas_startup(sc);
mps_unlock(sc);
@@ -1347,8 +1616,7 @@
db = mps_regread(sc, MPI2_DOORBELL_OFFSET);
if ((db & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
- device_printf(sc->mps_dev, "IOC Fault 0x%08x, Resetting\n", db);
-
+ mps_dprint(sc, MPS_FAULT, "IOC Fault 0x%08x, Resetting\n", db);
mps_reinit(sc);
}
@@ -1361,16 +1629,17 @@
{
MPI2_EVENT_DATA_LOG_ENTRY_ADDED *entry;
- mps_print_event(sc, event);
+ MPS_DPRINT_EVENT(sc, generic, event);
switch (event->Event) {
case MPI2_EVENT_LOG_DATA:
- device_printf(sc->mps_dev, "MPI2_EVENT_LOG_DATA:\n");
- hexdump(event->EventData, event->EventDataLength, NULL, 0);
+ mps_dprint(sc, MPS_EVENT, "MPI2_EVENT_LOG_DATA:\n");
+ if (sc->mps_debug & MPS_EVENT)
+ hexdump(event->EventData, event->EventDataLength, NULL, 0);
break;
case MPI2_EVENT_LOG_ENTRY_ADDED:
entry = (MPI2_EVENT_DATA_LOG_ENTRY_ADDED *)event->EventData;
- mps_dprint(sc, MPS_INFO, "MPI2_EVENT_LOG_ENTRY_ADDED event "
+ mps_dprint(sc, MPS_EVENT, "MPI2_EVENT_LOG_ENTRY_ADDED event "
"0x%x Sequence %d:\n", entry->LogEntryQualifier,
entry->LogSequence);
break;
@@ -1411,8 +1680,7 @@
int
mps_free(struct mps_softc *sc)
{
- struct mps_command *cm;
- int i, error;
+ int error;
/* Turn off the watchdog */
mps_lock(sc);
@@ -1420,6 +1688,7 @@
mps_unlock(sc);
/* Lock must not be held for this */
callout_drain(&sc->periodic);
+ callout_drain(&sc->device_check_callout);
if (((error = mps_detach_log(sc)) != 0) ||
((error = mps_detach_sas(sc)) != 0))
@@ -1438,62 +1707,15 @@
if (sc->facts != NULL)
free(sc->facts, M_MPT2);
- if (sc->pfacts != NULL)
- free(sc->pfacts, M_MPT2);
+ /*
+ * Free all buffers that are based on IOC Facts. A Diag Reset may need
+ * to free these buffers too.
+ */
+ mps_iocfacts_free(sc);
- if (sc->post_busaddr != 0)
- bus_dmamap_unload(sc->queues_dmat, sc->queues_map);
- if (sc->post_queue != NULL)
- bus_dmamem_free(sc->queues_dmat, sc->post_queue,
- sc->queues_map);
- if (sc->queues_dmat != NULL)
- bus_dma_tag_destroy(sc->queues_dmat);
-
- if (sc->chain_busaddr != 0)
- bus_dmamap_unload(sc->chain_dmat, sc->chain_map);
- if (sc->chain_frames != NULL)
- bus_dmamem_free(sc->chain_dmat, sc->chain_frames,sc->chain_map);
- if (sc->chain_dmat != NULL)
- bus_dma_tag_destroy(sc->chain_dmat);
-
- if (sc->sense_busaddr != 0)
- bus_dmamap_unload(sc->sense_dmat, sc->sense_map);
- if (sc->sense_frames != NULL)
- bus_dmamem_free(sc->sense_dmat, sc->sense_frames,sc->sense_map);
- if (sc->sense_dmat != NULL)
- bus_dma_tag_destroy(sc->sense_dmat);
-
- if (sc->reply_busaddr != 0)
- bus_dmamap_unload(sc->reply_dmat, sc->reply_map);
- if (sc->reply_frames != NULL)
- bus_dmamem_free(sc->reply_dmat, sc->reply_frames,sc->reply_map);
- if (sc->reply_dmat != NULL)
- bus_dma_tag_destroy(sc->reply_dmat);
-
- if (sc->req_busaddr != 0)
- bus_dmamap_unload(sc->req_dmat, sc->req_map);
- if (sc->req_frames != NULL)
- bus_dmamem_free(sc->req_dmat, sc->req_frames, sc->req_map);
- if (sc->req_dmat != NULL)
- bus_dma_tag_destroy(sc->req_dmat);
-
- if (sc->chains != NULL)
- free(sc->chains, M_MPT2);
- if (sc->commands != NULL) {
- for (i = 1; i < sc->num_reqs; i++) {
- cm = &sc->commands[i];
- bus_dmamap_destroy(sc->buffer_dmat, cm->cm_dmamap);
- }
- free(sc->commands, M_MPT2);
- }
- if (sc->buffer_dmat != NULL)
- bus_dma_tag_destroy(sc->buffer_dmat);
-
if (sc->sysctl_tree != NULL)
sysctl_ctx_free(&sc->sysctl_ctx);
- mps_mapping_free_memory(sc);
-
/* Deregister the shutdown function */
if (sc->shutdown_eh != NULL)
EVENTHANDLER_DEREGISTER(shutdown_final, sc->shutdown_eh);
@@ -1504,22 +1726,28 @@
}
static __inline void
-mps_complete_command(struct mps_command *cm)
+mps_complete_command(struct mps_softc *sc, struct mps_command *cm)
{
+ MPS_FUNCTRACE(sc);
+
+ if (cm == NULL) {
+ mps_dprint(sc, MPS_ERROR, "Completing NULL command\n");
+ return;
+ }
+
if (cm->cm_flags & MPS_CM_FLAGS_POLLED)
cm->cm_flags |= MPS_CM_FLAGS_COMPLETE;
if (cm->cm_complete != NULL) {
- mps_dprint(cm->cm_sc, MPS_TRACE,
+ mps_dprint(sc, MPS_TRACE,
"%s cm %p calling cm_complete %p data %p reply %p\n",
__func__, cm, cm->cm_complete, cm->cm_complete_data,
cm->cm_reply);
- cm->cm_complete(cm->cm_sc, cm);
+ cm->cm_complete(sc, cm);
}
if (cm->cm_flags & MPS_CM_FLAGS_WAKEUP) {
- mps_dprint(cm->cm_sc, MPS_TRACE, "%s: waking up %p\n",
- __func__, cm);
+ mps_dprint(sc, MPS_TRACE, "waking up %p\n", cm);
wakeup(cm);
}
@@ -1526,7 +1754,7 @@
if (cm->cm_sc->io_cmds_active != 0) {
cm->cm_sc->io_cmds_active--;
} else {
- mps_dprint(cm->cm_sc, MPS_INFO, "Warning: io_cmds_active is "
+ mps_dprint(sc, MPS_ERROR, "Warning: io_cmds_active is "
"out of sync - resynching to 0\n");
}
}
@@ -1572,7 +1800,7 @@
break;
}
- mps_dprint(sc, MPS_INFO, "log_info(0x%08x): originator(%s), "
+ mps_dprint(sc, MPS_LOG, "log_info(0x%08x): originator(%s), "
"code(0x%02x), sub_code(0x%04x)\n", log_info,
originator_str, sas_loginfo.dw.code,
sas_loginfo.dw.subcode);
@@ -1722,9 +1950,10 @@
*/
rel_rep =
(MPI2_DIAG_RELEASE_REPLY *)reply;
- if (le16toh(rel_rep->IOCStatus) ==
+ if ((le16toh(rel_rep->IOCStatus) &
+ MPI2_IOCSTATUS_MASK) ==
MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED)
- {
+ {
pBuffer =
&sc->fw_diag_buffer_list[
rel_rep->BufferType];
@@ -1750,7 +1979,7 @@
case MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS:
default:
/* Unhandled */
- device_printf(sc->mps_dev, "Unhandled reply 0x%x\n",
+ mps_dprint(sc, MPS_ERROR, "Unhandled reply 0x%x\n",
desc->Default.ReplyFlags);
cm = NULL;
break;
@@ -1761,7 +1990,7 @@
// Print Error reply frame
if (cm->cm_reply)
mps_display_reply_info(sc,cm->cm_reply);
- mps_complete_command(cm);
+ mps_complete_command(sc, cm);
}
desc->Words.Low = 0xffffffff;
@@ -1794,7 +2023,7 @@
}
if (handled == 0)
- device_printf(sc->mps_dev, "Unhandled event 0x%x\n", le16toh(event));
+ mps_dprint(sc, MPS_EVENT, "Unhandled event 0x%x\n", le16toh(event));
/*
* This is the only place that the event/reply should be freed.
@@ -1810,7 +2039,7 @@
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
if (cm->cm_reply)
- mps_print_event(sc,
+ MPS_DPRINT_EVENT(sc, generic,
(MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply);
mps_free_command(sc, cm);
@@ -1852,7 +2081,7 @@
u32 *mask)
{
MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
- MPI2_EVENT_NOTIFICATION_REPLY *reply;
+ MPI2_EVENT_NOTIFICATION_REPLY *reply = NULL;
struct mps_command *cm;
int error, i;
@@ -1890,15 +2119,20 @@
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, 0);
+ if (cm != NULL)
+ reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply;
if ((reply == NULL) ||
(reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
error = ENXIO;
- mps_print_event(sc, reply);
+
+ if (reply)
+ MPS_DPRINT_EVENT(sc, generic, reply);
+
mps_dprint(sc, MPS_TRACE, "%s finished error %d\n", __func__, error);
- mps_free_command(sc, cm);
+ if (cm != NULL)
+ mps_free_command(sc, cm);
return (error);
}
@@ -1914,7 +2148,7 @@
/* first, reregister events */
- for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
sc->event_mask[i] = -1;
TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
@@ -1946,7 +2180,8 @@
error = mps_map_command(sc, cm);
- mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__, error);
+ mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__,
+ error);
return (error);
}
@@ -2014,7 +2249,6 @@
MPI2_SGE_SIMPLE64 *sge = sgep;
int error, type;
uint32_t saved_buf_len, saved_address_low, saved_address_high;
- u32 sge_flags;
type = (tc->Flags & MPI2_SGE_FLAGS_ELEMENT_MASK);
@@ -2034,14 +2268,12 @@
break;
case MPI2_SGE_FLAGS_SIMPLE_ELEMENT:
/* Driver only uses 64-bit SGE simple elements */
- sge = sgep;
if (len != MPS_SGE64_SIZE)
panic("SGE simple %p length %u or %zu?", sge,
MPS_SGE64_SIZE, len);
- if (((sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT) &
+ if (((le32toh(sge->FlagsLength) >> MPI2_SGE_FLAGS_SHIFT) &
MPI2_SGE_FLAGS_ADDRESS_SIZE) == 0)
- panic("SGE simple %p flags %02x not marked 64-bit?",
- sge, sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT);
+ panic("SGE simple %p not marked 64-bit?", sge);
break;
default:
@@ -2073,8 +2305,8 @@
* Mark as last element in this chain if necessary.
*/
if (type == MPI2_SGE_FLAGS_SIMPLE_ELEMENT) {
- sge->FlagsLength |=
- (MPI2_SGE_FLAGS_LAST_ELEMENT << MPI2_SGE_FLAGS_SHIFT);
+ sge->FlagsLength |= htole32(
+ MPI2_SGE_FLAGS_LAST_ELEMENT << MPI2_SGE_FLAGS_SHIFT);
}
/*
@@ -2083,11 +2315,6 @@
* understanding the code.
*/
cm->cm_sglsize -= len;
- /* Endian Safe code */
- sge_flags = sge->FlagsLength;
- sge->FlagsLength = htole32(sge_flags);
- sge->Address.High = htole32(sge->Address.High);
- sge->Address.Low = htole32(sge->Address.Low);
bcopy(sgep, cm->cm_sge, len);
cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
return (mps_add_chain(cm));
@@ -2127,27 +2354,22 @@
* 2 SGL's for a bi-directional request, they both use the same
* DMA buffer (same cm command).
*/
- saved_buf_len = sge->FlagsLength & 0x00FFFFFF;
+ saved_buf_len = le32toh(sge->FlagsLength) & 0x00FFFFFF;
saved_address_low = sge->Address.Low;
saved_address_high = sge->Address.High;
if (cm->cm_out_len) {
- sge->FlagsLength = cm->cm_out_len |
+ sge->FlagsLength = htole32(cm->cm_out_len |
((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
MPI2_SGE_FLAGS_END_OF_BUFFER |
MPI2_SGE_FLAGS_HOST_TO_IOC |
MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
- MPI2_SGE_FLAGS_SHIFT);
+ MPI2_SGE_FLAGS_SHIFT));
cm->cm_sglsize -= len;
- /* Endian Safe code */
- sge_flags = sge->FlagsLength;
- sge->FlagsLength = htole32(sge_flags);
- sge->Address.High = htole32(sge->Address.High);
- sge->Address.Low = htole32(sge->Address.Low);
bcopy(sgep, cm->cm_sge, len);
cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge
+ len);
}
- sge->FlagsLength = saved_buf_len |
+ saved_buf_len |=
((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
MPI2_SGE_FLAGS_END_OF_BUFFER |
MPI2_SGE_FLAGS_LAST_ELEMENT |
@@ -2155,24 +2377,20 @@
MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
MPI2_SGE_FLAGS_SHIFT);
if (cm->cm_flags & MPS_CM_FLAGS_DATAIN) {
- sge->FlagsLength |=
+ saved_buf_len |=
((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
MPI2_SGE_FLAGS_SHIFT);
} else {
- sge->FlagsLength |=
+ saved_buf_len |=
((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
MPI2_SGE_FLAGS_SHIFT);
}
+ sge->FlagsLength = htole32(saved_buf_len);
sge->Address.Low = saved_address_low;
sge->Address.High = saved_address_high;
}
cm->cm_sglsize -= len;
- /* Endian Safe code */
- sge_flags = sge->FlagsLength;
- sge->FlagsLength = htole32(sge_flags);
- sge->Address.High = htole32(sge->Address.High);
- sge->Address.Low = htole32(sge->Address.Low);
bcopy(sgep, cm->cm_sge, len);
cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
return (0);
@@ -2190,10 +2408,10 @@
/*
* This driver always uses 64-bit address elements for simplicity.
*/
+ bzero(&sge, sizeof(sge));
flags |= MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
- /* Set Endian safe macro in mps_push_sge */
- sge.FlagsLength = len | (flags << MPI2_SGE_FLAGS_SHIFT);
+ sge.FlagsLength = htole32(len | (flags << MPI2_SGE_FLAGS_SHIFT));
mps_from_u64(pa, &sge.Address);
return (mps_push_sge(cm, &sge, sizeof sge, segsleft));
@@ -2214,7 +2432,8 @@
* user they did the wrong thing.
*/
if ((cm->cm_max_segs != 0) && (nsegs > cm->cm_max_segs)) {
- mps_printf(sc, "%s: warning: busdma returned %d segments, "
+ mps_dprint(sc, MPS_ERROR,
+ "%s: warning: busdma returned %d segments, "
"more than the %d allowed\n", __func__, nsegs,
cm->cm_max_segs);
}
@@ -2260,9 +2479,11 @@
sflags, nsegs - i);
if (error != 0) {
/* Resource shortage, roll back! */
- mps_dprint(sc, MPS_INFO, "out of chain frames\n");
+ if (ratecheck(&sc->lastfail, &mps_chainfail_interval))
+ mps_dprint(sc, MPS_INFO, "Out of chain frames, "
+ "consider increasing hw.mps.max_chains.\n");
cm->cm_flags |= MPS_CM_FLAGS_CHAIN_FAILED;
- mps_complete_command(cm);
+ mps_complete_command(sc, cm);
return;
}
}
@@ -2290,26 +2511,21 @@
int
mps_map_command(struct mps_softc *sc, struct mps_command *cm)
{
- MPI2_SGE_SIMPLE32 *sge;
int error = 0;
if (cm->cm_flags & MPS_CM_FLAGS_USE_UIO) {
error = bus_dmamap_load_uio(sc->buffer_dmat, cm->cm_dmamap,
&cm->cm_uio, mps_data_cb2, cm, 0);
+ } else if (cm->cm_flags & MPS_CM_FLAGS_USE_CCB) {
+ error = bus_dmamap_load_ccb(sc->buffer_dmat, cm->cm_dmamap,
+ cm->cm_data, mps_data_cb, cm, 0);
} else if ((cm->cm_data != NULL) && (cm->cm_length != 0)) {
error = bus_dmamap_load(sc->buffer_dmat, cm->cm_dmamap,
cm->cm_data, cm->cm_length, mps_data_cb, cm, 0);
} else {
/* Add a zero-length element as needed */
- if (cm->cm_sge != NULL) {
- sge = (MPI2_SGE_SIMPLE32 *)cm->cm_sge;
- sge->FlagsLength = htole32((MPI2_SGE_FLAGS_LAST_ELEMENT |
- MPI2_SGE_FLAGS_END_OF_BUFFER |
- MPI2_SGE_FLAGS_END_OF_LIST |
- MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
- MPI2_SGE_FLAGS_SHIFT);
- sge->Address = 0;
- }
+ if (cm->cm_sge != NULL)
+ mps_add_dmaseg(cm, 0, 0, 0, 1);
mps_enqueue_request(sc, cm);
}
@@ -2322,64 +2538,74 @@
* be executed and enqueued automatically. Other errors come from msleep().
*/
int
-mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout)
+mps_wait_command(struct mps_softc *sc, struct mps_command **cmp, int timeout,
+ int sleep_flag)
{
int error, rc;
+ struct timeval cur_time, start_time;
+ struct mps_command *cm = *cmp;
- mtx_assert(&sc->mps_mtx, MA_OWNED);
-
- if(sc->mps_flags & MPS_FLAGS_DIAGRESET)
+ if (sc->mps_flags & MPS_FLAGS_DIAGRESET)
return EBUSY;
cm->cm_complete = NULL;
- cm->cm_flags |= MPS_CM_FLAGS_WAKEUP;
+ cm->cm_flags |= MPS_CM_FLAGS_POLLED;
error = mps_map_command(sc, cm);
if ((error != 0) && (error != EINPROGRESS))
return (error);
- error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz);
- if (error == EWOULDBLOCK) {
- mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s\n", __func__);
- rc = mps_reinit(sc);
- mps_dprint(sc, MPS_FAULT, "Reinit %s\n",
- (rc == 0) ? "success" : "failed");
- error = ETIMEDOUT;
- }
- return (error);
-}
-/*
- * This is the routine to enqueue a command synchonously and poll for
- * completion. Its use should be rare.
- */
-int
-mps_request_polled(struct mps_softc *sc, struct mps_command *cm)
-{
- int error, timeout = 0, rc;
-
- error = 0;
-
- cm->cm_flags |= MPS_CM_FLAGS_POLLED;
- cm->cm_complete = NULL;
- mps_map_command(sc, cm);
-
- while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) {
- mps_intr_locked(sc);
-
- DELAY(50 * 1000);
- if (timeout++ > 1000) {
- mps_dprint(sc, MPS_FAULT, "polling failed\n");
- error = ETIMEDOUT;
- break;
+ /*
+ * Check for context and wait for 50 mSec at a time until time has
+ * expired or the command has finished. If msleep can't be used, need
+ * to poll.
+ */
+ if (curthread->td_no_sleeping != 0)
+ sleep_flag = NO_SLEEP;
+ getmicrouptime(&start_time);
+ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP) {
+ cm->cm_flags |= MPS_CM_FLAGS_WAKEUP;
+ error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz);
+ if (error == EWOULDBLOCK) {
+ /*
+ * Record the actual elapsed time in the case of a
+ * timeout for the message below.
+ */
+ getmicrouptime(&cur_time);
+ timevalsub(&cur_time, &start_time);
}
+ } else {
+ while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) {
+ mps_intr_locked(sc);
+ if (sleep_flag == CAN_SLEEP)
+ pause("mpswait", hz/20);
+ else
+ DELAY(50000);
+
+ getmicrouptime(&cur_time);
+ timevalsub(&cur_time, &start_time);
+ if (cur_time.tv_sec > timeout) {
+ error = EWOULDBLOCK;
+ break;
+ }
+ }
}
-
- if (error) {
- mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s\n", __func__);
+
+ if (error == EWOULDBLOCK) {
+ mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s, timeout=%d,"
+ " elapsed=%jd\n", __func__, timeout,
+ (intmax_t)cur_time.tv_sec);
rc = mps_reinit(sc);
- mps_dprint(sc, MPS_FAULT, "Reinit %s\n",
- (rc == 0) ? "success" : "failed");
+ mps_dprint(sc, MPS_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
+ "failed");
+ if (sc->mps_flags & MPS_FLAGS_REALLOCATED) {
+ /*
+ * Tell the caller that we freed the command in a
+ * reinit.
+ */
+ *cmp = NULL;
+ }
+ error = ETIMEDOUT;
}
-
return (error);
}
@@ -2431,9 +2657,12 @@
cm->cm_data = params->buffer;
cm->cm_length = params->length;
- cm->cm_sge = &req->PageBufferSGE;
- cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
- cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
+ if (cm->cm_data != NULL) {
+ cm->cm_sge = &req->PageBufferSGE;
+ cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
+ cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
+ } else
+ cm->cm_sge = NULL;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_complete_data = params;
@@ -2441,11 +2670,12 @@
cm->cm_complete = mps_config_complete;
return (mps_map_command(sc, cm));
} else {
- error = mps_wait_command(sc, cm, 0);
+ error = mps_wait_command(sc, &cm, 0, CAN_SLEEP);
if (error) {
mps_dprint(sc, MPS_FAULT,
"Error %d reading config page\n", error);
- mps_free_command(sc, cm);
+ if (cm != NULL)
+ mps_free_command(sc, cm);
return (error);
}
mps_config_complete(sc, cm);
@@ -2466,6 +2696,7 @@
MPI2_CONFIG_REPLY *reply;
struct mps_config_params *params;
+ MPS_FUNCTRACE(sc);
params = cm->cm_complete_data;
if (cm->cm_data != NULL) {
@@ -2489,9 +2720,12 @@
goto done;
}
params->status = reply->IOCStatus;
- if (params->hdr.Ext.ExtPageType != 0) {
+ if (params->hdr.Struct.PageType == MPI2_CONFIG_PAGETYPE_EXTENDED) {
params->hdr.Ext.ExtPageType = reply->ExtPageType;
params->hdr.Ext.ExtPageLength = reply->ExtPageLength;
+ params->hdr.Ext.PageType = reply->Header.PageType;
+ params->hdr.Ext.PageNumber = reply->Header.PageNumber;
+ params->hdr.Ext.PageVersion = reply->Header.PageVersion;
} else {
params->hdr.Struct.PageType = reply->Header.PageType;
params->hdr.Struct.PageNumber = reply->Header.PageNumber;
Modified: trunk/sys/dev/mps/mps_config.c
===================================================================
--- trunk/sys/dev/mps/mps_config.c 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_config.c 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,11 +25,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/mps/mps_config.c 322661 2017-08-18 15:38:08Z ken $");
/* TODO Move headers to mpsvar */
#include <sys/types.h>
@@ -70,7 +72,7 @@
Mpi2IOCPage8_t *config_page)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
int error = 0;
@@ -93,12 +95,16 @@
request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for header completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -107,7 +113,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: header read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -144,12 +153,17 @@
goto out;
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for page completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -158,7 +172,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: page read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -186,7 +203,7 @@
mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
pMpi2ManufacturingPagePS_t page = NULL;
uint32_t *pPS_info;
@@ -211,8 +228,14 @@
request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
+ error = mps_wait_command(sc, &cm, 60, 0);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
/* If the poll returns error then we need to do diag reset */
@@ -262,8 +285,14 @@
goto out;
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
+ error = mps_wait_command(sc, &cm, 60, 0);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
/* If the poll returns error then we need to do diag reset */
@@ -475,7 +504,8 @@
*/
if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
- if (mpi_reply.IOCStatus !=
+ if ((le16toh(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK) !=
MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
mps_dprint(sc, MPS_FAULT,
"Multiple RAID Volume Page0! Direct Drive "
@@ -534,7 +564,7 @@
Mpi2DriverMappingPage0_t *config_page, u16 sz)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
Mpi2DriverMappingPage0_t *page = NULL;
int error = 0;
@@ -561,12 +591,16 @@
MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for header completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -575,7 +609,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: header read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -615,12 +652,16 @@
goto out;
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for page completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -629,7 +670,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: page read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -658,7 +702,7 @@
Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
int error = 0;
@@ -685,12 +729,16 @@
request->PageAddress |= htole16(entry_idx);
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for header completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -699,7 +747,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: header read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -741,12 +792,16 @@
bcopy(config_page, page, MIN(cm->cm_length,
(sizeof(Mpi2DriverMappingPage0_t))));
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request to write page completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -755,7 +810,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: page written with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -784,7 +842,7 @@
*mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
Mpi2SasDevicePage0_t *page = NULL;
int error = 0;
@@ -808,12 +866,16 @@
request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for header completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -822,7 +884,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: header read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -862,12 +927,16 @@
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for page completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -876,7 +945,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: page read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -905,7 +977,7 @@
Mpi2BiosPage3_t *config_page)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
Mpi2BiosPage3_t *page = NULL;
int error = 0;
@@ -928,12 +1000,16 @@
request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for header completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -942,7 +1018,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: header read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -980,12 +1059,16 @@
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for page completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -994,7 +1077,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: page read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -1023,7 +1109,7 @@
*mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
Mpi2RaidVolPage0_t *page = NULL;
int error = 0;
@@ -1046,8 +1132,14 @@
request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
+ error = mps_wait_command(sc, &cm, 60, 0);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
/* If the poll returns error then we need to do diag reset */
@@ -1099,8 +1191,13 @@
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
+ error = mps_wait_command(sc, &cm, 60, 0);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
/* If the poll returns error then we need to do diag reset */
@@ -1143,7 +1240,7 @@
*mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
Mpi2RaidVolPage1_t *page = NULL;
int error = 0;
@@ -1166,12 +1263,16 @@
request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for header completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -1180,7 +1281,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: header read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -1219,12 +1323,16 @@
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for page completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -1233,7 +1341,10 @@
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: page read with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -1288,7 +1399,7 @@
Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
{
MPI2_CONFIG_REQUEST *request;
- MPI2_CONFIG_REPLY *reply;
+ MPI2_CONFIG_REPLY *reply = NULL;
struct mps_command *cm;
Mpi2RaidPhysDiskPage0_t *page = NULL;
int error = 0;
@@ -1311,8 +1422,14 @@
request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
+ error = mps_wait_command(sc, &cm, 60, 0);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
/* If the poll returns error then we need to do diag reset */
@@ -1364,8 +1481,13 @@
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
+ error = mps_wait_command(sc, &cm, 60, 0);
+ if (cm != NULL)
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
/* If the poll returns error then we need to do diag reset */
Modified: trunk/sys/dev/mps/mps_ioctl.h
===================================================================
--- trunk/sys/dev/mps/mps_ioctl.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_ioctl.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2008 Yahoo!, Inc.
* All rights reserved.
@@ -27,12 +28,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD userland interface
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mps_ioctl.h 281564 2015-04-15 21:47:15Z slm $
*/
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,9 +58,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mps_ioctl.h 281564 2015-04-15 21:47:15Z slm $
*/
#ifndef _MPS_IOCTL_H_
Modified: trunk/sys/dev/mps/mps_mapping.c
===================================================================
--- trunk/sys/dev/mps/mps_mapping.c 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_mapping.c 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,11 +25,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/mps/mps_mapping.c 319445 2017-06-01 16:54:10Z slm $");
/* TODO Move headers to mpsvar */
#include <sys/types.h>
@@ -42,6 +44,7 @@
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/sysctl.h>
+#include <sys/sbuf.h>
#include <sys/eventhandler.h>
#include <sys/uio.h>
#include <machine/bus.h>
@@ -58,7 +61,7 @@
#include <dev/mps/mps_mapping.h>
/**
- * _mapping_clear_entry - Clear a particular mapping entry.
+ * _mapping_clear_map_entry - Clear a particular mapping entry.
* @map_entry: map table entry
*
* Returns nothing.
@@ -71,7 +74,6 @@
map_entry->phy_bits = 0;
map_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
map_entry->dev_handle = 0;
- map_entry->channel = -1;
map_entry->id = -1;
map_entry->missing_count = 0;
map_entry->init_complete = 0;
@@ -138,12 +140,15 @@
dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
dpm_entry->Reserved1 = 0;
+ mps_dprint(sc, MPS_MAPPING, "%s: Writing DPM entry %d for enclosure.\n",
+ __func__, et_entry->dpm_entry_num);
memcpy(&config_page.Entry, (u8 *)dpm_entry,
sizeof(Mpi2DriverMap0Entry_t));
if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
et_entry->dpm_entry_num)) {
- printf("%s: write of dpm entry %d for enclosure failed\n",
- __func__, et_entry->dpm_entry_num);
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Write of DPM "
+ "entry %d for enclosure failed.\n", __func__,
+ et_entry->dpm_entry_num);
dpm_entry->MappingInformation = le16toh(dpm_entry->
MappingInformation);
dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
@@ -162,7 +167,7 @@
/**
* _mapping_commit_map_entry - write a particular map table entry in DPM page0.
* @sc: per adapter object
- * @enc_entry: enclosure table entry
+ * @mt_entry: mapping table entry
*
* Returns 0 for success, non-zero for failure.
*/
@@ -178,6 +183,19 @@
if (!sc->is_dpm_enable)
return 0;
+ /*
+ * It's possible that this Map Entry points to a BAD DPM index. This
+ * can happen if the Map Entry is a for a missing device and the DPM
+ * entry that was being used by this device is now being used by some
+ * new device. So, check for a BAD DPM index and just return if so.
+ */
+ if (mt_entry->dpm_entry_num == MPS_DPM_BAD_IDX) {
+ mps_dprint(sc, MPS_MAPPING, "%s: DPM entry location for target "
+ "%d is invalid. DPM will not be written.\n", __func__,
+ mt_entry->id);
+ return 0;
+ }
+
memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
@@ -191,13 +209,16 @@
dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
dpm_entry->PhysicalBitsMapping = 0;
dpm_entry->Reserved1 = 0;
- dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
memcpy(&config_page.Entry, (u8 *)dpm_entry,
sizeof(Mpi2DriverMap0Entry_t));
+
+ mps_dprint(sc, MPS_MAPPING, "%s: Writing DPM entry %d for target %d.\n",
+ __func__, mt_entry->dpm_entry_num, mt_entry->id);
if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
mt_entry->dpm_entry_num)) {
- printf("%s: write of dpm entry %d for device failed\n",
- __func__, mt_entry->dpm_entry_num);
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Write of DPM "
+ "entry %d for target %d failed.\n", __func__,
+ mt_entry->dpm_entry_num, mt_entry->id);
dpm_entry->MappingInformation = le16toh(dpm_entry->
MappingInformation);
dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
@@ -305,7 +326,7 @@
et_entry = &sc->enclosure_table[enc_idx];
if ((et_entry->missing_count > high_missing_count) &&
!et_entry->skip_search) {
- high_missing_count = et_entry->missing_count;
+ high_missing_count = et_entry->missing_count;
high_idx = enc_idx;
}
}
@@ -324,7 +345,7 @@
static u32
_mapping_get_high_missing_mt_idx(struct mps_softc *sc)
{
- u32 map_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
+ u32 map_idx, high_idx = MPS_MAPTABLE_BAD_IDX;
u8 high_missing_count = 0;
u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
struct dev_mapping_table *mt_entry;
@@ -336,12 +357,13 @@
end_idx = sc->max_devices;
if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
start_idx = 1;
- if (sc->ir_firmware)
+ if (sc->ir_firmware) {
_mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
- if (start_idx == start_idx_ir)
- start_idx = end_idx_ir + 1;
- else
- end_idx = start_idx_ir;
+ if (start_idx == start_idx_ir)
+ start_idx = end_idx_ir + 1;
+ else
+ end_idx = start_idx_ir;
+ }
mt_entry = &sc->mapping_table[start_idx];
for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
if (mt_entry->missing_count > high_missing_count) {
@@ -367,7 +389,7 @@
_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
mt_entry = &sc->mapping_table[start_idx];
- for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
+ for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
if (mt_entry->physical_id == wwid)
return map_idx;
@@ -455,20 +477,32 @@
u32 high_idx = MPS_MAPTABLE_BAD_IDX;
struct dev_mapping_table *mt_entry;
+ /*
+ * The IN_USE flag should be clear if the entry is available to use.
+ * This flag is cleared on initialization and and when a volume is
+ * deleted. All other times this flag should be set. If, for some
+ * reason, a free entry cannot be found, look for the entry with the
+ * highest missing count just in case there is one.
+ */
_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
mt_entry = &sc->mapping_table[start_idx];
- for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
+ for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
if (!(mt_entry->device_info & MPS_MAP_IN_USE))
return map_idx;
- mt_entry = &sc->mapping_table[start_idx];
- for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
if (mt_entry->missing_count > high_missing_count) {
high_missing_count = mt_entry->missing_count;
high_idx = map_idx;
}
}
+
+ if (high_idx == MPS_MAPTABLE_BAD_IDX) {
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Could not find a "
+ "free entry in the mapping table for a Volume. The mapping "
+ "table is probably corrupt.\n", __func__);
+ }
+
return high_idx;
}
@@ -491,6 +525,7 @@
if (sc->ir_firmware && (volume_mapping_flags ==
MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING))
max_idx -= sc->max_volumes;
+
for (map_idx = start_idx; map_idx < max_idx; map_idx++, mt_entry++)
if (!(mt_entry->device_info & (MPS_MAP_IN_USE |
MPS_DEV_RESERVED)))
@@ -539,12 +574,66 @@
_mapping_get_free_dpm_idx(struct mps_softc *sc)
{
u16 entry_num;
+ Mpi2DriverMap0Entry_t *dpm_entry;
+ u16 current_entry = MPS_DPM_BAD_IDX, missing_cnt, high_missing_cnt = 0;
+ u64 physical_id;
+ struct dev_mapping_table *mt_entry;
+ u32 map_idx;
- for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
- if (!sc->dpm_entry_used[entry_num])
- return entry_num;
+ for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
+ dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
+ sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+ dpm_entry += entry_num;
+ missing_cnt = dpm_entry->MappingInformation &
+ MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
+
+ /*
+ * If entry is used and not missing, then this entry can't be
+ * used. Look at next one.
+ */
+ if (sc->dpm_entry_used[entry_num] && !missing_cnt)
+ continue;
+
+ /*
+ * If this entry is not used at all, then the missing count
+ * doesn't matter. Just use this one. Otherwise, keep looking
+ * and make sure the entry with the highest missing count is
+ * used.
+ */
+ if (!sc->dpm_entry_used[entry_num]) {
+ current_entry = entry_num;
+ break;
+ }
+ if ((current_entry == MPS_DPM_BAD_IDX) ||
+ (missing_cnt > high_missing_cnt)) {
+ current_entry = entry_num;
+ high_missing_cnt = missing_cnt;
+ }
+ }
+
+ /*
+ * If an entry has been found to use and it's already marked as used
+ * it means that some device was already using this entry but it's
+ * missing, and that means that the connection between the missing
+ * device's DPM entry and the mapping table needs to be cleared. To do
+ * this, use the Physical ID of the old device still in the DPM entry
+ * to find its mapping table entry, then mark its DPM entry as BAD.
+ */
+ if ((current_entry != MPS_DPM_BAD_IDX) &&
+ sc->dpm_entry_used[current_entry]) {
+ dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
+ sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+ dpm_entry += current_entry;
+ physical_id = dpm_entry->PhysicalIdentifier.High;
+ physical_id = (physical_id << 32) |
+ dpm_entry->PhysicalIdentifier.Low;
+ map_idx = _mapping_get_mt_idx_from_id(sc, physical_id);
+ if (map_idx != MPS_MAPTABLE_BAD_IDX) {
+ mt_entry = &sc->mapping_table[map_idx];
+ mt_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
+ }
}
- return MPS_DPM_BAD_IDX;
+ return current_entry;
}
/**
@@ -563,40 +652,57 @@
Mpi2EventIrConfigElement_t *element, u64 wwid)
{
struct dev_mapping_table *mt_entry;
- u8 missing_cnt, reason = element->ReasonCode;
+ u8 missing_cnt, reason = element->ReasonCode, update_dpm = 1;
u16 dpm_idx;
Mpi2DriverMap0Entry_t *dpm_entry;
- if (!sc->is_dpm_enable)
- return;
+ /*
+ * Depending on the reason code, update the missing count. Always set
+ * the init_complete flag when here, so just do it first. That flag is
+ * used for volumes to make sure that the DPM entry has been updated.
+ * When a volume is deleted, clear the map entry's IN_USE flag so that
+ * the entry can be used again if another volume is created. Also clear
+ * its dev_handle entry so that other functions can't find this volume
+ * by the handle, since it's not defined any longer.
+ */
mt_entry = &sc->mapping_table[map_idx];
- if (reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) {
+ mt_entry->init_complete = 1;
+ if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) ||
+ (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED)) {
mt_entry->missing_count = 0;
- } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
- mt_entry->missing_count = 0;
- mt_entry->init_complete = 0;
- } else if ((reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED) ||
- (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)) {
- if (!mt_entry->init_complete) {
- if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
- mt_entry->missing_count++;
- else
- mt_entry->init_complete = 1;
- }
- if (!mt_entry->missing_count)
+ } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
+ if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
mt_entry->missing_count++;
+
+ mt_entry->device_info &= ~MPS_MAP_IN_USE;
mt_entry->dev_handle = 0;
}
+ /*
+ * If persistent mapping is enabled, update the DPM with the new missing
+ * count for the volume. If the DPM index is bad, get a free one. If
+ * it's bad for a volume that's being deleted do nothing because that
+ * volume doesn't have a DPM entry.
+ */
+ if (!sc->is_dpm_enable)
+ return;
dpm_idx = mt_entry->dpm_entry_num;
if (dpm_idx == MPS_DPM_BAD_IDX) {
- if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) ||
- (reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED))
- dpm_idx = _mapping_get_dpm_idx_from_id(sc,
- mt_entry->physical_id, 0);
- else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
+ if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
+ {
+ mps_dprint(sc, MPS_MAPPING, "%s: Volume being deleted "
+ "is not in DPM so DPM missing count will not be "
+ "updated.\n", __func__);
return;
+ }
}
+ if (dpm_idx == MPS_DPM_BAD_IDX)
+ dpm_idx = _mapping_get_free_dpm_idx(sc);
+
+ /*
+ * Got the DPM entry for the volume or found a free DPM entry if this is
+ * a new volume. Check if the current information is outdated.
+ */
if (dpm_idx != MPS_DPM_BAD_IDX) {
dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
@@ -604,17 +710,25 @@
missing_cnt = dpm_entry->MappingInformation &
MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
if ((mt_entry->physical_id ==
- le64toh((u64)dpm_entry->PhysicalIdentifier.High |
- dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt ==
- mt_entry->missing_count))
- mt_entry->init_complete = 1;
- } else {
- dpm_idx = _mapping_get_free_dpm_idx(sc);
- mt_entry->init_complete = 0;
+ le64toh(((u64)dpm_entry->PhysicalIdentifier.High << 32) |
+ (u64)dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt ==
+ mt_entry->missing_count)) {
+ mps_dprint(sc, MPS_MAPPING, "%s: DPM entry for volume "
+ "with target ID %d does not require an update.\n",
+ __func__, mt_entry->id);
+ update_dpm = 0;
+ }
}
- if ((dpm_idx != MPS_DPM_BAD_IDX) && !mt_entry->init_complete) {
- mt_entry->init_complete = 1;
+ /*
+ * Update the volume's persistent info if it's new or the ID or missing
+ * count has changed. If a good DPM index has not been found by now,
+ * there is no space left in the DPM table.
+ */
+ if ((dpm_idx != MPS_DPM_BAD_IDX) && update_dpm) {
+ mps_dprint(sc, MPS_MAPPING, "%s: Update DPM entry for volume "
+ "with target ID %d.\n", __func__, mt_entry->id);
+
mt_entry->dpm_entry_num = dpm_idx;
dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
@@ -630,44 +744,47 @@
sc->dpm_flush_entry[dpm_idx] = 1;
sc->dpm_entry_used[dpm_idx] = 1;
} else if (dpm_idx == MPS_DPM_BAD_IDX) {
- printf("%s: no space to add entry in DPM table\n", __func__);
- mt_entry->init_complete = 1;
+ mps_dprint(sc, MPS_INFO | MPS_MAPPING, "%s: No space to add an "
+ "entry in the DPM table for volume with target ID %d.\n",
+ __func__, mt_entry->id);
}
}
/**
- * _mapping_add_to_removal_table - mark an entry for removal
+ * _mapping_add_to_removal_table - add DPM index to the removal table
* @sc: per adapter object
- * @handle: Handle of enclosures/device/volume
+ * @dpm_idx: Index of DPM entry to remove
*
- * Adds the handle or DPM entry number in removal table.
+ * Adds a DPM entry number to the removal table.
*
* Returns nothing.
*/
static void
-_mapping_add_to_removal_table(struct mps_softc *sc, u16 handle,
- u16 dpm_idx)
+_mapping_add_to_removal_table(struct mps_softc *sc, u16 dpm_idx)
{
struct map_removal_table *remove_entry;
u32 i;
- u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+ /*
+ * This is only used to remove entries from the DPM in the controller.
+ * If DPM is not enabled, just return.
+ */
+ if (!sc->is_dpm_enable)
+ return;
+
+ /*
+ * Find the first available removal_table entry and add the new entry
+ * there.
+ */
remove_entry = sc->removal_table;
for (i = 0; i < sc->max_devices; i++, remove_entry++) {
- if (remove_entry->dev_handle || remove_entry->dpm_entry_num !=
- MPS_DPM_BAD_IDX)
+ if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX)
continue;
- if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
- MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
- if (dpm_idx)
- remove_entry->dpm_entry_num = dpm_idx;
- if (remove_entry->dpm_entry_num == MPS_DPM_BAD_IDX)
- remove_entry->dev_handle = handle;
- } else if ((ioc_pg8_flags &
- MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
- MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING)
- remove_entry->dev_handle = handle;
+
+ mps_dprint(sc, MPS_MAPPING, "%s: Adding DPM entry %d to table "
+ "for removal.\n", __func__, dpm_idx);
+ remove_entry->dpm_entry_num = dpm_idx;
break;
}
@@ -678,8 +795,13 @@
* @sc: per adapter object
* @topo_change: Topology change event entry
*
- * Search through the topology change list and if any device is found not
- * responding it's associated map table entry and DPM entry is updated
+ * Increment the missing count in the mapping table for a device that is not
+ * responding. If Persitent Mapping is used, increment the DPM entry as well.
+ * Currently, this function only increments the missing count if the device
+ * goes missing, so after initialization has completed. This means that the
+ * missing count can only go from 0 to 1 here. The missing count is incremented
+ * during initialization as well, so that's where a target's missing count can
+ * go past 1.
*
* Returns nothing.
*/
@@ -703,34 +825,45 @@
dev_handle);
phy_change->is_processed = 1;
if (map_idx == MPS_MAPTABLE_BAD_IDX) {
- printf("%s: device is already removed from mapping "
- "table\n", __func__);
+ mps_dprint(sc, MPS_INFO | MPS_MAPPING, "%s: device is "
+ "already removed from mapping table\n", __func__);
continue;
}
mt_entry = &sc->mapping_table[map_idx];
- if (!mt_entry->init_complete) {
- if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
- mt_entry->missing_count++;
- else
- mt_entry->init_complete = 1;
- }
- if (!mt_entry->missing_count)
+ if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
mt_entry->missing_count++;
- _mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0);
- mt_entry->dev_handle = 0;
+ /*
+ * When using Enc/Slot mapping, when a device is removed, it's
+ * mapping table information should be cleared. Otherwise, the
+ * target ID will be incorrect if this same device is re-added
+ * to a different slot.
+ */
+ if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+ MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+ _mapping_clear_map_entry(mt_entry);
+ }
+
+ /*
+ * When using device mapping, update the missing count in the
+ * DPM entry, but only if the missing count has changed.
+ */
if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
- sc->is_dpm_enable && !mt_entry->init_complete &&
+ sc->is_dpm_enable &&
mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
dpm_entry =
(Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
dpm_entry += mt_entry->dpm_entry_num;
- dpm_entry->MappingInformation = mt_entry->missing_count;
- sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1;
+ if (dpm_entry->MappingInformation !=
+ mt_entry->missing_count) {
+ dpm_entry->MappingInformation =
+ mt_entry->missing_count;
+ sc->dpm_flush_entry[mt_entry->dpm_entry_num] =
+ 1;
+ }
}
- mt_entry->init_complete = 1;
}
}
@@ -763,6 +896,10 @@
vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+ /*
+ * The end of the mapping table depends on where volumes are kept, if
+ * IR is enabled.
+ */
if (!sc->ir_firmware)
end_of_table = sc->max_devices;
else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)
@@ -770,6 +907,17 @@
else
end_of_table = sc->max_devices - sc->max_volumes;
+ /*
+ * The skip_count is the number of entries that are reserved at the
+ * beginning of the mapping table. But, it does not include the number
+ * of Physical IDs that are reserved for direct attached devices. Look
+ * through the mapping table after these reserved entries to see if
+ * the devices for this enclosure are already mapped. The PHY bit check
+ * is used to make sure that at least one PHY bit is common between the
+ * enclosure and the device that is already mapped.
+ */
+ mps_dprint(sc, MPS_MAPPING, "%s: Looking for space in the mapping "
+ "table for added enclosure.\n", __func__);
for (map_idx = (max_num_phy_ids + skip_count);
map_idx < end_of_table; map_idx++) {
mt_entry = &sc->mapping_table[map_idx];
@@ -779,11 +927,21 @@
num_found += 1;
if (num_found == et_entry->num_slots) {
start_idx = (map_idx - num_found) + 1;
+ mps_dprint(sc, MPS_MAPPING, "%s: Found space "
+ "in the mapping for enclosure at map index "
+ "%d.\n", __func__, start_idx);
return start_idx;
}
} else
num_found = 0;
}
+
+ /*
+ * If the enclosure's devices are not mapped already, look for
+ * contiguous entries in the mapping table that are not reserved. If
+ * enough entries are found, return the starting index for that space.
+ */
+ num_found = 0;
for (map_idx = (max_num_phy_ids + skip_count);
map_idx < end_of_table; map_idx++) {
mt_entry = &sc->mapping_table[map_idx];
@@ -791,6 +949,9 @@
num_found += 1;
if (num_found == et_entry->num_slots) {
start_idx = (map_idx - num_found) + 1;
+ mps_dprint(sc, MPS_MAPPING, "%s: Found space "
+ "in the mapping for enclosure at map index "
+ "%d.\n", __func__, start_idx);
return start_idx;
}
} else
@@ -797,21 +958,58 @@
num_found = 0;
}
+ /*
+ * If here, it means that not enough space in the mapping table was
+ * found to support this enclosure, so go through the enclosure table to
+ * see if any enclosure entries have a missing count. If so, get the
+ * enclosure with the highest missing count and check it to see if there
+ * is enough space for the new enclosure.
+ */
while (!done_flag) {
enc_idx = _mapping_get_high_missing_et_idx(sc);
- if (enc_idx == MPS_ENCTABLE_BAD_IDX)
+ if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
+ mps_dprint(sc, MPS_MAPPING, "%s: Not enough space was "
+ "found in the mapping for the added enclosure.\n",
+ __func__);
return MPS_MAPTABLE_BAD_IDX;
+ }
+
+ /*
+ * Found a missing enclosure. Set the skip_search flag so this
+ * enclosure is not checked again for a high missing count if
+ * the loop continues. This way, all missing enclosures can
+ * have their space added together to find enough space in the
+ * mapping table for the added enclosure. The space must be
+ * contiguous.
+ */
+ mps_dprint(sc, MPS_MAPPING, "%s: Space from a missing "
+ "enclosure was found.\n", __func__);
enc_entry = &sc->enclosure_table[enc_idx];
- /*VSP FIXME*/
enc_entry->skip_search = 1;
+
+ /*
+ * Unmark all of the missing enclosure's device's reserved
+ * space. These will be remarked as reserved if this missing
+ * enclosure's space is not used.
+ */
+ mps_dprint(sc, MPS_MAPPING, "%s: Clear the reserved flag for "
+ "all of the map entries for the enclosure.\n", __func__);
mt_entry = &sc->mapping_table[enc_entry->start_index];
for (map_idx = enc_entry->start_index; map_idx <
(enc_entry->start_index + enc_entry->num_slots); map_idx++,
mt_entry++)
- mt_entry->device_info &= ~MPS_DEV_RESERVED;
+ mt_entry->device_info &= ~MPS_DEV_RESERVED;
+
+ /*
+ * Now that space has been unreserved, check again to see if
+ * enough space is available for the new enclosure.
+ */
+ mps_dprint(sc, MPS_MAPPING, "%s: Check if new mapping space is "
+ "enough for the new enclosure.\n", __func__);
found_space = 0;
- for (map_idx = (max_num_phy_ids +
- skip_count); map_idx < end_of_table; map_idx++) {
+ num_found = 0;
+ for (map_idx = (max_num_phy_ids + skip_count);
+ map_idx < end_of_table; map_idx++) {
mt_entry = &sc->mapping_table[map_idx];
if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
num_found += 1;
@@ -818,13 +1016,24 @@
if (num_found == et_entry->num_slots) {
start_idx = (map_idx - num_found) + 1;
found_space = 1;
+ break;
}
} else
num_found = 0;
}
-
if (!found_space)
continue;
+
+ /*
+ * If enough space was found, all of the missing enclosures that
+ * will be used for the new enclosure must be added to the
+ * removal table. Then all mappings for the enclosure's devices
+ * and for the enclosure itself need to be cleared. There may be
+ * more than one enclosure to add to the removal table and
+ * clear.
+ */
+ mps_dprint(sc, MPS_MAPPING, "%s: Found space in the mapping "
+ "for enclosure at map index %d.\n", __func__, start_idx);
for (map_idx = start_idx; map_idx < (start_idx + num_found);
map_idx++) {
enc_entry = sc->enclosure_table;
@@ -835,26 +1044,38 @@
enc_entry->num_slots))
continue;
if (!enc_entry->removal_flag) {
+ mps_dprint(sc, MPS_MAPPING, "%s: "
+ "Enclosure %d will be removed from "
+ "the mapping table.\n", __func__,
+ enc_idx);
enc_entry->removal_flag = 1;
- _mapping_add_to_removal_table(sc, 0,
+ _mapping_add_to_removal_table(sc,
enc_entry->dpm_entry_num);
}
mt_entry = &sc->mapping_table[map_idx];
- if (mt_entry->device_info &
- MPS_MAP_IN_USE) {
- _mapping_add_to_removal_table(sc,
- mt_entry->dev_handle, 0);
- _mapping_clear_map_entry(mt_entry);
- }
+ _mapping_clear_map_entry(mt_entry);
if (map_idx == (enc_entry->start_index +
enc_entry->num_slots - 1))
_mapping_clear_enc_entry(et_entry);
}
}
+
+ /*
+ * During the search for space for this enclosure, some entries
+ * in the mapping table may have been unreserved. Go back and
+ * change all of these to reserved again. Only the enclosures
+ * with the removal_flag set should be left as unreserved. The
+ * skip_search flag needs to be cleared as well so that the
+ * enclosure's space will be looked at the next time space is
+ * needed.
+ */
enc_entry = sc->enclosure_table;
for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
enc_idx++, enc_entry++) {
if (!enc_entry->removal_flag) {
+ mps_dprint(sc, MPS_MAPPING, "%s: Reset the "
+ "reserved flag for all of the map entries "
+ "for enclosure %d.\n", __func__, enc_idx);
mt_entry = &sc->mapping_table[enc_entry->
start_index];
for (map_idx = enc_entry->start_index; map_idx <
@@ -895,7 +1116,7 @@
struct enc_mapping_table *et_entry;
struct dev_mapping_table *mt_entry;
u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
- int rc;
+ int rc = 1;
for (entry = 0; entry < topo_change->num_entries; entry++) {
phy_change = &topo_change->phy_details[entry];
@@ -902,6 +1123,7 @@
if (phy_change->is_processed || !phy_change->dev_handle ||
phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED)
continue;
+
if (mps_config_get_sas_device_pg0(sc, &mpi_reply,
&sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
phy_change->dev_handle)) {
@@ -909,51 +1131,55 @@
continue;
}
+ /*
+ * Always get SATA Identify information because this is used
+ * to determine if Start/Stop Unit should be sent to the drive
+ * when the system is shutdown.
+ */
device_info = le32toh(sas_device_pg0.DeviceInfo);
- if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
- MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
- if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
- (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
- rc = mpssas_get_sas_address_for_sata_disk(sc,
- &sas_address, phy_change->dev_handle,
- device_info);
- if (rc) {
- printf("%s: failed to compute the "
- "hashed SAS Address for SATA "
- "device with handle 0x%04x\n",
- __func__, phy_change->dev_handle);
- sas_address =
- sas_device_pg0.SASAddress.High;
- sas_address = (sas_address << 32) |
- sas_device_pg0.SASAddress.Low;
- }
+ sas_address = le32toh(sas_device_pg0.SASAddress.High);
+ sas_address = (sas_address << 32) |
+ le32toh(sas_device_pg0.SASAddress.Low);
+ if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
+ (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
+ rc = mpssas_get_sas_address_for_sata_disk(sc,
+ &sas_address, phy_change->dev_handle, device_info,
+ &phy_change->is_SATA_SSD);
+ if (rc) {
+ mps_dprint(sc, MPS_ERROR, "%s: failed to get "
+ "disk type (SSD or HDD) and SAS Address "
+ "for SATA device with handle 0x%04x\n",
+ __func__, phy_change->dev_handle);
+ } else {
mps_dprint(sc, MPS_INFO, "SAS Address for SATA "
- "device = %jx\n", sas_address);
- } else {
- sas_address =
- sas_device_pg0.SASAddress.High;
- sas_address = (sas_address << 32) |
- sas_device_pg0.SASAddress.Low;
+ "device = %jx\n", sas_address);
}
- } else {
- sas_address = sas_device_pg0.SASAddress.High;
- sas_address = (sas_address << 32) |
- sas_device_pg0.SASAddress.Low;
}
+
phy_change->physical_id = sas_address;
phy_change->slot = le16toh(sas_device_pg0.Slot);
- phy_change->device_info =
- le32toh(sas_device_pg0.DeviceInfo);
+ phy_change->device_info = device_info;
+ /*
+ * When using Enc/Slot mapping, if this device is an enclosure
+ * make sure that all of its slots can fit into the mapping
+ * table.
+ */
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+ /*
+ * The enclosure should already be in the enclosure
+ * table due to the Enclosure Add event. If not, just
+ * continue, nothing can be done.
+ */
enc_idx = _mapping_get_enc_idx_from_handle(sc,
topo_change->enc_handle);
if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
phy_change->is_processed = 1;
- printf("%s: failed to add the device with "
- "handle 0x%04x because the enclosure is "
- "not in the mapping table\n", __func__,
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
+ "failed to add the device with handle "
+ "0x%04x because the enclosure is not in "
+ "the mapping table\n", __func__,
phy_change->dev_handle);
continue;
}
@@ -967,8 +1193,20 @@
continue;
}
et_entry = &sc->enclosure_table[enc_idx];
+
+ /*
+ * If the enclosure already has a start_index, it's been
+ * mapped, so go to the next Topo change.
+ */
if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX)
continue;
+
+ /*
+ * If the Expander Handle is 0, the devices are direct
+ * attached. In that case, the start_index must be just
+ * after the reserved entries. Otherwise, find space in
+ * the mapping table for the enclosure's devices.
+ */
if (!topo_change->exp_handle) {
map_idx = sc->num_rsvd_entries;
et_entry->start_index = map_idx;
@@ -976,8 +1214,26 @@
map_idx = _mapping_find_enc_map_space(sc,
et_entry);
et_entry->start_index = map_idx;
+
+ /*
+ * If space cannot be found to hold all of the
+ * enclosure's devices in the mapping table,
+ * there's no need to continue checking the
+ * other devices in this event. Set all of the
+ * phy_details for this event (if the change is
+ * for an add) as already processed because none
+ * of these devices can be added to the mapping
+ * table.
+ */
if (et_entry->start_index ==
MPS_MAPTABLE_BAD_IDX) {
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
+ "%s: failed to add the enclosure "
+ "with ID 0x%016jx because there is "
+ "no free space available in the "
+ "mapping table for all of the "
+ "enclosure's devices.\n", __func__,
+ (uintmax_t)et_entry->enclosure_id);
phy_change->is_processed = 1;
for (phy_idx = 0; phy_idx <
topo_change->num_entries;
@@ -993,6 +1249,15 @@
break;
}
}
+
+ /*
+ * Found space in the mapping table for this enclosure.
+ * Initialize each mapping table entry for the
+ * enclosure.
+ */
+ mps_dprint(sc, MPS_MAPPING, "%s: Initialize %d map "
+ "entries for the enclosure, starting at map index "
+ " %d.\n", __func__, et_entry->num_slots, map_idx);
mt_entry = &sc->mapping_table[map_idx];
for (index = map_idx; index < (et_entry->num_slots
+ map_idx); index++, mt_entry++) {
@@ -999,6 +1264,7 @@
mt_entry->device_info = MPS_DEV_RESERVED;
mt_entry->physical_id = et_entry->enclosure_id;
mt_entry->phy_bits = et_entry->phy_bits;
+ mt_entry->missing_count = 0;
}
}
}
@@ -1018,6 +1284,7 @@
struct dev_mapping_table *mt_entry;
u16 slots = et_entry->num_slots, map_idx;
u32 start_idx = et_entry->start_index;
+
if (start_idx != MPS_MAPTABLE_BAD_IDX) {
mt_entry = &sc->mapping_table[start_idx];
for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
@@ -1067,6 +1334,13 @@
}
}
}
+
+ /*
+ * When using Enc/Slot mapping, if a new enclosure was added and old
+ * enclosure space was needed, the enclosure table may now have gaps
+ * that need to be closed. All enclosure mappings need to be contiguous
+ * so that space can be reused correctly if available.
+ */
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
num_entries = sc->num_enc_table_entries;
@@ -1109,8 +1383,8 @@
* @sc: per adapter object
* @topo_change: Topology change event entry
*
- * Search through the topology change event list and updates map table,
- * enclosure table and DPM pages for for the newly added devices.
+ * Search through the topology change event list and update map table,
+ * enclosure table and DPM pages for the newly added devices.
*
* Returns nothing
*/
@@ -1147,30 +1421,41 @@
(sc, topo_change->enc_handle);
if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
phy_change->is_processed = 1;
- printf("%s: failed to add the device with "
- "handle 0x%04x because the enclosure is "
- "not in the mapping table\n", __func__,
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
+ "failed to add the device with handle "
+ "0x%04x because the enclosure is not in "
+ "the mapping table\n", __func__,
phy_change->dev_handle);
continue;
}
+
+ /*
+ * If the enclosure's start_index is BAD here, it means
+ * that there is no room in the mapping table to cover
+ * all of the devices that could be in the enclosure.
+ * There's no reason to process any of the devices for
+ * this enclosure since they can't be mapped.
+ */
et_entry = &sc->enclosure_table[enc_idx];
if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) {
phy_change->is_processed = 1;
- if (!sc->mt_full_retry) {
- sc->mt_add_device_failed = 1;
- continue;
- }
- printf("%s: failed to add the device with "
- "handle 0x%04x because there is no free "
- "space available in the mapping table\n",
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
+ "failed to add the device with handle "
+ "0x%04x because there is no free space "
+ "available in the mapping table\n",
__func__, phy_change->dev_handle);
continue;
}
+
+ /*
+ * Add this device to the mapping table at the correct
+ * offset where space was found to map the enclosure.
+ * Then setup the DPM entry information if being used.
+ */
map_idx = et_entry->start_index + phy_change->slot -
et_entry->start_slot;
mt_entry = &sc->mapping_table[map_idx];
mt_entry->physical_id = phy_change->physical_id;
- mt_entry->channel = 0;
mt_entry->id = map_idx;
mt_entry->dev_handle = phy_change->dev_handle;
mt_entry->missing_count = 0;
@@ -1197,12 +1482,12 @@
et_entry->enclosure_id);
dpm_entry->
PhysicalIdentifier.High =
- ( et_entry->enclosure_id
+ (et_entry->enclosure_id
>> 32);
dpm_entry->DeviceIndex =
(U16)et_entry->start_index;
dpm_entry->MappingInformation =
- et_entry->num_slots;
+ et_entry->num_slots;
dpm_entry->MappingInformation
<<= map_shift;
dpm_entry->PhysicalBitsMapping
@@ -1209,7 +1494,6 @@
= et_entry->phy_bits;
et_entry->dpm_entry_num =
dpm_idx;
- /* FIXME Do I need to set the dpm_idxin mt_entry too */
sc->dpm_entry_used[dpm_idx] = 1;
sc->dpm_flush_entry[dpm_idx] =
1;
@@ -1216,12 +1500,13 @@
phy_change->is_processed = 1;
} else {
phy_change->is_processed = 1;
- printf("%s: failed to add the "
- "device with handle 0x%04x "
- "to persistent table "
- "because there is no free "
- "space available\n",
- __func__,
+ mps_dprint(sc, MPS_ERROR |
+ MPS_MAPPING, "%s: failed "
+ "to add the device with "
+ "handle 0x%04x to "
+ "persistent table because "
+ "there is no free space "
+ "available\n", __func__,
phy_change->dev_handle);
}
} else {
@@ -1229,11 +1514,20 @@
mt_entry->dpm_entry_num = dpm_idx;
}
}
- /* FIXME Why not mt_entry too? */
et_entry->init_complete = 1;
} else if ((ioc_pg8_flags &
MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+
+ /*
+ * Get the mapping table index for this device. If it's
+ * not in the mapping table yet, find a free entry if
+ * one is available. If there are no free entries, look
+ * for the entry that has the highest missing count. If
+ * none of that works to find an entry in the mapping
+ * table, there is a problem. Log a message and just
+ * continue on.
+ */
map_idx = _mapping_get_mt_idx_from_id
(sc, phy_change->physical_id);
if (map_idx == MPS_MAPTABLE_BAD_IDX) {
@@ -1243,16 +1537,18 @@
map_idx = _mapping_get_free_mt_idx(sc,
search_idx);
}
+
+ /*
+ * If an entry will be used that has a missing device,
+ * clear its entry from the DPM in the controller.
+ */
if (map_idx == MPS_MAPTABLE_BAD_IDX) {
map_idx = _mapping_get_high_missing_mt_idx(sc);
if (map_idx != MPS_MAPTABLE_BAD_IDX) {
mt_entry = &sc->mapping_table[map_idx];
- if (mt_entry->dev_handle) {
- _mapping_add_to_removal_table
- (sc, mt_entry->dev_handle,
- 0);
- is_removed = 1;
- }
+ _mapping_add_to_removal_table(sc,
+ mt_entry->dpm_entry_num);
+ is_removed = 1;
mt_entry->init_complete = 0;
}
}
@@ -1259,7 +1555,6 @@
if (map_idx != MPS_MAPTABLE_BAD_IDX) {
mt_entry = &sc->mapping_table[map_idx];
mt_entry->physical_id = phy_change->physical_id;
- mt_entry->channel = 0;
mt_entry->id = map_idx;
mt_entry->dev_handle = phy_change->dev_handle;
mt_entry->missing_count = 0;
@@ -1267,13 +1562,10 @@
| (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
} else {
phy_change->is_processed = 1;
- if (!sc->mt_full_retry) {
- sc->mt_add_device_failed = 1;
- continue;
- }
- printf("%s: failed to add the device with "
- "handle 0x%04x because there is no free "
- "space available in the mapping table\n",
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
+ "failed to add the device with handle "
+ "0x%04x because there is no free space "
+ "available in the mapping table\n",
__func__, phy_change->dev_handle);
continue;
}
@@ -1291,9 +1583,18 @@
PhysicalIdentifier.High;
temp64_var = (temp64_var << 32) |
dpm_entry->PhysicalIdentifier.Low;
+
+ /*
+ * If the Mapping Table's info is not
+ * the same as the DPM entry, clear the
+ * init_complete flag so that it's
+ * updated.
+ */
if ((mt_entry->physical_id ==
temp64_var) && !missing_cnt)
mt_entry->init_complete = 1;
+ else
+ mt_entry->init_complete = 0;
} else {
dpm_idx = _mapping_get_free_dpm_idx(sc);
mt_entry->init_complete = 0;
@@ -1300,7 +1601,6 @@
}
if (dpm_idx != MPS_DPM_BAD_IDX &&
!mt_entry->init_complete) {
- mt_entry->init_complete = 1;
mt_entry->dpm_entry_num = dpm_idx;
dpm_entry = (Mpi2DriverMap0Entry_t *)
((u8 *)sc->dpm_pg0 + hdr_sz);
@@ -1317,14 +1617,13 @@
sc->dpm_flush_entry[dpm_idx] = 1;
phy_change->is_processed = 1;
} else if (dpm_idx == MPS_DPM_BAD_IDX) {
- phy_change->is_processed = 1;
- printf("%s: failed to add the "
- "device with handle 0x%04x "
- "to persistent table "
- "because there is no free "
- "space available\n",
- __func__,
- phy_change->dev_handle);
+ phy_change->is_processed = 1;
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
+ "%s: failed to add the device with "
+ "handle 0x%04x to persistent table "
+ "because there is no free space "
+ "available\n", __func__,
+ phy_change->dev_handle);
}
}
mt_entry->init_complete = 1;
@@ -1367,10 +1666,13 @@
memcpy(&config_page.Entry, (u8 *)dpm_entry,
sizeof(Mpi2DriverMap0Entry_t));
/* TODO-How to handle failed writes? */
+ mps_dprint(sc, MPS_MAPPING, "%s: Flushing DPM entry %d.\n",
+ __func__, entry_num);
if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
entry_num)) {
- printf("%s: write of dpm entry %d for device failed\n",
- __func__, entry_num);
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Flush of "
+ "DPM entry %d for device failed\n", __func__,
+ entry_num);
} else
sc->dpm_flush_entry[entry_num] = 0;
dpm_entry->MappingInformation = le16toh(dpm_entry->
@@ -1460,7 +1762,6 @@
free(sc->dpm_pg0, M_MPT2);
}
-
static void
_mapping_process_dpm_pg0(struct mps_softc *sc)
{
@@ -1475,9 +1776,20 @@
u64 physical_id;
u32 phy_bits = 0;
+ /*
+ * start_idx and end_idx are only used for IR.
+ */
if (sc->ir_firmware)
_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
+ /*
+ * Look through all of the DPM entries that were read from the
+ * controller and copy them over to the driver's internal table if they
+ * have a non-zero ID. At this point, any ID with a value of 0 would be
+ * invalid, so don't copy it.
+ */
+ mps_dprint(sc, MPS_MAPPING, "%s: Start copy of %d DPM entries into the "
+ "mapping table.\n", __func__, sc->max_dpm_entries);
dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
@@ -1496,13 +1808,20 @@
MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
dev_idx = le16toh(dpm_entry->DeviceIndex);
phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
+
+ /*
+ * Volumes are at special locations in the mapping table so
+ * account for that. Volume mapping table entries do not depend
+ * on the type of mapping, so continue the loop after adding
+ * volumes to the mapping table.
+ */
if (sc->ir_firmware && (dev_idx >= start_idx) &&
(dev_idx <= end_idx)) {
mt_entry = &sc->mapping_table[dev_idx];
- mt_entry->physical_id = dpm_entry->PhysicalIdentifier.High;
+ mt_entry->physical_id =
+ dpm_entry->PhysicalIdentifier.High;
mt_entry->physical_id = (mt_entry->physical_id << 32) |
dpm_entry->PhysicalIdentifier.Low;
- mt_entry->channel = MPS_RAID_CHANNEL;
mt_entry->id = dev_idx;
mt_entry->missing_count = missing_cnt;
mt_entry->dpm_entry_num = entry_num;
@@ -1511,7 +1830,16 @@
}
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
- if (dev_idx < (sc->num_rsvd_entries +
+
+ /*
+ * The dev_idx for an enclosure is the start index. If
+ * the start index is within the controller's default
+ * enclosure area, set the number of slots for this
+ * enclosure to the max allowed. Otherwise, it should be
+ * a normal enclosure and the number of slots is in the
+ * DPM entry's Mapping Information.
+ */
+ if (dev_idx < (sc->num_rsvd_entries +
max_num_phy_ids)) {
slot_id = 0;
if (ioc_pg8_flags &
@@ -1526,8 +1854,9 @@
}
enc_idx = sc->num_enc_table_entries;
if (enc_idx >= sc->max_enclosures) {
- printf("%s: enclosure entries exceed max "
- "enclosures of %d\n", __func__,
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
+ "Number of enclosure entries in DPM exceed "
+ "the max allowed of %d.\n", __func__,
sc->max_enclosures);
break;
}
@@ -1543,21 +1872,32 @@
et_entry->missing_count = missing_cnt;
et_entry->phy_bits = phy_bits;
+ /*
+ * Initialize all entries for this enclosure in the
+ * mapping table and mark them as reserved. The actual
+ * devices have not been processed yet but when they are
+ * they will use these entries. If an entry is found
+ * that already has a valid DPM index, the mapping table
+ * is corrupt. This can happen if the mapping type is
+ * changed without clearing all of the DPM entries in
+ * the controller.
+ */
mt_entry = &sc->mapping_table[dev_idx];
for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
map_idx++, mt_entry++) {
if (mt_entry->dpm_entry_num !=
MPS_DPM_BAD_IDX) {
- printf("%s: conflict in mapping table "
- "for enclosure %d\n", __func__,
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
+ "%s: Conflict in mapping table for "
+ " enclosure %d\n", __func__,
enc_idx);
break;
}
- physical_id = dpm_entry->PhysicalIdentifier.High;
+ physical_id =
+ dpm_entry->PhysicalIdentifier.High;
mt_entry->physical_id = (physical_id << 32) |
dpm_entry->PhysicalIdentifier.Low;
mt_entry->phy_bits = phy_bits;
- mt_entry->channel = 0;
mt_entry->id = dev_idx;
mt_entry->dpm_entry_num = entry_num;
mt_entry->missing_count = missing_cnt;
@@ -1566,11 +1906,18 @@
} else if ((ioc_pg8_flags &
MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+
+ /*
+ * Device mapping, so simply copy the DPM entries to the
+ * mapping table, but check for a corrupt mapping table
+ * (as described above in Enc/Slot mapping).
+ */
map_idx = dev_idx;
mt_entry = &sc->mapping_table[map_idx];
if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
- printf("%s: conflict in mapping table for "
- "device %d\n", __func__, map_idx);
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
+ "Conflict in mapping table for device %d\n",
+ __func__, map_idx);
break;
}
physical_id = dpm_entry->PhysicalIdentifier.High;
@@ -1577,7 +1924,6 @@
mt_entry->physical_id = (physical_id << 32) |
dpm_entry->PhysicalIdentifier.Low;
mt_entry->phy_bits = phy_bits;
- mt_entry->channel = 0;
mt_entry->id = dev_idx;
mt_entry->missing_count = missing_cnt;
mt_entry->dpm_entry_num = entry_num;
@@ -1589,43 +1935,91 @@
/*
* mps_mapping_check_devices - start of the day check for device availabilty
* @sc: per adapter object
- * @sleep_flag: Flag indicating whether this function can sleep or not
*
* Returns nothing.
*/
void
-mps_mapping_check_devices(struct mps_softc *sc, int sleep_flag)
+mps_mapping_check_devices(void *data)
{
u32 i;
-/* u32 cntdn, i;
- u32 timeout = 60;*/
struct dev_mapping_table *mt_entry;
+ struct mps_softc *sc = (struct mps_softc *)data;
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
struct enc_mapping_table *et_entry;
- u32 start_idx, end_idx;
+ u32 start_idx = 0, end_idx = 0;
+ u8 stop_device_checks = 0;
- /* We need to ucomment this when this function is called
- * from the port enable complete */
-#if 0
+ MPS_FUNCTRACE(sc);
+
+ /*
+ * Clear this flag so that this function is never called again except
+ * within this function if the check needs to be done again. The
+ * purpose is to check for missing devices that are currently in the
+ * mapping table so do this only at driver init after discovery.
+ */
sc->track_mapping_events = 0;
- cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
- do {
- if (!sc->pending_map_events)
- break;
- if (sleep_flag == CAN_SLEEP)
- pause("mps_pause", (hz/1000));/* 1msec sleep */
- else
- DELAY(500); /* 500 useconds delay */
- } while (--cntdn);
+ /*
+ * callout synchronization
+ * This is used to prevent race conditions for the callout.
+ */
+ mps_dprint(sc, MPS_MAPPING, "%s: Start check for missing devices.\n",
+ __func__);
+ mtx_assert(&sc->mps_mtx, MA_OWNED);
+ if ((callout_pending(&sc->device_check_callout)) ||
+ (!callout_active(&sc->device_check_callout))) {
+ mps_dprint(sc, MPS_MAPPING, "%s: Device Check Callout is "
+ "already pending or not active.\n", __func__);
+ return;
+ }
+ callout_deactivate(&sc->device_check_callout);
- if (!cntdn)
- printf("%s: there are %d"
- " pending events after %d seconds of delay\n",
- __func__, sc->pending_map_events, timeout);
-#endif
- sc->pending_map_events = 0;
+ /*
+ * Use callout to check if any devices in the mapping table have been
+ * processed yet. If ALL devices are marked as not init_complete, no
+ * devices have been processed and mapped. Until devices are mapped
+ * there's no reason to mark them as missing. Continue resetting this
+ * callout until devices have been mapped.
+ */
+ if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+ MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+ et_entry = sc->enclosure_table;
+ for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
+ if (et_entry->init_complete) {
+ stop_device_checks = 1;
+ break;
+ }
+ }
+ } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+ MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+ mt_entry = sc->mapping_table;
+ for (i = 0; i < sc->max_devices; i++, mt_entry++) {
+ if (mt_entry->init_complete) {
+ stop_device_checks = 1;
+ break;
+ }
+ }
+ }
+ /*
+ * Setup another callout check after a delay. Keep doing this until
+ * devices are mapped.
+ */
+ if (!stop_device_checks) {
+ mps_dprint(sc, MPS_MAPPING, "%s: No devices have been mapped. "
+ "Reset callout to check again after a %d second delay.\n",
+ __func__, MPS_MISSING_CHECK_DELAY);
+ callout_reset(&sc->device_check_callout,
+ MPS_MISSING_CHECK_DELAY * hz, mps_mapping_check_devices,
+ sc);
+ return;
+ }
+ mps_dprint(sc, MPS_MAPPING, "%s: Device check complete.\n", __func__);
+
+ /*
+ * Depending on the mapping type, check if devices have been processed
+ * and update their missing counts if not processed.
+ */
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
et_entry = sc->enclosure_table;
@@ -1633,11 +2027,16 @@
if (!et_entry->init_complete) {
if (et_entry->missing_count <
MPS_MAX_MISSING_COUNT) {
+ mps_dprint(sc, MPS_MAPPING, "%s: "
+ "Enclosure %d is missing from the "
+ "topology. Update its missing "
+ "count.\n", __func__, i);
et_entry->missing_count++;
if (et_entry->dpm_entry_num !=
- MPS_DPM_BAD_IDX)
+ MPS_DPM_BAD_IDX) {
_mapping_commit_enc_entry(sc,
et_entry);
+ }
}
et_entry->init_complete = 1;
}
@@ -1646,70 +2045,46 @@
return;
_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
mt_entry = &sc->mapping_table[start_idx];
- for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
- if (mt_entry->device_info & MPS_DEV_RESERVED
- && !mt_entry->physical_id)
- mt_entry->init_complete = 1;
- else if (mt_entry->device_info & MPS_DEV_RESERVED) {
- if (!mt_entry->init_complete) {
- if (mt_entry->missing_count <
- MPS_MAX_MISSING_COUNT) {
- mt_entry->missing_count++;
- if (mt_entry->dpm_entry_num !=
- MPS_DPM_BAD_IDX)
- _mapping_commit_map_entry(sc,
- mt_entry);
- }
- mt_entry->init_complete = 1;
- }
- }
- }
} else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+ start_idx = 0;
+ end_idx = sc->max_devices - 1;
mt_entry = sc->mapping_table;
- for (i = 0; i < sc->max_devices; i++, mt_entry++) {
- if (mt_entry->device_info & MPS_DEV_RESERVED
- && !mt_entry->physical_id)
- mt_entry->init_complete = 1;
- else if (mt_entry->device_info & MPS_DEV_RESERVED) {
- if (!mt_entry->init_complete) {
- if (mt_entry->missing_count <
- MPS_MAX_MISSING_COUNT) {
- mt_entry->missing_count++;
- if (mt_entry->dpm_entry_num !=
- MPS_DPM_BAD_IDX)
+ }
+
+ /*
+ * The start and end indices have been set above according to the
+ * mapping type. Go through these mappings and update any entries that
+ * do not have the init_complete flag set, which means they are missing.
+ */
+ if (end_idx == 0)
+ return;
+ for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
+ if (mt_entry->device_info & MPS_DEV_RESERVED
+ && !mt_entry->physical_id)
+ mt_entry->init_complete = 1;
+ else if (mt_entry->device_info & MPS_DEV_RESERVED) {
+ if (!mt_entry->init_complete) {
+ mps_dprint(sc, MPS_MAPPING, "%s: Device in "
+ "mapping table at index %d is missing from "
+ "topology. Update its missing count.\n",
+ __func__, i);
+ if (mt_entry->missing_count <
+ MPS_MAX_MISSING_COUNT) {
+ mt_entry->missing_count++;
+ if (mt_entry->dpm_entry_num !=
+ MPS_DPM_BAD_IDX) {
_mapping_commit_map_entry(sc,
mt_entry);
}
- mt_entry->init_complete = 1;
}
+ mt_entry->init_complete = 1;
}
}
}
}
-
/**
- * mps_mapping_is_reinit_required - check whether event replay required
- * @sc: per adapter object
- *
- * Checks the per ioc flags and decide whether reinit of events required
- *
- * Returns 1 for reinit of ioc 0 for not.
- */
-int mps_mapping_is_reinit_required(struct mps_softc *sc)
-{
- if (!sc->mt_full_retry && sc->mt_add_device_failed) {
- sc->mt_full_retry = 1;
- sc->mt_add_device_failed = 0;
- _mapping_flush_dpm_pages(sc);
- return 1;
- }
- sc->mt_full_retry = 1;
- return 0;
-}
-
-/**
* mps_mapping_initialize - initialize mapping tables
* @sc: per adapter object
*
@@ -1737,11 +2112,14 @@
sc->pending_map_events = 0;
sc->num_enc_table_entries = 0;
sc->num_rsvd_entries = 0;
- sc->num_channels = 1;
sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
sc->track_mapping_events = 0;
+
+ mps_dprint(sc, MPS_MAPPING, "%s: Mapping table has a max of %d entries "
+ "and DPM has a max of %d entries.\n", __func__, sc->max_devices,
+ sc->max_dpm_entries);
if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
sc->is_dpm_enable = 0;
@@ -1781,8 +2159,8 @@
retry_read_dpm:
if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
dpm_pg0_sz)) {
- printf("%s: dpm page read failed; disabling dpm\n",
- __func__);
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: DPM page "
+ "read failed.\n", __func__);
if (retry_count < 3) {
retry_count++;
goto retry_read_dpm;
@@ -1793,6 +2171,11 @@
if (sc->is_dpm_enable)
_mapping_process_dpm_pg0(sc);
+ else {
+ mps_dprint(sc, MPS_MAPPING, "%s: DPM processing is disabled. "
+ "Device mappings will not persist across reboots or "
+ "resets.\n", __func__);
+ }
sc->track_mapping_events = 1;
return 0;
@@ -1812,15 +2195,15 @@
}
/**
- * mps_mapping_get_sas_id - assign a target id for sas device
+ * mps_mapping_get_tid - return the target id for sas device and handle
* @sc: per adapter object
* @sas_address: sas address of the device
* @handle: device handle
*
- * Returns valid ID on success or BAD_ID.
+ * Returns valid target ID on success or BAD_ID.
*/
unsigned int
-mps_mapping_get_sas_id(struct mps_softc *sc, uint64_t sas_address, u16 handle)
+mps_mapping_get_tid(struct mps_softc *sc, uint64_t sas_address, u16 handle)
{
u32 map_idx;
struct dev_mapping_table *mt_entry;
@@ -1836,38 +2219,39 @@
}
/**
- * mps_mapping_get_sas_id_from_handle - find a target id in mapping table using
+ * mps_mapping_get_tid_from_handle - find a target id in mapping table using
* only the dev handle. This is just a wrapper function for the local function
* _mapping_get_mt_idx_from_handle.
* @sc: per adapter object
* @handle: device handle
*
- * Returns valid ID on success or BAD_ID.
+ * Returns valid target ID on success or BAD_ID.
*/
unsigned int
-mps_mapping_get_sas_id_from_handle(struct mps_softc *sc, u16 handle)
+mps_mapping_get_tid_from_handle(struct mps_softc *sc, u16 handle)
{
return (_mapping_get_mt_idx_from_handle(sc, handle));
}
/**
- * mps_mapping_get_raid_id - assign a target id for raid device
+ * mps_mapping_get_raid_tid - return the target id for raid device
* @sc: per adapter object
* @wwid: world wide identifier for raid volume
- * @handle: device handle
+ * @volHandle: volume device handle
*
- * Returns valid ID on success or BAD_ID.
+ * Returns valid target ID on success or BAD_ID.
*/
unsigned int
-mps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid, u16 handle)
+mps_mapping_get_raid_tid(struct mps_softc *sc, u64 wwid, u16 volHandle)
{
- u32 map_idx;
+ u32 start_idx, end_idx, map_idx;
struct dev_mapping_table *mt_entry;
- for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
- mt_entry = &sc->mapping_table[map_idx];
- if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
- wwid)
+ _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
+ mt_entry = &sc->mapping_table[start_idx];
+ for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
+ if (mt_entry->dev_handle == volHandle &&
+ mt_entry->physical_id == wwid)
return mt_entry->id;
}
@@ -1875,16 +2259,16 @@
}
/**
- * mps_mapping_get_raid_id_from_handle - find raid device in mapping table
+ * mps_mapping_get_raid_tid_from_handle - find raid device in mapping table
* using only the volume dev handle. This is just a wrapper function for the
* local function _mapping_get_ir_mt_idx_from_handle.
* @sc: per adapter object
* @volHandle: volume device handle
*
- * Returns valid ID on success or BAD_ID.
+ * Returns valid target ID on success or BAD_ID.
*/
unsigned int
-mps_mapping_get_raid_id_from_handle(struct mps_softc *sc, u16 volHandle)
+mps_mapping_get_raid_tid_from_handle(struct mps_softc *sc, u16 volHandle)
{
return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
}
@@ -1918,8 +2302,8 @@
if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
if (!event_data->NumSlots) {
- printf("%s: enclosure with handle = 0x%x reported 0 "
- "slots\n", __func__,
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Enclosure "
+ "with handle = 0x%x reported 0 slots.\n", __func__,
le16toh(event_data->EnclosureHandle));
goto out;
}
@@ -1928,13 +2312,22 @@
event_data->EnclosureLogicalID.Low;
enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
event_data->PhyBits);
+
+ /*
+ * If the Added enclosure is already in the Enclosure Table,
+ * make sure that all the the enclosure info is up to date. If
+ * the enclosure was missing and has just been added back, or if
+ * the enclosure's Phy Bits have changed, clear the missing
+ * count and update the Phy Bits in the mapping table and in the
+ * DPM, if it's being used.
+ */
if (enc_idx != MPS_ENCTABLE_BAD_IDX) {
et_entry = &sc->enclosure_table[enc_idx];
if (et_entry->init_complete &&
!et_entry->missing_count) {
- printf("%s: enclosure %d is already present "
- "with handle = 0x%x\n",__func__, enc_idx,
- et_entry->enc_handle);
+ mps_dprint(sc, MPS_MAPPING, "%s: Enclosure %d "
+ "is already present with handle = 0x%x\n",
+ __func__, enc_idx, et_entry->enc_handle);
goto out;
}
et_entry->enc_handle = le16toh(event_data->
@@ -1953,8 +2346,7 @@
missing_count =
(u8)(dpm_entry->MappingInformation &
MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
- if (!et_entry->init_complete && (
- missing_count || update_phy_bits)) {
+ if (missing_count || update_phy_bits) {
dpm_entry->MappingInformation
= et_entry->num_slots;
dpm_entry->MappingInformation
@@ -1967,10 +2359,18 @@
}
}
} else {
+ /*
+ * This is a new enclosure that is being added.
+ * Initialize the Enclosure Table entry. It will be
+ * finalized when a device is added for the enclosure
+ * and the enclosure has enough space in the Mapping
+ * Table to map its devices.
+ */
enc_idx = sc->num_enc_table_entries;
if (enc_idx >= sc->max_enclosures) {
- printf("%s: enclosure can not be added; "
- "mapping table is full\n", __func__);
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
+ "Enclosure cannot be added to mapping "
+ "table because it's full.\n", __func__);
goto out;
}
sc->num_enc_table_entries++;
@@ -1977,10 +2377,11 @@
et_entry = &sc->enclosure_table[enc_idx];
et_entry->enc_handle = le16toh(event_data->
EnclosureHandle);
- et_entry->enclosure_id = event_data->
- EnclosureLogicalID.High;
- et_entry->enclosure_id = ( et_entry->enclosure_id <<
- 32) | event_data->EnclosureLogicalID.Low;
+ et_entry->enclosure_id = le64toh(event_data->
+ EnclosureLogicalID.High);
+ et_entry->enclosure_id =
+ ((et_entry->enclosure_id << 32) |
+ le64toh(event_data->EnclosureLogicalID.Low));
et_entry->start_index = MPS_MAPTABLE_BAD_IDX;
et_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
et_entry->num_slots = le16toh(event_data->NumSlots);
@@ -1990,23 +2391,23 @@
et_entry->init_complete = 1;
} else if (event_data->ReasonCode ==
MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
+ /*
+ * An enclosure was removed. Update its missing count and then
+ * update the DPM entry with the new missing count for the
+ * enclosure.
+ */
enc_idx = _mapping_get_enc_idx_from_handle(sc,
le16toh(event_data->EnclosureHandle));
if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
- printf("%s: cannot unmap enclosure %d because it has "
- "already been deleted", __func__, enc_idx);
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Cannot "
+ "unmap enclosure %d because it has already been "
+ "deleted.\n", __func__, enc_idx);
goto out;
}
et_entry = &sc->enclosure_table[enc_idx];
- if (!et_entry->init_complete) {
- if (et_entry->missing_count < MPS_MAX_MISSING_COUNT)
- et_entry->missing_count++;
- else
- et_entry->init_complete = 1;
- }
- if (!et_entry->missing_count)
+ if (et_entry->missing_count < MPS_MAX_MISSING_COUNT)
et_entry->missing_count++;
- if (sc->is_dpm_enable && !et_entry->init_complete &&
+ if (sc->is_dpm_enable &&
et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
dpm_entry += et_entry->dpm_entry_num;
dpm_entry->MappingInformation = et_entry->num_slots;
@@ -2076,66 +2477,6 @@
}
/**
- * _mapping_check_update_ir_mt_idx - Check and update IR map table index
- * @sc: per adapter object
- * @event_data: event data payload
- * @evt_idx: current event index
- * @map_idx: current index and the place holder for new map table index
- * @wwid_table: world wide name for volumes in the element table
- *
- * pass through IR events and find whether any events matches and if so
- * tries to find new index if not returns failure
- *
- * Returns 0 on success and 1 on failure
- */
-static int
-_mapping_check_update_ir_mt_idx(struct mps_softc *sc,
- Mpi2EventDataIrConfigChangeList_t *event_data, int evt_idx, u32 *map_idx,
- u64 *wwid_table)
-{
- struct dev_mapping_table *mt_entry;
- u32 st_idx, end_idx, mt_idx = *map_idx;
- u8 match = 0;
- Mpi2EventIrConfigElement_t *element;
- u16 element_flags;
- int i;
-
- mt_entry = &sc->mapping_table[mt_idx];
- _mapping_get_ir_maprange(sc, &st_idx, &end_idx);
-search_again:
- match = 0;
- for (i = evt_idx + 1; i < event_data->NumElements; i++) {
- element = (Mpi2EventIrConfigElement_t *)
- &event_data->ConfigElement[i];
- element_flags = le16toh(element->ElementFlags);
- if ((element_flags &
- MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) !=
- MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT)
- continue;
- if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_ADDED ||
- element->ReasonCode ==
- MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
- if (mt_entry->physical_id == wwid_table[i]) {
- match = 1;
- break;
- }
- }
- }
-
- if (match) {
- do {
- mt_idx++;
- if (mt_idx > end_idx)
- return 1;
- mt_entry = &sc->mapping_table[mt_idx];
- } while (mt_entry->device_info & MPS_MAP_IN_USE);
- goto search_again;
- }
- *map_idx = mt_idx;
- return 0;
-}
-
-/**
* mps_mapping_ir_config_change_event - handle IR config change list events
* @sc: per adapter object
* @event_data: event data payload
@@ -2152,7 +2493,6 @@
u32 map_idx, flags;
struct dev_mapping_table *mt_entry;
u16 element_flags;
- u8 log_full_error = 0;
wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPT2,
M_NOWAIT | M_ZERO);
@@ -2160,6 +2500,11 @@
goto out;
element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
flags = le32toh(event_data->Flags);
+
+ /*
+ * For volume changes, get the WWID for the volume and put it in a
+ * table to be used in the processing of the IR change event.
+ */
for (i = 0; i < event_data->NumElements; i++, element++) {
element_flags = le16toh(element->ElementFlags);
if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
@@ -2173,14 +2518,14 @@
MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
mps_config_get_volume_wwid(sc,
le16toh(element->VolDevHandle), &wwid_table[i]);
- map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
- wwid_table[i]);
- if (map_idx != MPS_MAPTABLE_BAD_IDX) {
- mt_entry = &sc->mapping_table[map_idx];
- mt_entry->device_info |= MPS_MAP_IN_USE;
- }
}
}
+
+ /*
+ * Check the ReasonCode for each element in the IR event and Add/Remove
+ * Volumes or Physical Disks of Volumes to/from the mapping table. Use
+ * the WWIDs gotten above in wwid_table.
+ */
if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
goto out;
else {
@@ -2194,8 +2539,11 @@
map_idx = _mapping_get_ir_mt_idx_from_wwid
(sc, wwid_table[i]);
if (map_idx != MPS_MAPTABLE_BAD_IDX) {
+ /*
+ * The volume is already in the mapping
+ * table. Just update it's info.
+ */
mt_entry = &sc->mapping_table[map_idx];
- mt_entry->channel = MPS_RAID_CHANNEL;
mt_entry->id = map_idx;
mt_entry->dev_handle = le16toh
(element->VolDevHandle);
@@ -2205,31 +2553,33 @@
map_idx, element, wwid_table[i]);
continue;
}
+
+ /*
+ * Volume is not in mapping table yet. Find a
+ * free entry in the mapping table at the
+ * volume mapping locations. If no entries are
+ * available, this is an error because it means
+ * there are more volumes than can be mapped
+ * and that should never happen for volumes.
+ */
map_idx = _mapping_get_free_ir_mt_idx(sc);
if (map_idx == MPS_MAPTABLE_BAD_IDX)
- log_full_error = 1;
- else if (i < (event_data->NumElements - 1)) {
- log_full_error =
- _mapping_check_update_ir_mt_idx
- (sc, event_data, i, &map_idx,
- wwid_table);
- }
- if (log_full_error) {
- printf("%s: no space to add the RAID "
- "volume with handle 0x%04x in "
- "mapping table\n", __func__, le16toh
- (element->VolDevHandle));
+ {
+ mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
+ "%s: failed to add the volume with "
+ "handle 0x%04x because there is no "
+ "free space available in the "
+ "mapping table\n", __func__,
+ le16toh(element->VolDevHandle));
continue;
}
mt_entry = &sc->mapping_table[map_idx];
mt_entry->physical_id = wwid_table[i];
- mt_entry->channel = MPS_RAID_CHANNEL;
mt_entry->id = map_idx;
mt_entry->dev_handle = le16toh(element->
VolDevHandle);
mt_entry->device_info = MPS_DEV_RESERVED |
MPS_MAP_IN_USE;
- mt_entry->init_complete = 0;
_mapping_update_ir_missing_cnt(sc, map_idx,
element, wwid_table[i]);
} else if (element->ReasonCode ==
@@ -2237,9 +2587,10 @@
map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
wwid_table[i]);
if (map_idx == MPS_MAPTABLE_BAD_IDX) {
- printf("%s: failed to remove a volume "
- "because it has already been "
- "removed\n", __func__);
+ mps_dprint(sc, MPS_MAPPING,"%s: Failed "
+ "to remove a volume because it has "
+ "already been removed.\n",
+ __func__);
continue;
}
_mapping_update_ir_missing_cnt(sc, map_idx,
@@ -2249,9 +2600,10 @@
map_idx = _mapping_get_mt_idx_from_handle(sc,
le16toh(element->VolDevHandle));
if (map_idx == MPS_MAPTABLE_BAD_IDX) {
- printf("%s: failed to remove volume "
- "with handle 0x%04x because it has "
- "already been removed\n", __func__,
+ mps_dprint(sc, MPS_MAPPING,"%s: Failed "
+ "to remove volume with handle "
+ "0x%04x because it has already "
+ "been removed.\n", __func__,
le16toh(element->VolDevHandle));
continue;
}
@@ -2268,3 +2620,61 @@
if (sc->pending_map_events)
sc->pending_map_events--;
}
+
+int
+mps_mapping_dump(SYSCTL_HANDLER_ARGS)
+{
+ struct mps_softc *sc;
+ struct dev_mapping_table *mt_entry;
+ struct sbuf sbuf;
+ int i, error;
+
+ sc = (struct mps_softc *)arg1;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
+ sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
+
+ sbuf_printf(&sbuf, "\nindex physical_id handle id\n");
+ for (i = 0; i < sc->max_devices; i++) {
+ mt_entry = &sc->mapping_table[i];
+ if (mt_entry->physical_id == 0)
+ continue;
+ sbuf_printf(&sbuf, "%4d %jx %04x %hd\n",
+ i, mt_entry->physical_id, mt_entry->dev_handle,
+ mt_entry->id);
+ }
+ error = sbuf_finish(&sbuf);
+ sbuf_delete(&sbuf);
+ return (error);
+}
+
+int
+mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS)
+{
+ struct mps_softc *sc;
+ struct enc_mapping_table *enc_entry;
+ struct sbuf sbuf;
+ int i, error;
+
+ sc = (struct mps_softc *)arg1;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
+ sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
+
+ sbuf_printf(&sbuf, "\nindex enclosure_id handle map_index\n");
+ for (i = 0; i < sc->max_enclosures; i++) {
+ enc_entry = &sc->enclosure_table[i];
+ if (enc_entry->enclosure_id == 0)
+ continue;
+ sbuf_printf(&sbuf, "%4d %jx %04x %d\n",
+ i, enc_entry->enclosure_id, enc_entry->enc_handle,
+ enc_entry->start_index);
+ }
+ error = sbuf_finish(&sbuf);
+ sbuf_delete(&sbuf);
+ return (error);
+}
Modified: trunk/sys/dev/mps/mps_mapping.h
===================================================================
--- trunk/sys/dev/mps/mps_mapping.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_mapping.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,9 +25,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mps_mapping.h 281564 2015-04-15 21:47:15Z slm $
*/
#ifndef _MPS_MAPPING_H
@@ -38,6 +40,7 @@
* @dev_handle: device handle for the device pointed by this entry
* @slot: slot ID
* @is_processed: Flag to indicate whether this entry is processed or not
+ * @is_SATA_SSD: 1 if this is a SATA device AND an SSD, 0 otherwise
*/
struct _map_phy_change {
uint64_t physical_id;
@@ -46,6 +49,8 @@
uint16_t slot;
uint8_t reason;
uint8_t is_processed;
+ uint8_t is_SATA_SSD;
+ uint8_t reserved;
};
/**
@@ -66,6 +71,6 @@
extern int
mpssas_get_sas_address_for_sata_disk(struct mps_softc *ioc,
- u64 *sas_address, u16 handle, u32 device_info);
+ u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
#endif
Modified: trunk/sys/dev/mps/mps_pci.c
===================================================================
--- trunk/sys/dev/mps/mps_pci.c 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_pci.c 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009 Yahoo! Inc.
* All rights reserved.
@@ -25,9 +26,9 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/mps/mps_pci.c 322661 2017-08-18 15:38:08Z ken $");
-/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */
+/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT2 controllers */
/* TODO Move headers to mpsvar */
#include <sys/types.h>
@@ -68,6 +69,7 @@
static void mps_pci_free(struct mps_softc *);
static int mps_alloc_msix(struct mps_softc *sc, int msgs);
static int mps_alloc_msi(struct mps_softc *sc, int msgs);
+static int mps_pci_alloc_interrupts(struct mps_softc *sc);
static device_method_t mps_methods[] = {
DEVMETHOD(device_probe, mps_pci_probe),
@@ -98,33 +100,33 @@
const char *desc;
} mps_identifiers[] = {
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
- 0xffff, 0xffff, 0, "LSI SAS2004" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2004" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
- 0xffff, 0xffff, 0, "LSI SAS2008" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2008" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
- 0xffff, 0xffff, 0, "LSI SAS2108" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
- 0xffff, 0xffff, 0, "LSI SAS2108" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
- 0xffff, 0xffff, 0, "LSI SAS2108" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
- 0xffff, 0xffff, 0, "LSI SAS2116" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2116" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
- 0xffff, 0xffff, 0, "LSI SAS2116" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2116" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
- 0xffff, 0xffff, 0, "LSI SAS2208" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
- 0xffff, 0xffff, 0, "LSI SAS2208" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
- 0xffff, 0xffff, 0, "LSI SAS2208" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
- 0xffff, 0xffff, 0, "LSI SAS2208" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
- 0xffff, 0xffff, 0, "LSI SAS2208" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
- 0xffff, 0xffff, 0, "LSI SAS2208" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
- 0xffff, 0xffff, 0, "LSI SAS2308" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" },
// Add Customer specific vender/subdevice id before generic
// (0xffff) vender/subdevice id.
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
@@ -136,11 +138,11 @@
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
0x8086, 0x3519, 0, "Intel(R) Integrated RAID Module RMS25KB040" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
- 0xffff, 0xffff, 0, "LSI SAS2308" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
- 0xffff, 0xffff, 0, "LSI SAS2308" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
- 0xffff, 0xffff, MPS_FLAGS_WD_AVAILABLE, "LSI SSS6200" },
+ 0xffff, 0xffff, 0, "Avago Technologies (LSI) SSS6200" },
{ 0, 0, 0, 0, 0, NULL }
};
@@ -183,7 +185,6 @@
{
struct mps_softc *sc;
struct mps_ident *m;
- uint16_t command;
int error;
sc = device_get_softc(dev);
@@ -192,25 +193,16 @@
m = mps_find_ident(dev);
sc->mps_flags = m->flags;
+ mps_get_tunables(sc);
+
/* Twiddle basic PCI config bits for a sanity check */
- command = pci_read_config(dev, PCIR_COMMAND, 2);
- command |= PCIM_CMD_BUSMASTEREN;
- pci_write_config(dev, PCIR_COMMAND, command, 2);
- command = pci_read_config(dev, PCIR_COMMAND, 2);
- if ((command & PCIM_CMD_BUSMASTEREN) == 0) {
- device_printf(dev, "Cannot enable PCI busmaster\n");
- return (ENXIO);
- }
- if ((command & PCIM_CMD_MEMEN) == 0) {
- device_printf(dev, "PCI memory window not available\n");
- return (ENXIO);
- }
+ pci_enable_busmaster(dev);
/* Allocate the System Interface Register Set */
sc->mps_regs_rid = PCIR_BAR(1);
if ((sc->mps_regs_resource = bus_alloc_resource_any(dev,
SYS_RES_MEMORY, &sc->mps_regs_rid, RF_ACTIVE)) == NULL) {
- device_printf(dev, "Cannot allocate PCI registers\n");
+ mps_printf(sc, "Cannot allocate PCI registers\n");
return (ENXIO);
}
sc->mps_btag = rman_get_bustag(sc->mps_regs_resource);
@@ -228,25 +220,34 @@
0, /* flags */
NULL, NULL, /* lockfunc, lockarg */
&sc->mps_parent_dmat)) {
- device_printf(dev, "Cannot allocate parent DMA tag\n");
+ mps_printf(sc, "Cannot allocate parent DMA tag\n");
mps_pci_free(sc);
return (ENOMEM);
}
- if ((error = mps_attach(sc)) != 0)
+ if (((error = mps_pci_alloc_interrupts(sc)) != 0) ||
+ ((error = mps_attach(sc)) != 0))
mps_pci_free(sc);
return (error);
}
-int
-mps_pci_setup_interrupts(struct mps_softc *sc)
+/*
+ * Allocate, but don't assign interrupts early. Doing it before requesting
+ * the IOCFacts message informs the firmware that we want to do MSI-X
+ * multiqueue. We might not use all of the available messages, but there's
+ * no reason to re-alloc if we don't.
+ */
+static int
+mps_pci_alloc_interrupts(struct mps_softc *sc)
{
device_t dev;
- int i, error, msgs;
+ int error, msgs;
dev = sc->mps_dev;
- error = ENXIO;
+ error = 0;
+ msgs = 0;
+
if ((sc->disable_msix == 0) &&
((msgs = pci_msix_count(dev)) >= MPS_MSI_COUNT))
error = mps_alloc_msix(sc, MPS_MSI_COUNT);
@@ -253,14 +254,29 @@
if ((error != 0) && (sc->disable_msi == 0) &&
((msgs = pci_msi_count(dev)) >= MPS_MSI_COUNT))
error = mps_alloc_msi(sc, MPS_MSI_COUNT);
+ if (error != 0)
+ msgs = 0;
- if (error != 0) {
+ sc->msi_msgs = msgs;
+ return (error);
+}
+
+int
+mps_pci_setup_interrupts(struct mps_softc *sc)
+{
+ device_t dev;
+ int i, error;
+
+ dev = sc->mps_dev;
+ error = ENXIO;
+
+ if (sc->msi_msgs == 0) {
sc->mps_flags |= MPS_FLAGS_INTX;
sc->mps_irq_rid[0] = 0;
sc->mps_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->mps_irq_rid[0], RF_SHAREABLE | RF_ACTIVE);
if (sc->mps_irq[0] == NULL) {
- device_printf(dev, "Cannot allocate INTx interrupt\n");
+ mps_printf(sc, "Cannot allocate INTx interrupt\n");
return (ENXIO);
}
error = bus_setup_intr(dev, sc->mps_irq[0],
@@ -267,7 +283,7 @@
INTR_TYPE_BIO | INTR_MPSAFE, NULL, mps_intr, sc,
&sc->mps_intrhand[0]);
if (error)
- device_printf(dev, "Cannot setup INTx interrupt\n");
+ mps_printf(sc, "Cannot setup INTx interrupt\n");
} else {
sc->mps_flags |= MPS_FLAGS_MSI;
for (i = 0; i < MPS_MSI_COUNT; i++) {
@@ -275,7 +291,7 @@
sc->mps_irq[i] = bus_alloc_resource_any(dev,
SYS_RES_IRQ, &sc->mps_irq_rid[i], RF_ACTIVE);
if (sc->mps_irq[i] == NULL) {
- device_printf(dev,
+ mps_printf(sc,
"Cannot allocate MSI interrupt\n");
return (ENXIO);
}
@@ -283,7 +299,7 @@
INTR_TYPE_BIO | INTR_MPSAFE, NULL, mps_intr_msi,
sc, &sc->mps_intrhand[i]);
if (error) {
- device_printf(dev,
+ mps_printf(sc,
"Cannot setup MSI interrupt %d\n", i);
break;
}
Modified: trunk/sys/dev/mps/mps_sas.c
===================================================================
--- trunk/sys/dev/mps/mps_sas.c 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_sas.c 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,6 +1,8 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009 Yahoo! Inc.
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,15 +26,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mps_sas.c 322661 2017-08-18 15:38:08Z ken $
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/mps/mps_sas.c 322661 2017-08-18 15:38:08Z ken $");
-/* Communications core for LSI MPT2 */
+/* Communications core for Avago Technologies (LSI) MPT2 */
/* TODO Move headers to mpsvar */
#include <sys/types.h>
@@ -115,11 +117,12 @@
MALLOC_DEFINE(M_MPSSAS, "MPSSAS", "MPS SAS memory");
-static void mpssas_discovery_timeout(void *data);
static void mpssas_remove_device(struct mps_softc *, struct mps_command *);
static void mpssas_remove_complete(struct mps_softc *, struct mps_command *);
static void mpssas_action(struct cam_sim *sim, union ccb *ccb);
static void mpssas_poll(struct cam_sim *sim);
+static int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm,
+ struct mps_command *cm);
static void mpssas_scsiio_timeout(void *data);
static void mpssas_abort_complete(struct mps_softc *sc, struct mps_command *cm);
static void mpssas_direct_drive_io(struct mpssas_softc *sassc,
@@ -134,16 +137,12 @@
static void mpssas_action_smpio(struct mpssas_softc *sassc, union ccb *ccb);
#endif //FreeBSD_version >= 900026
static void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *);
-static int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm);
-static int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type);
-static void mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb);
-static void mpssas_rescan_done(struct cam_periph *periph, union ccb *done_ccb);
-static void mpssas_scanner_thread(void *arg);
-#if __FreeBSD_version >= 1000006
static void mpssas_async(void *callback_arg, uint32_t code,
struct cam_path *path, void *arg);
-#else
-static void mpssas_check_eedp(struct mpssas_softc *sassc);
+#if (__FreeBSD_version < 901503) || \
+ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006))
+static void mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path,
+ struct ccb_getdev *cgd);
static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb);
#endif
static int mpssas_send_portenable(struct mps_softc *sc);
@@ -156,7 +155,7 @@
struct mpssas_target *target;
int i;
- for (i = start; i < sassc->sc->facts->MaxTargets; i++) {
+ for (i = start; i < sassc->maxtargets; i++) {
target = &sassc->targets[i];
if (target->handle == handle)
return (target);
@@ -175,38 +174,59 @@
void
mpssas_startup_increment(struct mpssas_softc *sassc)
{
+ MPS_FUNCTRACE(sassc->sc);
+
if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) {
if (sassc->startup_refcount++ == 0) {
/* just starting, freeze the simq */
- mps_dprint(sassc->sc, MPS_INFO,
+ mps_dprint(sassc->sc, MPS_INIT,
"%s freezing simq\n", __func__);
+#if __FreeBSD_version >= 1000039
+ xpt_hold_boot();
+#endif
xpt_freeze_simq(sassc->sim, 1);
}
- mps_dprint(sassc->sc, MPS_TRACE, "%s refcount %u\n", __func__,
+ mps_dprint(sassc->sc, MPS_INIT, "%s refcount %u\n", __func__,
sassc->startup_refcount);
}
}
void
+mpssas_release_simq_reinit(struct mpssas_softc *sassc)
+{
+ if (sassc->flags & MPSSAS_QUEUE_FROZEN) {
+ sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
+ xpt_release_simq(sassc->sim, 1);
+ mps_dprint(sassc->sc, MPS_INFO, "Unfreezing SIM queue\n");
+ }
+}
+
+void
mpssas_startup_decrement(struct mpssas_softc *sassc)
{
+ MPS_FUNCTRACE(sassc->sc);
+
if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) {
if (--sassc->startup_refcount == 0) {
/* finished all discovery-related actions, release
* the simq and rescan for the latest topology.
*/
- mps_dprint(sassc->sc, MPS_INFO,
+ mps_dprint(sassc->sc, MPS_INIT,
"%s releasing simq\n", __func__);
sassc->flags &= ~MPSSAS_IN_STARTUP;
xpt_release_simq(sassc->sim, 1);
+#if __FreeBSD_version >= 1000039
+ xpt_release_boot();
+#else
mpssas_rescan_target(sassc->sc, NULL);
+#endif
}
- mps_dprint(sassc->sc, MPS_TRACE, "%s refcount %u\n", __func__,
+ mps_dprint(sassc->sc, MPS_INIT, "%s refcount %u\n", __func__,
sassc->startup_refcount);
}
}
-/* LSI's firmware requires us to stop sending commands when we're doing task
+/* The firmware requires us to stop sending commands when we're doing task
* management, so refcount the TMs and keep the simq frozen when any are in
* use.
*/
@@ -216,14 +236,6 @@
struct mps_command *tm;
tm = mps_alloc_high_priority_command(sc);
- if (tm != NULL) {
- if (sc->sassc->tm_count++ == 0) {
- mps_printf(sc, "%s freezing simq\n", __func__);
- xpt_freeze_simq(sc->sassc->sim, 1);
- }
- mps_dprint(sc, MPS_TRACE, "%s tm_count %u\n", __func__,
- sc->sassc->tm_count);
- }
return tm;
}
@@ -230,24 +242,31 @@
void
mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm)
{
+ int target_id = 0xFFFFFFFF;
+
if (tm == NULL)
return;
- /* if there are no TMs in use, we can release the simq. We use our
- * own refcount so that it's easier for a diag reset to cleanup and
- * release the simq.
+ /*
+ * For TM's the devq is frozen for the device. Unfreeze it here and
+ * free the resources used for freezing the devq. Must clear the
+ * INRESET flag as well or scsi I/O will not work.
*/
- if (--sc->sassc->tm_count == 0) {
- mps_printf(sc, "%s releasing simq\n", __func__);
- xpt_release_simq(sc->sassc->sim, 1);
+ if (tm->cm_targ != NULL) {
+ tm->cm_targ->flags &= ~MPSSAS_TARGET_INRESET;
+ target_id = tm->cm_targ->tid;
}
- mps_dprint(sc, MPS_TRACE, "%s tm_count %u\n", __func__,
- sc->sassc->tm_count);
+ if (tm->cm_ccb) {
+ mps_dprint(sc, MPS_INFO, "Unfreezing devq for target ID %d\n",
+ target_id);
+ xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE);
+ xpt_free_path(tm->cm_ccb->ccb_h.path);
+ xpt_free_ccb(tm->cm_ccb);
+ }
mps_free_high_priority_command(sc, tm);
}
-
void
mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ)
{
@@ -256,6 +275,7 @@
target_id_t targetid;
union ccb *ccb;
+ MPS_FUNCTRACE(sc);
pathid = cam_sim_path(sassc->sim);
if (targ == NULL)
targetid = CAM_TARGET_WILDCARD;
@@ -267,13 +287,13 @@
*/
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
- mps_dprint(sc, MPS_FAULT, "unable to alloc CCB for rescan\n");
+ mps_dprint(sc, MPS_ERROR, "unable to alloc CCB for rescan\n");
return;
}
- if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid,
- targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- mps_dprint(sc, MPS_FAULT, "unable to create path for rescan\n");
+ if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid,
+ targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ mps_dprint(sc, MPS_ERROR, "unable to create path for rescan\n");
xpt_free_ccb(ccb);
return;
}
@@ -284,11 +304,11 @@
ccb->ccb_h.func_code = XPT_SCAN_TGT;
mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid);
- mpssas_rescan(sassc, ccb);
+ xpt_rescan(ccb);
}
static void
-mpssas_log_command(struct mps_command *cm, const char *fmt, ...)
+mpssas_log_command(struct mps_command *cm, u_int level, const char *fmt, ...)
{
struct sbuf sb;
va_list ap;
@@ -298,6 +318,10 @@
if (cm == NULL)
return;
+ /* No need to be in here if debugging isn't enabled */
+ if ((cm->cm_sc->mps_debug & level) == 0)
+ return;
+
sbuf_new(&sb, str, sizeof(str), 0);
va_start(ap, fmt);
@@ -324,7 +348,7 @@
sbuf_printf(&sb, "SMID %u ", cm->cm_desc.Default.SMID);
sbuf_vprintf(&sb, fmt, ap);
sbuf_finish(&sb);
- printf("%s", sbuf_data(&sb));
+ mps_print_field(cm->cm_sc, "%s", sbuf_data(&sb));
va_end(ap);
}
@@ -337,7 +361,7 @@
struct mpssas_target *targ;
uint16_t handle;
- mps_dprint(sc, MPS_INFO, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
@@ -345,24 +369,27 @@
if (reply == NULL) {
/* XXX retry the remove after the diag reset completes? */
- mps_printf(sc, "%s NULL reply reseting device 0x%04x\n",
- __func__, handle);
+ mps_dprint(sc, MPS_FAULT,
+ "%s NULL reply resetting device 0x%04x\n", __func__,
+ handle);
mpssas_free_tm(sc, tm);
return;
}
- if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) {
- mps_printf(sc, "IOCStatus = 0x%x while resetting device 0x%x\n",
- reply->IOCStatus, handle);
- mpssas_free_tm(sc, tm);
- return;
+ if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
+ MPI2_IOCSTATUS_SUCCESS) {
+ mps_dprint(sc, MPS_ERROR,
+ "IOCStatus = 0x%x while resetting device 0x%x\n",
+ le16toh(reply->IOCStatus), handle);
}
- mps_printf(sc, "Reset aborted %u commands\n", reply->TerminationCount);
+ mps_dprint(sc, MPS_XINFO,
+ "Reset aborted %u commands\n", reply->TerminationCount);
mps_free_reply(sc, tm->cm_reply_data);
tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */
- mps_printf(sc, "clearing target %u handle 0x%04x\n", targ->tid, handle);
+ mps_dprint(sc, MPS_XINFO,
+ "clearing target %u handle 0x%04x\n", targ->tid, handle);
/*
* Don't clear target if remove fails because things will get confusing.
@@ -370,7 +397,8 @@
* this target id if possible, and so we can assign the same target id
* to this device if it comes back in the future.
*/
- if (reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) {
+ if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) ==
+ MPI2_IOCSTATUS_SUCCESS) {
targ = tm->cm_targ;
targ->handle = 0x0;
targ->encl_handle = 0x0;
@@ -398,7 +426,7 @@
struct mps_command *cm;
struct mpssas_target *targ = NULL;
- mps_dprint(sassc->sc, MPS_INFO, "%s\n", __func__);
+ MPS_FUNCTRACE(sassc->sc);
sc = sassc->sc;
#ifdef WD_SUPPORT
@@ -417,7 +445,8 @@
if (targ == NULL) {
/* FIXME: what is the action? */
/* We don't know about this device? */
- printf("%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle);
+ mps_dprint(sc, MPS_ERROR,
+ "%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle);
return;
}
@@ -425,7 +454,8 @@
cm = mpssas_alloc_tm(sc);
if (cm == NULL) {
- mps_printf(sc, "%s: command alloc failure\n", __func__);
+ mps_dprint(sc, MPS_ERROR,
+ "%s: command alloc failure\n", __func__);
return;
}
@@ -445,6 +475,11 @@
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
cm->cm_complete = mpssas_remove_volume;
cm->cm_complete_data = (void *)(uintptr_t)handle;
+
+ mps_dprint(sc, MPS_INFO, "%s: Sending reset for target ID %d\n",
+ __func__, targ->tid);
+ mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
+
mps_map_command(sc, cm);
}
@@ -465,7 +500,7 @@
struct mps_command *cm;
struct mpssas_target *targ = NULL;
- mps_dprint(sassc->sc, MPS_INFO, "%s\n", __func__);
+ MPS_FUNCTRACE(sassc->sc);
sc = sassc->sc;
@@ -473,7 +508,8 @@
if (targ == NULL) {
/* FIXME: what is the action? */
/* We don't know about this device? */
- printf("%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle);
+ mps_dprint(sc, MPS_ERROR,
+ "%s : invalid handle 0x%x \n", __func__, handle);
return;
}
@@ -481,7 +517,8 @@
cm = mpssas_alloc_tm(sc);
if (cm == NULL) {
- mps_printf(sc, "%s: command alloc failure\n", __func__);
+ mps_dprint(sc, MPS_ERROR,
+ "%s: command alloc failure\n", __func__);
return;
}
@@ -501,6 +538,11 @@
cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
cm->cm_complete = mpssas_remove_device;
cm->cm_complete_data = (void *)(uintptr_t)handle;
+
+ mps_dprint(sc, MPS_INFO, "%s: Sending reset for target ID %d\n",
+ __func__, targ->tid);
+ mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
+
mps_map_command(sc, cm);
}
@@ -513,7 +555,7 @@
struct mps_command *next_cm;
uint16_t handle;
- mps_dprint(sc, MPS_INFO, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
@@ -525,29 +567,29 @@
* task management commands don't have S/G lists.
*/
if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
- mps_printf(sc, "%s: cm_flags = %#x for remove of handle %#04x! "
- "This should not happen!\n", __func__, tm->cm_flags,
- handle);
- mpssas_free_tm(sc, tm);
- return;
+ mps_dprint(sc, MPS_ERROR,
+ "%s: cm_flags = %#x for remove of handle %#04x! "
+ "This should not happen!\n", __func__, tm->cm_flags,
+ handle);
}
if (reply == NULL) {
/* XXX retry the remove after the diag reset completes? */
- mps_printf(sc, "%s NULL reply reseting device 0x%04x\n",
- __func__, handle);
+ mps_dprint(sc, MPS_FAULT,
+ "%s NULL reply resetting device 0x%04x\n", __func__,
+ handle);
mpssas_free_tm(sc, tm);
return;
}
- if (le16toh(reply->IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
- mps_printf(sc, "IOCStatus = 0x%x while resetting device 0x%x\n",
+ if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
+ MPI2_IOCSTATUS_SUCCESS) {
+ mps_dprint(sc, MPS_ERROR,
+ "IOCStatus = 0x%x while resetting device 0x%x\n",
le16toh(reply->IOCStatus), handle);
- mpssas_free_tm(sc, tm);
- return;
}
- mps_dprint(sc, MPS_INFO, "Reset aborted %u commands\n",
+ mps_dprint(sc, MPS_XINFO, "Reset aborted %u commands\n",
le32toh(reply->TerminationCount));
mps_free_reply(sc, tm->cm_reply_data);
tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */
@@ -565,14 +607,14 @@
mps_map_command(sc, tm);
- mps_dprint(sc, MPS_INFO, "clearing target %u handle 0x%04x\n",
+ mps_dprint(sc, MPS_XINFO, "clearing target %u handle 0x%04x\n",
targ->tid, handle);
TAILQ_FOREACH_SAFE(tm, &targ->commands, cm_link, next_cm) {
union ccb *ccb;
- mps_dprint(sc, MPS_INFO, "Completing missed command %p\n", tm);
+ mps_dprint(sc, MPS_XINFO, "Completing missed command %p\n", tm);
ccb = tm->cm_complete_data;
- ccb->ccb_h.status = CAM_DEV_NOT_THERE;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
mpssas_scsiio_complete(sc, tm);
}
}
@@ -585,7 +627,7 @@
struct mpssas_target *targ;
struct mpssas_lun *lun;
- mps_dprint(sc, MPS_INFO, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply;
handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
@@ -596,7 +638,8 @@
* task management commands don't have S/G lists.
*/
if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
- mps_printf(sc, "%s: cm_flags = %#x for remove of handle %#04x! "
+ mps_dprint(sc, MPS_XINFO,
+ "%s: cm_flags = %#x for remove of handle %#04x! "
"This should not happen!\n", __func__, tm->cm_flags,
handle);
mpssas_free_tm(sc, tm);
@@ -605,13 +648,14 @@
if (reply == NULL) {
/* most likely a chip reset */
- mps_printf(sc, "%s NULL reply removing device 0x%04x\n",
- __func__, handle);
+ mps_dprint(sc, MPS_FAULT,
+ "%s NULL reply removing device 0x%04x\n", __func__, handle);
mpssas_free_tm(sc, tm);
return;
}
- mps_printf(sc, "%s on handle 0x%04x, IOCStatus= 0x%x\n", __func__,
+ mps_dprint(sc, MPS_XINFO,
+ "%s on handle 0x%04x, IOCStatus= 0x%x\n", __func__,
handle, le16toh(reply->IOCStatus));
/*
@@ -620,7 +664,8 @@
* this target id if possible, and so we can assign the same target id
* to this device if it comes back in the future.
*/
- if (le16toh(reply->IOCStatus) == MPI2_IOCSTATUS_SUCCESS) {
+ if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) ==
+ MPI2_IOCSTATUS_SUCCESS) {
targ = tm->cm_targ;
targ->handle = 0x0;
targ->encl_handle = 0x0;
@@ -671,12 +716,10 @@
mps_attach_sas(struct mps_softc *sc)
{
struct mpssas_softc *sassc;
-#if __FreeBSD_version >= 1000006
cam_status status;
-#endif
int unit, error = 0;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
sassc = malloc(sizeof(struct mpssas_softc), M_MPT2, M_WAITOK|M_ZERO);
if(!sassc) {
@@ -684,8 +727,16 @@
__func__, __LINE__);
return (ENOMEM);
}
+
+ /*
+ * XXX MaxTargets could change during a reinit. Since we don't
+ * resize the targets[] array during such an event, cache the value
+ * of MaxTargets here so that we don't get into trouble later. This
+ * should move into the reinit logic.
+ */
+ sassc->maxtargets = sc->facts->MaxTargets + sc->facts->MaxVolumes;
sassc->targets = malloc(sizeof(struct mpssas_target) *
- sc->facts->MaxTargets, M_MPT2, M_WAITOK|M_ZERO);
+ sassc->maxtargets, M_MPT2, M_WAITOK|M_ZERO);
if(!sassc->targets) {
device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
__func__, __LINE__);
@@ -696,7 +747,7 @@
sassc->sc = sc;
if ((sassc->devq = cam_simq_alloc(sc->num_reqs)) == NULL) {
- mps_dprint(sc, MPS_FAULT, "Cannot allocate SIMQ\n");
+ mps_dprint(sc, MPS_ERROR, "Cannot allocate SIMQ\n");
error = ENOMEM;
goto out;
}
@@ -705,7 +756,7 @@
sassc->sim = cam_sim_alloc(mpssas_action, mpssas_poll, "mps", sassc,
unit, &sc->mps_mtx, sc->num_reqs, sc->num_reqs, sassc->devq);
if (sassc->sim == NULL) {
- mps_dprint(sc, MPS_FAULT, "Cannot allocate SIM\n");
+ mps_dprint(sc, MPS_ERROR, "Cannot allocate SIM\n");
error = EINVAL;
goto out;
}
@@ -716,21 +767,10 @@
TASK_INIT(&sassc->ev_task, 0, mpssas_firmware_event_work, sc);
sassc->ev_tq = taskqueue_create("mps_taskq", M_NOWAIT | M_ZERO,
taskqueue_thread_enqueue, &sassc->ev_tq);
-
- /* Run the task queue with lowest priority */
- taskqueue_start_threads(&sassc->ev_tq, 1, 255, "%s taskq",
+ taskqueue_start_threads(&sassc->ev_tq, 1, PRIBIO, "%s taskq",
device_get_nameunit(sc->mps_dev));
- TAILQ_INIT(&sassc->ccb_scanq);
- error = mps_kproc_create(mpssas_scanner_thread, sassc,
- &sassc->rescan_thread, 0, 0, "mps_scan%d", unit);
- if (error) {
- mps_printf(sc, "Error %d starting rescan thread\n", error);
- goto out;
- }
-
mps_lock(sc);
- sassc->flags |= MPSSAS_SCANTHREAD;
/*
* XXX There should be a bus for every port on the adapter, but since
@@ -738,7 +778,7 @@
* everything is just a target on a single bus.
*/
if ((error = xpt_bus_register(sassc->sim, sc->mps_dev, 0)) != 0) {
- mps_dprint(sc, MPS_FAULT, "Error %d registering SCSI bus\n",
+ mps_dprint(sc, MPS_ERROR, "Error %d registering SCSI bus\n",
error);
mps_unlock(sc);
goto out;
@@ -745,26 +785,52 @@
}
/*
- * Assume that discovery events will start right away. Freezing
- * the simq will prevent the CAM boottime scanner from running
- * before discovery is complete.
+ * Assume that discovery events will start right away.
+ *
+ * Hold off boot until discovery is complete.
*/
sassc->flags |= MPSSAS_IN_STARTUP | MPSSAS_IN_DISCOVERY;
- xpt_freeze_simq(sassc->sim, 1);
sc->sassc->startup_refcount = 0;
+ mpssas_startup_increment(sassc);
callout_init(&sassc->discovery_callout, 1 /*mpsafe*/);
- sassc->discovery_timeouts = 0;
- sassc->tm_count = 0;
+ /*
+ * Register for async events so we can determine the EEDP
+ * capabilities of devices.
+ */
+ status = xpt_create_path(&sassc->path, /*periph*/NULL,
+ cam_sim_path(sc->sassc->sim), CAM_TARGET_WILDCARD,
+ CAM_LUN_WILDCARD);
+ if (status != CAM_REQ_CMP) {
+ mps_printf(sc, "Error %#x creating sim path\n", status);
+ sassc->path = NULL;
+ } else {
+ int event;
-#if __FreeBSD_version >= 1000006
- status = xpt_register_async(AC_ADVINFO_CHANGED, mpssas_async, sc, NULL);
+#if (__FreeBSD_version >= 1000006) || \
+ ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000))
+ event = AC_ADVINFO_CHANGED;
+#else
+ event = AC_FOUND_DEVICE;
+#endif
+ status = xpt_register_async(event, mpssas_async, sc,
+ sassc->path);
+ if (status != CAM_REQ_CMP) {
+ mps_dprint(sc, MPS_ERROR,
+ "Error %#x registering async handler for "
+ "AC_ADVINFO_CHANGED events\n", status);
+ xpt_free_path(sassc->path);
+ sassc->path = NULL;
+ }
+ }
if (status != CAM_REQ_CMP) {
- mps_printf(sc, "Error %#x registering async handler for "
- "AC_ADVINFO_CHANGED events\n", status);
+ /*
+ * EEDP use is the exception, not the rule.
+ * Warn the user, but do not fail to attach.
+ */
+ mps_printf(sc, "EEDP capabilities disabled.\n");
}
-#endif
mps_unlock(sc);
@@ -783,7 +849,7 @@
struct mpssas_target *targ;
int i;
- mps_dprint(sc, MPS_INFO, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
if (sc->sassc == NULL)
return (0);
@@ -803,9 +869,11 @@
mps_lock(sc);
/* Deregister our async handler */
-#if __FreeBSD_version >= 1000006
- xpt_register_async(0, mpssas_async, sc, NULL);
-#endif
+ if (sassc->path != NULL) {
+ xpt_register_async(0, mpssas_async, sc, sassc->path);
+ xpt_free_path(sassc->path);
+ sassc->path = NULL;
+ }
if (sassc->flags & MPSSAS_IN_STARTUP)
xpt_release_simq(sassc->sim, 1);
@@ -815,22 +883,12 @@
cam_sim_free(sassc->sim, FALSE);
}
- if (sassc->flags & MPSSAS_SCANTHREAD) {
- sassc->flags |= MPSSAS_SHUTDOWN;
- wakeup(&sassc->ccb_scanq);
-
- if (sassc->flags & MPSSAS_SCANTHREAD) {
- msleep(&sassc->flags, &sc->mps_mtx, PRIBIO,
- "mps_shutdown", 30 * hz);
- }
- }
mps_unlock(sc);
- mps_dprint(sc, MPS_INFO, "%s:%d\n", __func__,__LINE__);
if (sassc->devq != NULL)
cam_simq_free(sassc->devq);
- for(i=0; i< sc->facts->MaxTargets ;i++) {
+ for(i=0; i< sassc->maxtargets ;i++) {
targ = &sassc->targets[i];
SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) {
free(lun, M_MPT2);
@@ -848,51 +906,30 @@
{
struct mps_softc *sc = sassc->sc;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
if (sassc->flags & MPSSAS_DISCOVERY_TIMEOUT_PENDING)
callout_stop(&sassc->discovery_callout);
-}
-
-static void
-mpssas_discovery_timeout(void *data)
-{
- struct mpssas_softc *sassc = data;
- struct mps_softc *sc;
-
- sc = sassc->sc;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
-
- mps_lock(sc);
- mps_printf(sc,
- "Timeout waiting for discovery, interrupts may not be working!\n");
- sassc->flags &= ~MPSSAS_DISCOVERY_TIMEOUT_PENDING;
-
- /* Poll the hardware for events in case interrupts aren't working */
- mps_intr_locked(sc);
-
- mps_printf(sassc->sc,
- "Finished polling after discovery timeout at %d\n", ticks);
-
- if ((sassc->flags & MPSSAS_IN_DISCOVERY) == 0) {
- mpssas_discovery_end(sassc);
- } else {
- if (sassc->discovery_timeouts < MPSSAS_MAX_DISCOVERY_TIMEOUTS) {
- sassc->flags |= MPSSAS_DISCOVERY_TIMEOUT_PENDING;
- callout_reset(&sassc->discovery_callout,
- MPSSAS_DISCOVERY_TIMEOUT * hz,
- mpssas_discovery_timeout, sassc);
- sassc->discovery_timeouts++;
- } else {
- mps_dprint(sassc->sc, MPS_FAULT,
- "Discovery timed out, continuing.\n");
- sassc->flags &= ~MPSSAS_IN_DISCOVERY;
- mpssas_discovery_end(sassc);
- }
+ /*
+ * After discovery has completed, check the mapping table for any
+ * missing devices and update their missing counts. Only do this once
+ * whenever the driver is initialized so that missing counts aren't
+ * updated unnecessarily. Note that just because discovery has
+ * completed doesn't mean that events have been processed yet. The
+ * check_devices function is a callout timer that checks if ALL devices
+ * are missing. If so, it will wait a little longer for events to
+ * complete and keep resetting itself until some device in the mapping
+ * table is not missing, meaning that event processing has started.
+ */
+ if (sc->track_mapping_events) {
+ mps_dprint(sc, MPS_XINFO | MPS_MAPPING, "Discovery has "
+ "completed. Check for missing devices in the mapping "
+ "table.\n");
+ callout_reset(&sc->device_check_callout,
+ MPS_MISSING_CHECK_DELAY * hz, mps_mapping_check_devices,
+ sc);
}
-
- mps_unlock(sc);
}
static void
@@ -902,7 +939,8 @@
sassc = cam_sim_softc(sim);
- mps_dprint(sassc->sc, MPS_TRACE, "%s func 0x%x\n", __func__,
+ MPS_FUNCTRACE(sassc->sc);
+ mps_dprint(sassc->sc, MPS_TRACE, "ccb func_code 0x%x\n",
ccb->ccb_h.func_code);
mtx_assert(&sassc->sc->mps_mtx, MA_OWNED);
@@ -910,18 +948,29 @@
case XPT_PATH_INQ:
{
struct ccb_pathinq *cpi = &ccb->cpi;
+ struct mps_softc *sc = sassc->sc;
+ uint8_t sges_per_frame;
cpi->version_num = 1;
cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
cpi->target_sprt = 0;
- cpi->hba_misc = PIM_NOBUSRESET;
+#if __FreeBSD_version >= 1000039
+ cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN;
+#else
+ cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
+#endif
cpi->hba_eng_cnt = 0;
- cpi->max_target = sassc->sc->facts->MaxTargets - 1;
+ cpi->max_target = sassc->maxtargets - 1;
cpi->max_lun = 255;
- cpi->initiator_id = 255;
- strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
- strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN);
- strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+
+ /*
+ * initiator_id is set here to an ID outside the set of valid
+ * target IDs (including volumes).
+ */
+ cpi->initiator_id = sassc->maxtargets;
+ strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+ strlcpy(cpi->hba_vid, "Avago Tech", HBA_IDLEN);
+ strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
cpi->unit_number = cam_sim_unit(sim);
cpi->bus_id = cam_sim_bus(sim);
cpi->base_transfer_speed = 150000;
@@ -929,13 +978,24 @@
cpi->transport_version = 0;
cpi->protocol = PROTO_SCSI;
cpi->protocol_version = SCSI_REV_SPC;
-#if __FreeBSD_version >= 800001
+
/*
- * XXX KDM where does this number come from?
+ * Max IO Size is Page Size * the following:
+ * ((SGEs per frame - 1 for chain element) *
+ * Max Chain Depth) + 1 for no chain needed in last frame
+ *
+ * If user suggests a Max IO size to use, use the smaller of the
+ * user's value and the calculated value as long as the user's
+ * value is larger than 0. The user's value is in pages.
*/
- cpi->maxio = 256 * 1024;
-#endif
- cpi->ccb_h.status = CAM_REQ_CMP;
+ sges_per_frame = ((sc->facts->IOCRequestFrameSize * 4) /
+ sizeof(MPI2_SGE_SIMPLE64)) - 1;
+ cpi->maxio = (sges_per_frame * sc->facts->MaxChainDepth) + 1;
+ cpi->maxio *= PAGE_SIZE;
+ if ((sc->max_io_pages > 0) && (sc->max_io_pages * PAGE_SIZE <
+ cpi->maxio))
+ cpi->maxio = sc->max_io_pages * PAGE_SIZE;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
break;
}
case XPT_GET_TRAN_SETTINGS:
@@ -949,9 +1009,12 @@
sas = &cts->xport_specific.sas;
scsi = &cts->proto_specific.scsi;
+ KASSERT(cts->ccb_h.target_id < sassc->maxtargets,
+ ("Target %d out of bounds in XPT_GET_TRANS_SETTINGS\n",
+ cts->ccb_h.target_id));
targ = &sassc->targets[cts->ccb_h.target_id];
if (targ->handle == 0x0) {
- cts->ccb_h.status = CAM_SEL_TIMEOUT;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
break;
}
@@ -978,23 +1041,23 @@
scsi->valid = CTS_SCSI_VALID_TQ;
scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
- cts->ccb_h.status = CAM_REQ_CMP;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
break;
}
case XPT_CALC_GEOMETRY:
cam_calc_geometry(&ccb->ccg, /*extended*/1);
- ccb->ccb_h.status = CAM_REQ_CMP;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
break;
case XPT_RESET_DEV:
- mps_printf(sassc->sc, "mpssas_action XPT_RESET_DEV\n");
+ mps_dprint(sassc->sc, MPS_XINFO, "mpssas_action XPT_RESET_DEV\n");
mpssas_action_resetdev(sassc, ccb);
return;
case XPT_RESET_BUS:
case XPT_ABORT:
case XPT_TERM_IO:
- mps_printf(sassc->sc, "mpssas_action faking success for "
- "abort or reset\n");
- ccb->ccb_h.status = CAM_REQ_CMP;
+ mps_dprint(sassc->sc, MPS_XINFO,
+ "mpssas_action faking success for abort or reset\n");
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
break;
case XPT_SCSI_IO:
mpssas_action_scsiio(sassc, ccb);
@@ -1005,7 +1068,7 @@
return;
#endif
default:
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+ mpssas_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL);
break;
}
xpt_done(ccb);
@@ -1019,12 +1082,12 @@
path_id_t path_id = cam_sim_path(sc->sassc->sim);
struct cam_path *path;
- mps_printf(sc, "%s code %x target %d lun %d\n", __func__,
- ac_code, target_id, lun_id);
+ mps_dprint(sc, MPS_XINFO, "%s code %x target %d lun %jx\n", __func__,
+ ac_code, target_id, (uintmax_t)lun_id);
if (xpt_create_path(&path, NULL,
path_id, target_id, lun_id) != CAM_REQ_CMP) {
- mps_printf(sc, "unable to create path for reset "
+ mps_dprint(sc, MPS_ERROR, "unable to create path for reset "
"notification\n");
return;
}
@@ -1040,7 +1103,7 @@
int i;
int completed;
- mps_printf(sc, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
mtx_assert(&sc->mps_mtx, MA_OWNED);
/* complete all commands with a NULL reply */
@@ -1053,7 +1116,7 @@
cm->cm_flags |= MPS_CM_FLAGS_COMPLETE;
if (cm->cm_complete != NULL) {
- mpssas_log_command(cm,
+ mpssas_log_command(cm, MPS_RECOVERY,
"completing cm %p state %x ccb %p for diag reset\n",
cm, cm->cm_state, cm->cm_ccb);
@@ -1062,16 +1125,19 @@
}
if (cm->cm_flags & MPS_CM_FLAGS_WAKEUP) {
- mpssas_log_command(cm,
+ mpssas_log_command(cm, MPS_RECOVERY,
"waking up cm %p state %x ccb %p for diag reset\n",
cm, cm->cm_state, cm->cm_ccb);
wakeup(cm);
completed = 1;
}
+
+ if (cm->cm_sc->io_cmds_active != 0)
+ cm->cm_sc->io_cmds_active--;
if ((completed == 0) && (cm->cm_state != MPS_CM_STATE_FREE)) {
/* this should never happen, but if it does, log */
- mpssas_log_command(cm,
+ mpssas_log_command(cm, MPS_RECOVERY,
"cm %p state %x flags 0x%x ccb %p during diag "
"reset\n", cm, cm->cm_state, cm->cm_flags,
cm->cm_ccb);
@@ -1092,10 +1158,10 @@
* discovery-related activities have finished, the simq will be
* released.
*/
- mps_printf(sc, "%s startup\n", __func__);
+ mps_dprint(sc, MPS_INIT, "%s startup\n", __func__);
sc->sassc->flags |= MPSSAS_IN_STARTUP;
sc->sassc->flags |= MPSSAS_IN_DISCOVERY;
- xpt_freeze_simq(sc->sassc->sim, 1);
+ mpssas_startup_increment(sc->sassc);
/* notify CAM of a bus reset */
mpssas_announce_reset(sc, AC_BUS_RESET, CAM_TARGET_WILDCARD,
@@ -1104,22 +1170,17 @@
/* complete and cleanup after all outstanding commands */
mpssas_complete_all_commands(sc);
- mps_printf(sc, "%s startup %u tm %u after command completion\n",
- __func__, sc->sassc->startup_refcount, sc->sassc->tm_count);
+ mps_dprint(sc, MPS_INIT,
+ "%s startup %u after command completion\n", __func__,
+ sc->sassc->startup_refcount);
- /*
- * The simq was explicitly frozen above, so set the refcount to 0.
- * The simq will be explicitly released after port enable completes.
- */
- sc->sassc->startup_refcount = 0;
-
/* zero all the target handles, since they may change after the
* reset, and we have to rediscover all the targets and use the new
* handles.
*/
- for (i = 0; i < sc->facts->MaxTargets; i++) {
+ for (i = 0; i < sc->sassc->maxtargets; i++) {
if (sc->sassc->targets[i].outstanding != 0)
- mps_printf(sc, "target %u outstanding %u\n",
+ mps_dprint(sc, MPS_INIT, "target %u outstanding %u\n",
i, sc->sassc->targets[i].outstanding);
sc->sassc->targets[i].handle = 0x0;
sc->sassc->targets[i].exp_dev_handle = 0x0;
@@ -1127,6 +1188,7 @@
sc->sassc->targets[i].flags = MPSSAS_TARGET_INDIAGRESET;
}
}
+
static void
mpssas_tm_timeout(void *data)
{
@@ -1135,7 +1197,8 @@
mtx_assert(&sc->mps_mtx, MA_OWNED);
- mpssas_log_command(tm, "task mgmt %p timed out\n", tm);
+ mpssas_log_command(tm, MPS_INFO|MPS_RECOVERY,
+ "task mgmt %p timed out\n", tm);
mps_reinit(sc);
}
@@ -1158,9 +1221,10 @@
* Currently there should be no way we can hit this case. It only
* happens when we have a failure to allocate chain frames, and
* task management commands don't have S/G lists.
+ * XXXSL So should it be an assertion?
*/
if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
- mps_printf(sc, "%s: cm_flags = %#x for LUN reset! "
+ mps_dprint(sc, MPS_ERROR, "%s: cm_flags = %#x for LUN reset! "
"This should not happen!\n", __func__, tm->cm_flags);
mpssas_free_tm(sc, tm);
return;
@@ -1167,10 +1231,10 @@
}
if (reply == NULL) {
- mpssas_log_command(tm, "NULL reset reply for tm %p\n", tm);
+ mpssas_log_command(tm, MPS_RECOVERY,
+ "NULL reset reply for tm %p\n", tm);
if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
/* this completion was due to a reset, just cleanup */
- targ->flags &= ~MPSSAS_TARGET_INRESET;
targ->tm = NULL;
mpssas_free_tm(sc, tm);
}
@@ -1181,7 +1245,7 @@
return;
}
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"logical unit reset status 0x%x code 0x%x count %u\n",
le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
le32toh(reply->TerminationCount));
@@ -1196,7 +1260,7 @@
}
if (cm_count == 0) {
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO,
"logical unit %u finished recovery after reset\n",
tm->cm_lun, tm);
@@ -1221,7 +1285,7 @@
* effectively failed, regardless of the status reported.
* Escalate to a target reset.
*/
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"logical unit reset complete for tm %p, but still have %u command(s)\n",
tm, cm_count);
mpssas_send_reset(sc, tm,
@@ -1248,7 +1312,7 @@
* task management commands don't have S/G lists.
*/
if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
- mps_printf(sc, "%s: cm_flags = %#x for target reset! "
+ mps_dprint(sc, MPS_ERROR,"%s: cm_flags = %#x for target reset! "
"This should not happen!\n", __func__, tm->cm_flags);
mpssas_free_tm(sc, tm);
return;
@@ -1255,10 +1319,10 @@
}
if (reply == NULL) {
- mpssas_log_command(tm, "NULL reset reply for tm %p\n", tm);
+ mpssas_log_command(tm, MPS_RECOVERY,
+ "NULL reset reply for tm %p\n", tm);
if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
/* this completion was due to a reset, just cleanup */
- targ->flags &= ~MPSSAS_TARGET_INRESET;
targ->tm = NULL;
mpssas_free_tm(sc, tm);
}
@@ -1269,18 +1333,16 @@
return;
}
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"target reset status 0x%x code 0x%x count %u\n",
le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
le32toh(reply->TerminationCount));
- targ->flags &= ~MPSSAS_TARGET_INRESET;
-
if (targ->outstanding == 0) {
/* we've finished recovery for this target and all
* of its logical units.
*/
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO,
"recovery finished after target reset\n");
mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
@@ -1294,7 +1356,7 @@
* outstanding commands, the reset effectively failed,
* regardless of the status reported. escalate.
*/
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"target reset complete for tm %p, but still have %u command(s)\n",
tm, targ->outstanding);
mps_reinit(sc);
@@ -1303,7 +1365,7 @@
#define MPS_RESET_TIMEOUT 30
-static int
+int
mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type)
{
MPI2_SCSI_TASK_MANAGE_REQUEST *req;
@@ -1312,7 +1374,7 @@
target = tm->cm_targ;
if (target->handle == 0) {
- mps_printf(sc, "%s null devhandle for target_id %d\n",
+ mps_dprint(sc, MPS_ERROR,"%s null devhandle for target_id %d\n",
__func__, target->tid);
return -1;
}
@@ -1326,19 +1388,25 @@
/* XXX Need to handle invalid LUNs */
MPS_SET_LUN(req->LUN, tm->cm_lun);
tm->cm_targ->logical_unit_resets++;
- mpssas_log_command(tm, "sending logical unit reset\n");
+ mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO,
+ "sending logical unit reset\n");
tm->cm_complete = mpssas_logical_unit_reset_complete;
+ mpssas_prepare_for_tm(sc, tm, target, tm->cm_lun);
}
else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
- /* Target reset method = SAS Hard Link Reset / SATA Link Reset */
+ /*
+ * Target reset method =
+ * SAS Hard Link Reset / SATA Link Reset
+ */
req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
tm->cm_targ->target_resets++;
- tm->cm_targ->flags |= MPSSAS_TARGET_INRESET;
- mpssas_log_command(tm, "sending target reset\n");
+ mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO,
+ "sending target reset\n");
tm->cm_complete = mpssas_target_reset_complete;
+ mpssas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD);
}
else {
- mps_printf(sc, "unexpected reset type 0x%x\n", type);
+ mps_dprint(sc, MPS_ERROR, "unexpected reset type 0x%x\n", type);
return -1;
}
@@ -1351,7 +1419,7 @@
err = mps_map_command(sc, tm);
if (err)
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"error %d sending reset type %u\n",
err, type);
@@ -1379,7 +1447,7 @@
* task management commands don't have S/G lists.
*/
if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"cm_flags = %#x for abort %p TaskMID %u!\n",
tm->cm_flags, tm, le16toh(req->TaskMID));
mpssas_free_tm(sc, tm);
@@ -1387,7 +1455,7 @@
}
if (reply == NULL) {
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"NULL abort reply for tm %p TaskMID %u\n",
tm, le16toh(req->TaskMID));
if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
@@ -1402,7 +1470,7 @@
return;
}
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"abort TaskMID %u status 0x%x code 0x%x count %u\n",
le16toh(req->TaskMID),
le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
@@ -1413,7 +1481,7 @@
/* if there are no more timedout commands, we're done with
* error recovery for this target.
*/
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"finished recovery after aborting TaskMID %u\n",
le16toh(req->TaskMID));
@@ -1422,7 +1490,7 @@
}
else if (le16toh(req->TaskMID) != cm->cm_desc.Default.SMID) {
/* abort success, but we have more timedout commands to abort */
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"continuing recovery after aborting TaskMID %u\n",
le16toh(req->TaskMID));
@@ -1432,7 +1500,7 @@
/* we didn't get a command completion, so the abort
* failed as far as we're concerned. escalate.
*/
- mpssas_log_command(tm,
+ mpssas_log_command(tm, MPS_RECOVERY,
"abort failed for TaskMID %u tm %p\n",
le16toh(req->TaskMID), tm);
@@ -1452,11 +1520,14 @@
targ = cm->cm_targ;
if (targ->handle == 0) {
- mps_printf(sc, "%s null devhandle for target_id %d\n",
+ mps_dprint(sc, MPS_ERROR,"%s null devhandle for target_id %d\n",
__func__, cm->cm_ccb->ccb_h.target_id);
return -1;
}
+ mpssas_log_command(cm, MPS_RECOVERY|MPS_INFO,
+ "Aborting command %p\n", cm);
+
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
req->DevHandle = htole16(targ->handle);
req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
@@ -1479,15 +1550,18 @@
targ->aborts++;
+ mps_dprint(sc, MPS_INFO, "Sending reset from %s for target ID %d\n",
+ __func__, targ->tid);
+ mpssas_prepare_for_tm(sc, tm, targ, tm->cm_lun);
+
err = mps_map_command(sc, tm);
if (err)
- mpssas_log_command(tm,
+ mps_dprint(sc, MPS_RECOVERY,
"error %d sending abort for cm %p SMID %u\n",
err, cm, req->TaskMID);
return err;
}
-
static void
mpssas_scsiio_timeout(void *data)
{
@@ -1498,9 +1572,10 @@
cm = (struct mps_command *)data;
sc = cm->cm_sc;
+ MPS_FUNCTRACE(sc);
mtx_assert(&sc->mps_mtx, MA_OWNED);
- mps_printf(sc, "%s checking sc %p cm %p\n", __func__, sc, cm);
+ mps_dprint(sc, MPS_XINFO, "Timeout checking cm %p\n", sc);
/*
* Run the interrupt handler to make sure it's not pending. This
@@ -1509,26 +1584,27 @@
*/
mps_intr_locked(sc);
if (cm->cm_state == MPS_CM_STATE_FREE) {
- mps_printf(sc, "SCSI command %p sc %p almost timed out\n", cm, sc);
+ mpssas_log_command(cm, MPS_XINFO,
+ "SCSI command %p almost timed out\n", cm);
return;
}
if (cm->cm_ccb == NULL) {
- mps_printf(sc, "command timeout with NULL ccb\n");
+ mps_dprint(sc, MPS_ERROR, "command timeout with NULL ccb\n");
return;
}
- mpssas_log_command(cm, "command timeout cm %p ccb %p\n",
- cm, cm->cm_ccb);
-
targ = cm->cm_targ;
targ->timeouts++;
+ mpssas_log_command(cm, MPS_ERROR, "command timeout %d cm %p target "
+ "%u, handle(0x%04x)\n", cm->cm_ccb->ccb_h.timeout, cm, targ->tid,
+ targ->handle);
+
/* XXX first, check the firmware state, to see if it's still
* operational. if not, do a diag reset.
*/
-
- cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT;
+ mpssas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT);
cm->cm_state = MPS_CM_STATE_TIMEDOUT;
TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery);
@@ -1536,11 +1612,12 @@
/* target already in recovery, just queue up another
* timedout command to be processed later.
*/
- mps_printf(sc, "queued timedout cm %p for processing by tm %p\n",
+ mps_dprint(sc, MPS_RECOVERY,
+ "queued timedout cm %p for processing by tm %p\n",
cm, targ->tm);
}
else if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) {
- mps_printf(sc, "timedout cm %p allocated tm %p\n",
+ mps_dprint(sc, MPS_RECOVERY, "timedout cm %p allocated tm %p\n",
cm, targ->tm);
/* start recovery by aborting the first timedout command */
@@ -1556,8 +1633,8 @@
* more credits than disks in an enclosure, and limit
* ourselves to one TM per target for recovery.
*/
- mps_printf(sc, "timedout cm %p failed to allocate a tm\n",
- cm);
+ mps_dprint(sc, MPS_RECOVERY,
+ "timedout cm %p failed to allocate a tm\n", cm);
}
}
@@ -1576,26 +1653,41 @@
uint32_t mpi_control;
sc = sassc->sc;
+ MPS_FUNCTRACE(sc);
mtx_assert(&sc->mps_mtx, MA_OWNED);
csio = &ccb->csio;
+ KASSERT(csio->ccb_h.target_id < sassc->maxtargets,
+ ("Target %d out of bounds in XPT_SCSI_IO\n",
+ csio->ccb_h.target_id));
targ = &sassc->targets[csio->ccb_h.target_id];
- mps_dprint(sc, MPS_TRACE, "%s ccb %p target flag %x\n", __func__, ccb, targ->flags);
+ mps_dprint(sc, MPS_TRACE, "ccb %p target flag %x\n", ccb, targ->flags);
if (targ->handle == 0x0) {
- mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n",
+ mps_dprint(sc, MPS_ERROR, "%s NULL handle for target %u\n",
__func__, csio->ccb_h.target_id);
- csio->ccb_h.status = CAM_SEL_TIMEOUT;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
xpt_done(ccb);
return;
}
if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) {
- mps_dprint(sc, MPS_TRACE, "%s Raid component no SCSI IO supported %u\n",
- __func__, csio->ccb_h.target_id);
- csio->ccb_h.status = CAM_TID_INVALID;
+ mps_dprint(sc, MPS_ERROR, "%s Raid component no SCSI IO "
+ "supported %u\n", __func__, csio->ccb_h.target_id);
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
xpt_done(ccb);
return;
}
/*
+ * Sometimes, it is possible to get a command that is not "In
+ * Progress" and was actually aborted by the upper layer. Check for
+ * this here and complete the command without error.
+ */
+ if (mpssas_get_ccbstatus(ccb) != CAM_REQ_INPROG) {
+ mps_dprint(sc, MPS_TRACE, "%s Command is not in progress for "
+ "target %u\n", __func__, csio->ccb_h.target_id);
+ xpt_done(ccb);
+ return;
+ }
+ /*
* If devinfo is 0 this will be a volume. In that case don't tell CAM
* that the volume has timed out. We want volumes to be enumerated
* until they are deleted/removed, not just failed.
@@ -1602,22 +1694,38 @@
*/
if (targ->flags & MPSSAS_TARGET_INREMOVAL) {
if (targ->devinfo == 0)
- csio->ccb_h.status = CAM_REQ_CMP;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
else
- csio->ccb_h.status = CAM_SEL_TIMEOUT;
+ mpssas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT);
xpt_done(ccb);
return;
}
if ((sc->mps_flags & MPS_FLAGS_SHUTDOWN) != 0) {
- mps_dprint(sc, MPS_TRACE, "%s shutting down\n", __func__);
- csio->ccb_h.status = CAM_TID_INVALID;
+ mps_dprint(sc, MPS_INFO, "%s shutting down\n", __func__);
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
xpt_done(ccb);
return;
}
+ /*
+ * If target has a reset in progress, freeze the devq and return. The
+ * devq will be released when the TM reset is finished.
+ */
+ if (targ->flags & MPSSAS_TARGET_INRESET) {
+ ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
+ mps_dprint(sc, MPS_INFO, "%s: Freezing devq for target ID %d\n",
+ __func__, targ->tid);
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ xpt_done(ccb);
+ return;
+ }
+
cm = mps_alloc_command(sc);
- if (cm == NULL) {
+ if (cm == NULL || (sc->mps_flags & MPS_FLAGS_DIAGRESET)) {
+ if (cm != NULL) {
+ mps_free_command(sc, cm);
+ }
if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) {
xpt_freeze_simq(sassc->sim, 1);
sassc->flags |= MPSSAS_QUEUE_FROZEN;
@@ -1663,7 +1771,7 @@
break;
}
- if (csio->cdb_len == 32)
+ if (csio->cdb_len == 32)
mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
/*
* It looks like the hardware doesn't require an explicit tag
@@ -1690,7 +1798,7 @@
req->Control = htole32(mpi_control);
if (MPS_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) {
mps_free_command(sc, cm);
- ccb->ccb_h.status = CAM_LUN_INVALID;
+ mpssas_set_ccbstatus(ccb, CAM_LUN_INVALID);
xpt_done(ccb);
return;
}
@@ -1755,8 +1863,13 @@
}
}
- cm->cm_data = csio->data_ptr;
cm->cm_length = csio->dxfer_len;
+ if (cm->cm_length != 0) {
+ cm->cm_data = ccb;
+ cm->cm_flags |= MPS_CM_FLAGS_USE_CCB;
+ } else {
+ cm->cm_data = NULL;
+ }
cm->cm_sge = &req->SGL;
cm->cm_sglsize = (32 - 24) * 4;
cm->cm_desc.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
@@ -1773,23 +1886,23 @@
* the I/O to the IR volume itself.
*/
if (sc->WD_valid_config) {
- if (ccb->ccb_h.status != MPS_WD_RETRY) {
+ if (ccb->ccb_h.sim_priv.entries[0].field == MPS_WD_RETRY) {
mpssas_direct_drive_io(sassc, cm, ccb);
} else {
- ccb->ccb_h.status = CAM_REQ_INPROG;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_INPROG);
}
}
- callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000,
- mpssas_scsiio_timeout, cm);
+ callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0,
+ mpssas_scsiio_timeout, cm, 0);
targ->issued++;
targ->outstanding++;
TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link);
+ ccb->ccb_h.status |= CAM_SIM_QUEUED;
- if ((sc->mps_debug & MPS_TRACE) != 0)
- mpssas_log_command(cm, "%s cm %p ccb %p outstanding %u\n",
- __func__, cm, ccb, targ->outstanding);
+ mpssas_log_command(cm, MPS_XINFO, "%s cm %p ccb %p outstanding %u\n",
+ __func__, cm, ccb, targ->outstanding);
mps_map_command(sc, cm);
return;
@@ -1829,7 +1942,7 @@
desc = "unknown";
break;
}
- mps_dprint(sc, MPS_INFO, "response_code(0x%01x): %s\n",
+ mps_dprint(sc, MPS_XINFO, "response_code(0x%01x): %s\n",
response_code, desc);
}
/**
@@ -1963,21 +2076,20 @@
if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
strcat(desc_scsi_state, "autosense valid ");
- mps_dprint(sc, MPS_INFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x), \n",
- le16toh(mpi_reply->DevHandle),
- desc_ioc_state, ioc_status);
+ mps_dprint(sc, MPS_XINFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x)\n",
+ le16toh(mpi_reply->DevHandle), desc_ioc_state, ioc_status);
/* We can add more detail about underflow data here
* TO-DO
* */
- mps_dprint(sc, MPS_INFO, "\tscsi_status(%s)(0x%02x), "
- "scsi_state(%s)(0x%02x)\n", desc_scsi_status,
- scsi_status, desc_scsi_state, scsi_state);
+ mps_dprint(sc, MPS_XINFO, "\tscsi_status(%s)(0x%02x), "
+ "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status,
+ desc_scsi_state, scsi_state);
- if (sc->mps_debug & MPS_INFO &&
+ if (sc->mps_debug & MPS_XINFO &&
scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
- mps_dprint(sc, MPS_INFO, "-> Sense Buffer Data : Start :\n");
+ mps_dprint(sc, MPS_XINFO, "-> Sense Buffer Data : Start :\n");
scsi_sense_print(csio);
- mps_dprint(sc, MPS_INFO, "-> Sense Buffer Data : End :\n");
+ mps_dprint(sc, MPS_XINFO, "-> Sense Buffer Data : End :\n");
}
if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
@@ -1998,10 +2110,13 @@
u8 *TLR_bits, TLR_on;
int dir = 0, i;
u16 alloc_len;
+ struct mpssas_target *target;
+ target_id_t target_id;
+ MPS_FUNCTRACE(sc);
mps_dprint(sc, MPS_TRACE,
- "%s cm %p SMID %u ccb %p reply %p outstanding %u\n",
- __func__, cm, cm->cm_desc.Default.SMID, cm->cm_ccb, cm->cm_reply,
+ "cm %p SMID %u ccb %p reply %p outstanding %u\n", cm,
+ cm->cm_desc.Default.SMID, cm->cm_ccb, cm->cm_reply,
cm->cm_targ->outstanding);
callout_stop(&cm->cm_callout);
@@ -2010,6 +2125,7 @@
sassc = sc->sassc;
ccb = cm->cm_complete_data;
csio = &ccb->csio;
+ target_id = csio->ccb_h.target_id;
rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply;
/*
* XXX KDM if the chain allocation fails, does it matter if we do
@@ -2028,11 +2144,12 @@
cm->cm_targ->completed++;
cm->cm_targ->outstanding--;
TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link);
+ ccb->ccb_h.status &= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED);
if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) {
TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery);
if (cm->cm_reply != NULL)
- mpssas_log_command(cm,
+ mpssas_log_command(cm, MPS_RECOVERY,
"completed timedout cm %p ccb %p during recovery "
"ioc %x scsi %x state %x xfer %u\n",
cm, cm->cm_ccb,
@@ -2039,12 +2156,12 @@
le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
le32toh(rep->TransferCount));
else
- mpssas_log_command(cm,
+ mpssas_log_command(cm, MPS_RECOVERY,
"completed timedout cm %p ccb %p during recovery\n",
cm, cm->cm_ccb);
} else if (cm->cm_targ->tm != NULL) {
if (cm->cm_reply != NULL)
- mpssas_log_command(cm,
+ mpssas_log_command(cm, MPS_RECOVERY,
"completed cm %p ccb %p during recovery "
"ioc %x scsi %x state %x xfer %u\n",
cm, cm->cm_ccb,
@@ -2051,11 +2168,11 @@
le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
le32toh(rep->TransferCount));
else
- mpssas_log_command(cm,
+ mpssas_log_command(cm, MPS_RECOVERY,
"completed cm %p ccb %p during recovery\n",
cm, cm->cm_ccb);
} else if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
- mpssas_log_command(cm,
+ mpssas_log_command(cm, MPS_RECOVERY,
"reset completed cm %p ccb %p\n",
cm, cm->cm_ccb);
}
@@ -2069,7 +2186,7 @@
* because there can be no reply when we haven't actually
* gone out to the hardware.
*/
- ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ mpssas_set_ccbstatus(ccb, CAM_REQUEUE_REQ);
/*
* Currently the only error included in the mask is
@@ -2085,25 +2202,37 @@
if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) {
xpt_freeze_simq(sassc->sim, 1);
sassc->flags |= MPSSAS_QUEUE_FROZEN;
- mps_dprint(sc, MPS_INFO, "Error sending command, "
+ mps_dprint(sc, MPS_XINFO, "Error sending command, "
"freezing SIM queue\n");
}
}
+ /*
+ * If this is a Start Stop Unit command and it was issued by the driver
+ * during shutdown, decrement the refcount to account for all of the
+ * commands that were sent. All SSU commands should be completed before
+ * shutdown completes, meaning SSU_refcount will be 0 after SSU_started
+ * is TRUE.
+ */
+ if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) {
+ mps_dprint(sc, MPS_INFO, "Decrementing SSU count.\n");
+ sc->SSU_refcount--;
+ }
+
/* Take the fast path to completion */
if (cm->cm_reply == NULL) {
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
+ if (mpssas_get_ccbstatus(ccb) == CAM_REQ_INPROG) {
if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0)
- ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
+ mpssas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET);
else {
- ccb->ccb_h.status = CAM_REQ_CMP;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
ccb->csio.scsi_status = SCSI_STATUS_OK;
}
if (sassc->flags & MPSSAS_QUEUE_FROZEN) {
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
- mps_dprint(sc, MPS_INFO,
- "Unfreezing SIM queue\n");
+ mps_dprint(sc, MPS_XINFO,
+ "Unfreezing SIM queue\n");
}
}
@@ -2112,10 +2241,10 @@
* CAM_REQ_CMP. The first is if MPS_CM_FLAGS_ERROR_MASK is
* set, the second is in the MPS_FLAGS_DIAGRESET above.
*/
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ if (mpssas_get_ccbstatus(ccb) != CAM_REQ_CMP) {
/*
* Freeze the dev queue so that commands are
- * executed in the correct order with after error
+ * executed in the correct order after error
* recovery.
*/
ccb->ccb_h.status |= CAM_DEV_QFRZN;
@@ -2126,11 +2255,10 @@
return;
}
- if (sc->mps_debug & MPS_TRACE)
- mpssas_log_command(cm,
- "ioc %x scsi %x state %x xfer %u\n",
- le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
- le32toh(rep->TransferCount));
+ mpssas_log_command(cm, MPS_XINFO,
+ "ioc %x scsi %x state %x xfer %u\n",
+ le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+ le32toh(rep->TransferCount));
/*
* If this is a Direct Drive I/O, reissue the I/O to the original IR
@@ -2140,10 +2268,11 @@
*/
if (cm->cm_flags & MPS_CM_FLAGS_DD_IO) {
mps_free_command(sc, cm);
- ccb->ccb_h.status = MPS_WD_RETRY;
+ ccb->ccb_h.sim_priv.entries[0].field = MPS_WD_RETRY;
mpssas_action_scsiio(sassc, ccb);
return;
- }
+ } else
+ ccb->ccb_h.sim_priv.entries[0].field = 0;
switch (le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) {
case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
@@ -2154,12 +2283,12 @@
if ((le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) ==
MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR)
- mpssas_log_command(cm, "recovered error\n");
+ mpssas_log_command(cm, MPS_XINFO, "recovered error\n");
/* Completion failed at the transport level. */
if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS |
MPI2_SCSI_STATE_TERMINATED)) {
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
break;
}
@@ -2168,7 +2297,7 @@
* recover the command.
*/
if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) {
- ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
+ mpssas_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL);
break;
}
@@ -2178,9 +2307,10 @@
* TLR_bits for the target.
*/
if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) &&
- ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) ==
+ ((le32toh(rep->ResponseInfo) &
+ MPI2_SCSI_RI_MASK_REASONCODE) ==
MPS_SCSI_RI_INVALID_FRAME)) {
- sc->mapping_table[csio->ccb_h.target_id].TLR_bits =
+ sc->mapping_table[target_id].TLR_bits =
(u8)MPI2_SCSIIO_CONTROL_NO_TLR;
}
@@ -2192,7 +2322,7 @@
*/
if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) ||
(rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) {
- ccb->ccb_h.status = CAM_REQ_ABORTED;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_ABORTED);
break;
}
@@ -2199,9 +2329,9 @@
/* Handle normal status and sense */
csio->scsi_status = rep->SCSIStatus;
if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD)
- ccb->ccb_h.status = CAM_REQ_CMP;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
else
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+ mpssas_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR);
if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
int sense_len, returned_sense_len;
@@ -2233,18 +2363,20 @@
if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) &&
(csio->cdb_io.cdb_bytes[1] & SI_EVPD) &&
(csio->cdb_io.cdb_bytes[2] == SVPD_SUPPORTED_PAGE_LIST) &&
- (csio->data_ptr != NULL) && (((uint8_t *)cm->cm_data)[0] ==
- T_SEQUENTIAL) && (sc->control_TLR) &&
- (sc->mapping_table[csio->ccb_h.target_id].device_info &
+ ((csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) &&
+ (csio->data_ptr != NULL) &&
+ ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) &&
+ (sc->control_TLR) &&
+ (sc->mapping_table[target_id].device_info &
MPI2_SAS_DEVICE_INFO_SSP_TARGET)) {
vpd_list = (struct scsi_vpd_supported_page_list *)
csio->data_ptr;
- TLR_bits = &sc->mapping_table[csio->ccb_h.target_id].
- TLR_bits;
+ TLR_bits = &sc->mapping_table[target_id].TLR_bits;
*TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON;
alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) +
csio->cdb_io.cdb_bytes[4];
+ alloc_len -= csio->resid;
for (i = 0; i < MIN(vpd_list->length, alloc_len); i++) {
if (vpd_list->list[i] == 0x90) {
*TLR_bits = TLR_on;
@@ -2252,6 +2384,24 @@
}
}
}
+
+ /*
+ * If this is a SATA direct-access end device, mark it so that
+ * a SCSI StartStopUnit command will be sent to it when the
+ * driver is being shutdown.
+ */
+ if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) &&
+ ((csio->data_ptr[0] & 0x1f) == T_DIRECT) &&
+ (sc->mapping_table[target_id].device_info &
+ MPI2_SAS_DEVICE_INFO_SATA_DEVICE) &&
+ ((sc->mapping_table[target_id].device_info &
+ MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
+ MPI2_SAS_DEVICE_INFO_END_DEVICE)) {
+ target = &sassc->targets[target_id];
+ target->supports_SSU = TRUE;
+ mps_dprint(sc, MPS_XINFO, "Target %d supports SSU\n",
+ target_id);
+ }
break;
case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
@@ -2262,13 +2412,13 @@
* failed.
*/
if (cm->cm_targ->devinfo == 0)
- ccb->ccb_h.status = CAM_REQ_CMP;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
else
- ccb->ccb_h.status = CAM_DEV_NOT_THERE;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
break;
case MPI2_IOCSTATUS_INVALID_SGL:
mps_print_scsiio_cmd(sc, cm);
- ccb->ccb_h.status = CAM_UNREC_HBA_ERROR;
+ mpssas_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR);
break;
case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
/*
@@ -2281,27 +2431,37 @@
* on the console.
*/
if (cm->cm_state == MPS_CM_STATE_TIMEDOUT)
- ccb->ccb_h.status = CAM_CMD_TIMEOUT;
+ mpssas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT);
else
- ccb->ccb_h.status = CAM_REQ_ABORTED;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_ABORTED);
break;
case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
/* resid is ignored for this condition */
csio->resid = 0;
- ccb->ccb_h.status = CAM_DATA_RUN_ERR;
+ mpssas_set_ccbstatus(ccb, CAM_DATA_RUN_ERR);
break;
case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
/*
- * Since these are generally external (i.e. hopefully
- * transient transport-related) errors, retry these without
- * decrementing the retry count.
+ * These can sometimes be transient transport-related
+ * errors, and sometimes persistent drive-related errors.
+ * We used to retry these without decrementing the retry
+ * count by returning CAM_REQUEUE_REQ. Unfortunately, if
+ * we hit a persistent drive problem that returns one of
+ * these error codes, we would retry indefinitely. So,
+ * return CAM_REQ_CMP_ERROR so that we decrement the retry
+ * count and avoid infinite retries. We're taking the
+ * potential risk of flagging false failures in the event
+ * of a topology-related error (e.g. a SAS expander problem
+ * causes a command addressed to a drive to fail), but
+ * avoiding getting into an infinite retry loop.
*/
- ccb->ccb_h.status = CAM_REQUEUE_REQ;
- mpssas_log_command(cm,
- "terminated ioc %x scsi %x state %x xfer %u\n",
- le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
- le32toh(rep->TransferCount));
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
+ mpssas_log_command(cm, MPS_INFO,
+ "terminated ioc %x loginfo %x scsi %x state %x xfer %u\n",
+ le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo),
+ rep->SCSIStatus, rep->SCSIState,
+ le32toh(rep->TransferCount));
break;
case MPI2_IOCSTATUS_INVALID_FUNCTION:
case MPI2_IOCSTATUS_INTERNAL_ERROR:
@@ -2314,12 +2474,13 @@
case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
default:
- mpssas_log_command(cm,
- "completed ioc %x scsi %x state %x xfer %u\n",
- le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
- le32toh(rep->TransferCount));
+ mpssas_log_command(cm, MPS_XINFO,
+ "completed ioc %x loginfo %x scsi %x state %x xfer %u\n",
+ le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo),
+ rep->SCSIStatus, rep->SCSIState,
+ le32toh(rep->TransferCount));
csio->resid = cm->cm_length;
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
break;
}
@@ -2328,11 +2489,11 @@
if (sassc->flags & MPSSAS_QUEUE_FROZEN) {
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
- mps_dprint(sc, MPS_INFO, "Command completed, "
- "unfreezing SIM queue\n");
+ mps_dprint(sc, MPS_XINFO, "Command completed, "
+ "unfreezing SIM queue\n");
}
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ if (mpssas_get_ccbstatus(ccb) != CAM_REQ_CMP) {
ccb->ccb_h.status |= CAM_DEV_QFRZN;
xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1);
}
@@ -2628,16 +2789,16 @@
* in the standard request size.
*/
if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
- mps_printf(sc, "%s: cm_flags = %#x on SMP request!\n",
+ mps_dprint(sc, MPS_ERROR,"%s: cm_flags = %#x on SMP request!\n",
__func__, cm->cm_flags);
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
goto bailout;
}
rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply;
if (rpl == NULL) {
- mps_dprint(sc, MPS_INFO, "%s: NULL cm_reply!\n", __func__);
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ mps_dprint(sc, MPS_ERROR, "%s: NULL cm_reply!\n", __func__);
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
goto bailout;
}
@@ -2645,22 +2806,23 @@
sasaddr = le32toh(req->SASAddress.Low);
sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32;
- if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS ||
+ if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
+ MPI2_IOCSTATUS_SUCCESS ||
rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) {
- mps_dprint(sc, MPS_INFO, "%s: IOCStatus %04x SASStatus %02x\n",
+ mps_dprint(sc, MPS_XINFO, "%s: IOCStatus %04x SASStatus %02x\n",
__func__, le16toh(rpl->IOCStatus), rpl->SASStatus);
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
goto bailout;
}
- mps_dprint(sc, MPS_INFO, "%s: SMP request to SAS address "
+ mps_dprint(sc, MPS_XINFO, "%s: SMP request to SAS address "
"%#jx completed successfully\n", __func__,
(uintmax_t)sasaddr);
if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED)
- ccb->ccb_h.status = CAM_REQ_CMP;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
else
- ccb->ccb_h.status = CAM_SMP_STATUS_ERROR;
+ mpssas_set_ccbstatus(ccb, CAM_SMP_STATUS_ERROR);
bailout:
/*
@@ -2681,29 +2843,23 @@
uint8_t *request, *response;
MPI2_SMP_PASSTHROUGH_REQUEST *req;
struct mps_softc *sc;
- struct sglist *sg;
int error;
sc = sassc->sc;
- sg = NULL;
error = 0;
/*
* XXX We don't yet support physical addresses here.
*/
- if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) {
- mps_printf(sc, "%s: physical addresses not supported\n",
- __func__);
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) {
+ case CAM_DATA_PADDR:
+ case CAM_DATA_SG_PADDR:
+ mps_dprint(sc, MPS_ERROR,
+ "%s: physical addresses not supported\n", __func__);
+ mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
xpt_done(ccb);
return;
- }
-
- /*
- * If the user wants to send an S/G list, check to make sure they
- * have single buffers.
- */
- if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
+ case CAM_DATA_SG:
/*
* The chip does not support more than one buffer for the
* request or response.
@@ -2710,10 +2866,11 @@
*/
if ((ccb->smpio.smp_request_sglist_cnt > 1)
|| (ccb->smpio.smp_response_sglist_cnt > 1)) {
- mps_printf(sc, "%s: multiple request or response "
+ mps_dprint(sc, MPS_ERROR,
+ "%s: multiple request or response "
"buffer segments not supported for SMP\n",
__func__);
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
xpt_done(ccb);
return;
}
@@ -2730,7 +2887,7 @@
bus_dma_segment_t *req_sg;
req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request;
- request = (uint8_t *)req_sg[0].ds_addr;
+ request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr;
} else
request = ccb->smpio.smp_request;
@@ -2738,18 +2895,25 @@
bus_dma_segment_t *rsp_sg;
rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response;
- response = (uint8_t *)rsp_sg[0].ds_addr;
+ response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr;
} else
response = ccb->smpio.smp_response;
- } else {
+ break;
+ case CAM_DATA_VADDR:
request = ccb->smpio.smp_request;
response = ccb->smpio.smp_response;
+ break;
+ default:
+ mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
+ xpt_done(ccb);
+ return;
}
cm = mps_alloc_command(sc);
if (cm == NULL) {
- mps_printf(sc, "%s: cannot allocate command\n", __func__);
- ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ mps_dprint(sc, MPS_ERROR,
+ "%s: cannot allocate command\n", __func__);
+ mpssas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL);
xpt_done(ccb);
return;
}
@@ -2765,8 +2929,8 @@
req->SGLFlags =
MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI;
- mps_dprint(sc, MPS_INFO, "%s: sending SMP request to SAS "
- "address %#jx\n", __func__, (uintmax_t)sasaddr);
+ mps_dprint(sc, MPS_XINFO, "%s: sending SMP request to SAS "
+ "address %#jx\n", __func__, (uintmax_t)sasaddr);
mpi_init_sge(cm, req, &req->SGL);
@@ -2827,7 +2991,8 @@
*/
error = mps_map_command(sc, cm);
if ((error != 0) && (error != EINPROGRESS)) {
- mps_printf(sc, "%s: error %d returned from mps_map_command()\n",
+ mps_dprint(sc, MPS_ERROR,
+ "%s: error %d returned from mps_map_command()\n",
__func__, error);
goto bailout_error;
}
@@ -2836,7 +3001,7 @@
bailout_error:
mps_free_command(sc, cm);
- ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ mpssas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL);
xpt_done(ccb);
return;
@@ -2854,11 +3019,14 @@
/*
* Make sure the target exists.
*/
+ KASSERT(ccb->ccb_h.target_id < sassc->maxtargets,
+ ("Target %d out of bounds in XPT_SMP_IO\n", ccb->ccb_h.target_id));
targ = &sassc->targets[ccb->ccb_h.target_id];
if (targ->handle == 0x0) {
- mps_printf(sc, "%s: target %d does not exist!\n", __func__,
+ mps_dprint(sc, MPS_ERROR,
+ "%s: target %d does not exist!\n", __func__,
ccb->ccb_h.target_id);
- ccb->ccb_h.status = CAM_SEL_TIMEOUT;
+ mpssas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT);
xpt_done(ccb);
return;
}
@@ -2904,9 +3072,10 @@
#endif
if (targ->parent_handle == 0x0) {
- mps_printf(sc, "%s: handle %d does not have a valid "
+ mps_dprint(sc, MPS_ERROR,
+ "%s: handle %d does not have a valid "
"parent handle!\n", __func__, targ->handle);
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
goto bailout;
}
#ifdef OLD_MPS_PROBE
@@ -2914,18 +3083,20 @@
targ->parent_handle);
if (parent_target == NULL) {
- mps_printf(sc, "%s: handle %d does not have a valid "
+ mps_dprint(sc, MPS_ERROR,
+ "%s: handle %d does not have a valid "
"parent target!\n", __func__, targ->handle);
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
goto bailout;
}
if ((parent_target->devinfo &
MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) {
- mps_printf(sc, "%s: handle %d parent %d does not "
+ mps_dprint(sc, MPS_ERROR,
+ "%s: handle %d parent %d does not "
"have an SMP target!\n", __func__,
targ->handle, parent_target->handle);
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
goto bailout;
}
@@ -2934,18 +3105,20 @@
#else /* OLD_MPS_PROBE */
if ((targ->parent_devinfo &
MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) {
- mps_printf(sc, "%s: handle %d parent %d does not "
+ mps_dprint(sc, MPS_ERROR,
+ "%s: handle %d parent %d does not "
"have an SMP target!\n", __func__,
targ->handle, targ->parent_handle);
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
goto bailout;
}
if (targ->parent_sasaddr == 0x0) {
- mps_printf(sc, "%s: handle %d parent handle %d does "
+ mps_dprint(sc, MPS_ERROR,
+ "%s: handle %d parent handle %d does "
"not have a valid SAS address!\n",
__func__, targ->handle, targ->parent_handle);
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
goto bailout;
}
@@ -2955,9 +3128,10 @@
}
if (sasaddr == 0) {
- mps_printf(sc, "%s: unable to find SAS address for handle %d\n",
+ mps_dprint(sc, MPS_INFO,
+ "%s: unable to find SAS address for handle %d\n",
__func__, targ->handle);
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
goto bailout;
}
mpssas_send_smpcmd(sassc, ccb, sasaddr);
@@ -2978,14 +3152,18 @@
struct mps_command *tm;
struct mpssas_target *targ;
- mps_dprint(sassc->sc, MPS_TRACE, __func__);
+ MPS_FUNCTRACE(sassc->sc);
mtx_assert(&sassc->sc->mps_mtx, MA_OWNED);
+ KASSERT(ccb->ccb_h.target_id < sassc->maxtargets,
+ ("Target %d out of bounds in XPT_RESET_DEV\n",
+ ccb->ccb_h.target_id));
sc = sassc->sc;
tm = mps_alloc_command(sc);
if (tm == NULL) {
- mps_printf(sc, "comand alloc failure in mpssas_action_resetdev\n");
- ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ mps_dprint(sc, MPS_ERROR,
+ "command alloc failure in mpssas_action_resetdev\n");
+ mpssas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL);
xpt_done(ccb);
return;
}
@@ -3004,6 +3182,8 @@
tm->cm_complete = mpssas_resetdev_complete;
tm->cm_complete_data = ccb;
tm->cm_targ = targ;
+ targ->flags |= MPSSAS_TARGET_INRESET;
+
mps_map_command(sc, tm);
}
@@ -3013,7 +3193,7 @@
MPI2_SCSI_TASK_MANAGE_REPLY *resp;
union ccb *ccb;
- mps_dprint(sc, MPS_TRACE, __func__);
+ MPS_FUNCTRACE(sc);
mtx_assert(&sc->mps_mtx, MA_OWNED);
resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
@@ -3029,23 +3209,25 @@
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
- mps_printf(sc, "%s: cm_flags = %#x for reset of handle %#04x! "
+ mps_dprint(sc, MPS_ERROR,
+ "%s: cm_flags = %#x for reset of handle %#04x! "
"This should not happen!\n", __func__, tm->cm_flags,
req->DevHandle);
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
goto bailout;
}
- printf("%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__,
+ mps_dprint(sc, MPS_XINFO,
+ "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__,
le16toh(resp->IOCStatus), le32toh(resp->ResponseCode));
if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) {
- ccb->ccb_h.status = CAM_REQ_CMP;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP);
mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
CAM_LUN_WILDCARD);
}
else
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
bailout:
@@ -3072,114 +3254,6 @@
}
static void
-mpssas_rescan_done(struct cam_periph *periph, union ccb *done_ccb)
-{
- struct mpssas_softc *sassc;
- char path_str[64];
-
- if (done_ccb == NULL)
- return;
-
- sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
-
- mtx_assert(&sassc->sc->mps_mtx, MA_OWNED);
-
- xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
- mps_dprint(sassc->sc, MPS_INFO, "Completing rescan for %s\n", path_str);
-
- xpt_free_path(done_ccb->ccb_h.path);
- xpt_free_ccb(done_ccb);
-
-#if __FreeBSD_version < 1000006
- /*
- * Before completing scan, get EEDP stuff for all of the existing
- * targets.
- */
- mpssas_check_eedp(sassc);
-#endif
-
-}
-
-/* thread to handle bus rescans */
-static void
-mpssas_scanner_thread(void *arg)
-{
- struct mpssas_softc *sassc;
- struct mps_softc *sc;
- union ccb *ccb;
-
- sassc = (struct mpssas_softc *)arg;
- sc = sassc->sc;
-
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
-
- mps_lock(sc);
- for (;;) {
- /* Sleep for 1 second and check the queue status*/
- msleep(&sassc->ccb_scanq, &sc->mps_mtx, PRIBIO,
- "mps_scanq", 1 * hz);
- if (sassc->flags & MPSSAS_SHUTDOWN) {
- mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n");
- break;
- }
-next_work:
- // Get first work.
- ccb = (union ccb *)TAILQ_FIRST(&sassc->ccb_scanq);
- if (ccb == NULL)
- continue;
- // Got first work.
- TAILQ_REMOVE(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe);
- xpt_action(ccb);
- if (sassc->flags & MPSSAS_SHUTDOWN) {
- mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n");
- break;
- }
- goto next_work;
- }
-
- sassc->flags &= ~MPSSAS_SCANTHREAD;
- wakeup(&sassc->flags);
- mps_unlock(sc);
- mps_dprint(sc, MPS_TRACE, "Scanner exiting\n");
- mps_kproc_exit(0);
-}
-
-/*
- * This function will send READ_CAP_16 to find out EEDP protection mode.
- * It will check inquiry data before sending READ_CAP_16.
- * Callback for READ_CAP_16 is "mpssas_read_cap_done".
- * This is insternal scsi command and we need to take care release of devq, if
- * CAM_DEV_QFRZN is set. Driver needs to release devq if it has frozen any.
- * xpt_release_devq is called from mpssas_read_cap_done.
- *
- * All other commands will be handled by periph layer and there it will
- * check for "CAM_DEV_QFRZN" and release of devq will be done.
- */
-static void
-mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb)
-{
- char path_str[64];
-
- mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
-
- mtx_assert(&sassc->sc->mps_mtx, MA_OWNED);
-
- if (ccb == NULL)
- return;
-
- xpt_path_string(ccb->ccb_h.path, path_str, sizeof(path_str));
- mps_dprint(sassc->sc, MPS_INFO, "Queueing rescan for %s\n", path_str);
-
- /* Prepare request */
- ccb->ccb_h.ppriv_ptr1 = sassc;
- ccb->ccb_h.cbfcnp = mpssas_rescan_done;
- xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, MPS_PRIORITY_XPT);
- TAILQ_INSERT_TAIL(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe);
- wakeup(&sassc->ccb_scanq);
-}
-
-#if __FreeBSD_version >= 1000006
-static void
mpssas_async(void *callback_arg, uint32_t code, struct cam_path *path,
void *arg)
{
@@ -3188,6 +3262,8 @@
sc = (struct mps_softc *)callback_arg;
switch (code) {
+#if (__FreeBSD_version >= 1000006) || \
+ ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000))
case AC_ADVINFO_CHANGED: {
struct mpssas_target *target;
struct mpssas_softc *sassc;
@@ -3210,15 +3286,11 @@
break;
/*
- * We're only interested in devices that are attached to
- * this controller.
- */
- if (xpt_path_path_id(path) != sassc->sim->path_id)
- break;
-
- /*
* We should have a handle for this, but check to make sure.
*/
+ KASSERT(xpt_path_target_id(path) < sassc->maxtargets,
+ ("Target %d out of bounds in mpssas_async\n",
+ xpt_path_target_id(path)));
target = &sassc->targets[xpt_path_target_id(path)];
if (target->handle == 0)
break;
@@ -3236,7 +3308,7 @@
lun = malloc(sizeof(struct mpssas_lun), M_MPT2,
M_NOWAIT | M_ZERO);
if (lun == NULL) {
- mps_dprint(sc, MPS_FAULT, "Unable to alloc "
+ mps_dprint(sc, MPS_ERROR, "Unable to alloc "
"LUN for EEDP support.\n");
break;
}
@@ -3249,7 +3321,12 @@
cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
cdai.ccb_h.flags = CAM_DIR_IN;
cdai.buftype = CDAI_TYPE_RCAPLONG;
+#if (__FreeBSD_version >= 1100061) || \
+ ((__FreeBSD_version >= 1001510) && (__FreeBSD_version < 1100000))
+ cdai.flags = CDAI_FLAG_NONE;
+#else
cdai.flags = 0;
+#endif
cdai.bufsiz = sizeof(rcap_buf);
cdai.buf = (uint8_t *)&rcap_buf;
xpt_action((union ccb *)&cdai);
@@ -3257,7 +3334,7 @@
cam_release_devq(cdai.ccb_h.path,
0, 0, 0, FALSE);
- if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
+ if ((mpssas_get_ccbstatus((union ccb *)&cdai) == CAM_REQ_CMP)
&& (rcap_buf.prot & SRC16_PROT_EN)) {
lun->eedp_formatted = TRUE;
lun->eedp_block_size = scsi_4btoul(rcap_buf.length);
@@ -3267,178 +3344,152 @@
}
break;
}
+#else
+ case AC_FOUND_DEVICE: {
+ struct ccb_getdev *cgd;
+
+ cgd = arg;
+ mpssas_check_eedp(sc, path, cgd);
+ break;
+ }
+#endif
default:
break;
}
}
-#else /* __FreeBSD_version >= 1000006 */
+#if (__FreeBSD_version < 901503) || \
+ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006))
static void
-mpssas_check_eedp(struct mpssas_softc *sassc)
+mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path,
+ struct ccb_getdev *cgd)
{
- struct mps_softc *sc = sassc->sc;
+ struct mpssas_softc *sassc = sc->sassc;
struct ccb_scsiio *csio;
struct scsi_read_capacity_16 *scsi_cmd;
struct scsi_read_capacity_eedp *rcap_buf;
- union ccb *ccb;
- path_id_t pathid = cam_sim_path(sassc->sim);
+ path_id_t pathid;
target_id_t targetid;
lun_id_t lunid;
- struct cam_periph *found_periph;
+ union ccb *ccb;
+ struct cam_path *local_path;
struct mpssas_target *target;
struct mpssas_lun *lun;
uint8_t found_lun;
- struct ccb_getdev cgd;
char path_str[64];
+ sassc = sc->sassc;
+ pathid = cam_sim_path(sassc->sim);
+ targetid = xpt_path_target_id(path);
+ lunid = xpt_path_lun_id(path);
+
+ KASSERT(targetid < sassc->maxtargets,
+ ("Target %d out of bounds in mpssas_check_eedp\n",
+ targetid));
+ target = &sassc->targets[targetid];
+ if (target->handle == 0x0)
+ return;
+
/*
- * Issue a READ CAPACITY 16 command to each LUN of each target. This
- * info is used to determine if the LUN is formatted for EEDP support.
+ * Determine if the device is EEDP capable.
+ *
+ * If this flag is set in the inquiry data,
+ * the device supports protection information,
+ * and must support the 16 byte read
+ * capacity command, otherwise continue without
+ * sending read cap 16
*/
- for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
- target = &sassc->targets[targetid];
- if (target->handle == 0x0) {
- continue;
- }
+ if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0)
+ return;
- lunid = 0;
- do {
- ccb = xpt_alloc_ccb_nowait();
- if (ccb == NULL) {
- mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB "
- "for EEDP support.\n");
- return;
- }
+ /*
+ * Issue a READ CAPACITY 16 command. This info
+ * is used to determine if the LUN is formatted
+ * for EEDP support.
+ */
+ ccb = xpt_alloc_ccb_nowait();
+ if (ccb == NULL) {
+ mps_dprint(sc, MPS_ERROR, "Unable to alloc CCB "
+ "for EEDP support.\n");
+ return;
+ }
- if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
- pathid, targetid, lunid) != CAM_REQ_CMP) {
- mps_dprint(sc, MPS_FAULT, "Unable to create "
- "path for EEDP support\n");
- xpt_free_ccb(ccb);
- return;
- }
+ if (xpt_create_path(&local_path, xpt_periph,
+ pathid, targetid, lunid) != CAM_REQ_CMP) {
+ mps_dprint(sc, MPS_ERROR, "Unable to create "
+ "path for EEDP support\n");
+ xpt_free_ccb(ccb);
+ return;
+ }
- /*
- * If a periph is returned, the LUN exists. Create an
- * entry in the target's LUN list.
- */
- if ((found_periph = cam_periph_find(ccb->ccb_h.path,
- NULL)) != NULL) {
- /*
- * If LUN is already in list, don't create a new
- * one.
- */
- found_lun = FALSE;
- SLIST_FOREACH(lun, &target->luns, lun_link) {
- if (lun->lun_id == lunid) {
- found_lun = TRUE;
- break;
- }
- }
- if (!found_lun) {
- lun = malloc(sizeof(struct mpssas_lun),
- M_MPT2, M_NOWAIT | M_ZERO);
- if (lun == NULL) {
- mps_dprint(sc, MPS_FAULT,
- "Unable to alloc LUN for "
- "EEDP support.\n");
- xpt_free_path(ccb->ccb_h.path);
- xpt_free_ccb(ccb);
- return;
- }
- lun->lun_id = lunid;
- SLIST_INSERT_HEAD(&target->luns, lun,
- lun_link);
- }
- lunid++;
- /* Before Issuing READ CAPACITY 16,
- * check Device type.
- */
- xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path,
- CAM_PRIORITY_NORMAL);
- cgd.ccb_h.func_code = XPT_GDEV_TYPE;
- xpt_action((union ccb *)&cgd);
+ /*
+ * If LUN is already in list, don't create a new
+ * one.
+ */
+ found_lun = FALSE;
+ SLIST_FOREACH(lun, &target->luns, lun_link) {
+ if (lun->lun_id == lunid) {
+ found_lun = TRUE;
+ break;
+ }
+ }
+ if (!found_lun) {
+ lun = malloc(sizeof(struct mpssas_lun), M_MPT2,
+ M_NOWAIT | M_ZERO);
+ if (lun == NULL) {
+ mps_dprint(sc, MPS_ERROR,
+ "Unable to alloc LUN for EEDP support.\n");
+ xpt_free_path(local_path);
+ xpt_free_ccb(ccb);
+ return;
+ }
+ lun->lun_id = lunid;
+ SLIST_INSERT_HEAD(&target->luns, lun,
+ lun_link);
+ }
- /*
- * If this flag is set in the inquiry data,
- * the device supports protection information,
- * and must support the 16 byte read
- * capacity command, otherwise continue without
- * sending read cap 16
- */
+ xpt_path_string(local_path, path_str, sizeof(path_str));
- xpt_path_string(ccb->ccb_h.path, path_str,
- sizeof(path_str));
+ mps_dprint(sc, MPS_INFO, "Sending read cap: path %s handle %d\n",
+ path_str, target->handle);
- if ((cgd.inq_data.spc3_flags &
- SPC3_SID_PROTECT) == 0) {
- xpt_free_path(ccb->ccb_h.path);
- xpt_free_ccb(ccb);
- continue;
- }
-
- mps_dprint(sc, MPS_INFO,
- "Sending read cap: path %s"
- " handle %d\n", path_str, target->handle );
-
- /*
- * Issue a READ CAPACITY 16 command for the LUN.
- * The mpssas_read_cap_done function will load
- * the read cap info into the LUN struct.
- */
- rcap_buf =
- malloc(sizeof(struct scsi_read_capacity_eedp),
- M_MPT2, M_NOWAIT| M_ZERO);
- if (rcap_buf == NULL) {
- mps_dprint(sc, MPS_FAULT, "Unable to alloc read "
- "capacity buffer for EEDP support.\n");
- xpt_free_path(ccb->ccb_h.path);
- xpt_free_ccb(ccb);
- return;
- }
- csio = &ccb->csio;
- csio->ccb_h.func_code = XPT_SCSI_IO;
- csio->ccb_h.flags = CAM_DIR_IN;
- csio->ccb_h.retry_count = 4;
- csio->ccb_h.cbfcnp = mpssas_read_cap_done;
- csio->ccb_h.timeout = 60000;
- csio->data_ptr = (uint8_t *)rcap_buf;
- csio->dxfer_len = sizeof(struct
- scsi_read_capacity_eedp);
- csio->sense_len = MPS_SENSE_LEN;
- csio->cdb_len = sizeof(*scsi_cmd);
- csio->tag_action = MSG_SIMPLE_Q_TAG;
+ /*
+ * Issue a READ CAPACITY 16 command for the LUN.
+ * The mpssas_read_cap_done function will load
+ * the read cap info into the LUN struct.
+ */
+ rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp),
+ M_MPT2, M_NOWAIT | M_ZERO);
+ if (rcap_buf == NULL) {
+ mps_dprint(sc, MPS_FAULT,
+ "Unable to alloc read capacity buffer for EEDP support.\n");
+ xpt_free_path(ccb->ccb_h.path);
+ xpt_free_ccb(ccb);
+ return;
+ }
+ xpt_setup_ccb(&ccb->ccb_h, local_path, CAM_PRIORITY_XPT);
+ csio = &ccb->csio;
+ csio->ccb_h.func_code = XPT_SCSI_IO;
+ csio->ccb_h.flags = CAM_DIR_IN;
+ csio->ccb_h.retry_count = 4;
+ csio->ccb_h.cbfcnp = mpssas_read_cap_done;
+ csio->ccb_h.timeout = 60000;
+ csio->data_ptr = (uint8_t *)rcap_buf;
+ csio->dxfer_len = sizeof(struct scsi_read_capacity_eedp);
+ csio->sense_len = MPS_SENSE_LEN;
+ csio->cdb_len = sizeof(*scsi_cmd);
+ csio->tag_action = MSG_SIMPLE_Q_TAG;
- scsi_cmd = (struct scsi_read_capacity_16 *)
- &csio->cdb_io.cdb_bytes;
- bzero(scsi_cmd, sizeof(*scsi_cmd));
- scsi_cmd->opcode = 0x9E;
- scsi_cmd->service_action = SRC16_SERVICE_ACTION;
- ((uint8_t *)scsi_cmd)[13] = sizeof(struct
- scsi_read_capacity_eedp);
+ scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes;
+ bzero(scsi_cmd, sizeof(*scsi_cmd));
+ scsi_cmd->opcode = 0x9E;
+ scsi_cmd->service_action = SRC16_SERVICE_ACTION;
+ ((uint8_t *)scsi_cmd)[13] = sizeof(struct scsi_read_capacity_eedp);
- /*
- * Set the path, target and lun IDs for the READ
- * CAPACITY request.
- */
- ccb->ccb_h.path_id =
- xpt_path_path_id(ccb->ccb_h.path);
- ccb->ccb_h.target_id =
- xpt_path_target_id(ccb->ccb_h.path);
- ccb->ccb_h.target_lun =
- xpt_path_lun_id(ccb->ccb_h.path);
-
- ccb->ccb_h.ppriv_ptr1 = sassc;
- xpt_action(ccb);
- } else {
- xpt_free_path(ccb->ccb_h.path);
- xpt_free_ccb(ccb);
- }
- } while (found_periph);
- }
+ ccb->ccb_h.ppriv_ptr1 = sassc;
+ xpt_action(ccb);
}
-
static void
mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb)
{
@@ -3471,6 +3522,9 @@
* target.
*/
sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
+ KASSERT(done_ccb->ccb_h.target_id < sassc->maxtargets,
+ ("Target %d out of bounds in mpssas_read_cap_done\n",
+ done_ccb->ccb_h.target_id));
target = &sassc->targets[done_ccb->ccb_h.target_id];
SLIST_FOREACH(lun, &target->luns, lun_link) {
if (lun->lun_id != done_ccb->ccb_h.target_lun)
@@ -3483,7 +3537,7 @@
* the lun as not supporting EEDP and set the block size
* to 0.
*/
- if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+ if ((mpssas_get_ccbstatus(done_ccb) != CAM_REQ_CMP)
|| (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) {
lun->eedp_formatted = FALSE;
lun->eedp_block_size = 0;
@@ -3491,6 +3545,10 @@
}
if (rcap_buf->protect & 0x01) {
+ mps_dprint(sassc->sc, MPS_INFO, "LUN %d for "
+ "target ID %d is formatted for EEDP "
+ "support.\n", done_ccb->ccb_h.target_lun,
+ done_ccb->ccb_h.target_id);
lun->eedp_formatted = TRUE;
lun->eedp_block_size = scsi_4btoul(rcap_buf->length);
}
@@ -3502,12 +3560,40 @@
xpt_free_path(done_ccb->ccb_h.path);
xpt_free_ccb(done_ccb);
}
-#endif /* __FreeBSD_version >= 1000006 */
+#endif /* (__FreeBSD_version < 901503) || \
+ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */
+void
+mpssas_prepare_for_tm(struct mps_softc *sc, struct mps_command *tm,
+ struct mpssas_target *target, lun_id_t lun_id)
+{
+ union ccb *ccb;
+ path_id_t path_id;
+
+ /*
+ * Set the INRESET flag for this target so that no I/O will be sent to
+ * the target until the reset has completed. If an I/O request does
+ * happen, the devq will be frozen. The CCB holds the path which is
+ * used to release the devq. The devq is released and the CCB is freed
+ * when the TM completes.
+ */
+ ccb = xpt_alloc_ccb_nowait();
+ if (ccb) {
+ path_id = cam_sim_path(sc->sassc->sim);
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id,
+ target->tid, lun_id) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ } else {
+ tm->cm_ccb = ccb;
+ tm->cm_targ = target;
+ target->flags |= MPSSAS_TARGET_INRESET;
+ }
+ }
+}
+
int
mpssas_startup(struct mps_softc *sc)
{
- struct mpssas_softc *sassc;
/*
* Send the port enable message and set the wait_for_port_enable flag.
@@ -3514,8 +3600,6 @@
* This flag helps to keep the simq frozen until all discovery events
* are processed.
*/
- sassc = sc->sassc;
- mpssas_startup_increment(sassc);
sc->wait_for_port_enable = 1;
mpssas_send_portenable(sc);
return (0);
@@ -3527,7 +3611,7 @@
MPI2_PORT_ENABLE_REQUEST *request;
struct mps_command *cm;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
if ((cm = mps_alloc_command(sc)) == NULL)
return (EBUSY);
@@ -3541,7 +3625,7 @@
cm->cm_sge = NULL;
mps_map_command(sc, cm);
- mps_dprint(sc, MPS_TRACE,
+ mps_dprint(sc, MPS_XINFO,
"mps_send_portenable finished cm %p req %p complete %p\n",
cm, cm->cm_req, cm->cm_complete);
return (0);
@@ -3553,7 +3637,7 @@
MPI2_PORT_ENABLE_REPLY *reply;
struct mpssas_softc *sassc;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ MPS_FUNCTRACE(sc);
sassc = sc->sassc;
/*
@@ -3562,7 +3646,7 @@
* port enable commands don't have S/G lists.
*/
if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
- mps_printf(sc, "%s: cm_flags = %#x for port enable! "
+ mps_dprint(sc, MPS_ERROR, "%s: cm_flags = %#x for port enable! "
"This should not happen!\n", __func__, cm->cm_flags);
}
@@ -3575,7 +3659,7 @@
mps_free_command(sc, cm);
if (sc->mps_ich.ich_arg != NULL) {
- mps_dprint(sc, MPS_INFO, "disestablish config intrhook\n");
+ mps_dprint(sc, MPS_XINFO, "disestablish config intrhook\n");
config_intrhook_disestablish(&sc->mps_ich);
sc->mps_ich.ich_arg = NULL;
}
@@ -3600,6 +3684,52 @@
sc->port_enable_complete = 1;
wakeup(&sc->port_enable_complete);
mpssas_startup_decrement(sassc);
- xpt_release_simq(sassc->sim, 1);
}
+int
+mpssas_check_id(struct mpssas_softc *sassc, int id)
+{
+ struct mps_softc *sc = sassc->sc;
+ char *ids;
+ char *name;
+
+ ids = &sc->exclude_ids[0];
+ while((name = strsep(&ids, ",")) != NULL) {
+ if (name[0] == '\0')
+ continue;
+ if (strtol(name, NULL, 0) == (long)id)
+ return (1);
+ }
+
+ return (0);
+}
+
+void
+mpssas_realloc_targets(struct mps_softc *sc, int maxtargets)
+{
+ struct mpssas_softc *sassc;
+ struct mpssas_lun *lun, *lun_tmp;
+ struct mpssas_target *targ;
+ int i;
+
+ sassc = sc->sassc;
+ /*
+ * The number of targets is based on IOC Facts, so free all of
+ * the allocated LUNs for each target and then the target buffer
+ * itself.
+ */
+ for (i=0; i< maxtargets; i++) {
+ targ = &sassc->targets[i];
+ SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) {
+ free(lun, M_MPT2);
+ }
+ }
+ free(sassc->targets, M_MPT2);
+
+ sassc->targets = malloc(sizeof(struct mpssas_target) * maxtargets,
+ M_MPT2, M_WAITOK|M_ZERO);
+ if (!sassc->targets) {
+ panic("%s failed to alloc targets with error %d\n",
+ __func__, ENOMEM);
+ }
+}
Modified: trunk/sys/dev/mps/mps_sas.h
===================================================================
--- trunk/sys/dev/mps/mps_sas.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_sas.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,9 +25,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mps_sas.h 281564 2015-04-15 21:47:15Z slm $
*/
struct mps_fw_event_work;
@@ -51,11 +53,10 @@
#define MPSSAS_TARGET_INREMOVAL (1 << 3)
#define MPS_TARGET_FLAGS_RAID_COMPONENT (1 << 4)
#define MPS_TARGET_FLAGS_VOLUME (1 << 5)
+#define MPS_TARGET_IS_SATA_SSD (1 << 6)
#define MPSSAS_TARGET_INRECOVERY (MPSSAS_TARGET_INABORT | \
MPSSAS_TARGET_INRESET | MPSSAS_TARGET_INCHIPRESET)
-#define MPSSAS_TARGET_ADD (1 << 29)
-#define MPSSAS_TARGET_REMOVE (1 << 30)
uint16_t tid;
SLIST_HEAD(, mpssas_lun) luns;
TAILQ_HEAD(, mps_command) commands;
@@ -77,6 +78,8 @@
unsigned int aborts;
unsigned int logical_unit_resets;
unsigned int target_resets;
+ uint8_t stop_at_shutdown;
+ uint8_t supports_SSU;
};
struct mpssas_softc {
@@ -87,7 +90,7 @@
#define MPSSAS_DISCOVERY_TIMEOUT_PENDING (1 << 2)
#define MPSSAS_QUEUE_FROZEN (1 << 3)
#define MPSSAS_SHUTDOWN (1 << 4)
-#define MPSSAS_SCANTHREAD (1 << 5)
+ u_int maxtargets;
struct mpssas_target *targets;
struct cam_devq *devq;
struct cam_sim *sim;
@@ -94,16 +97,11 @@
struct cam_path *path;
struct intr_config_hook sas_ich;
struct callout discovery_callout;
- u_int discovery_timeouts;
struct mps_event_handle *mpssas_eh;
u_int startup_refcount;
- u_int tm_count;
struct proc *sysctl_proc;
- TAILQ_HEAD(, ccb_hdr) ccb_scanq;
- struct proc *rescan_thread;
-
struct taskqueue *ev_tq;
struct task ev_task;
TAILQ_HEAD(, mps_fw_event_work) ev_queue;
@@ -148,6 +146,19 @@
return (0);
}
+static __inline void
+mpssas_set_ccbstatus(union ccb *ccb, int status)
+{
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= status;
+}
+
+static __inline int
+mpssas_get_ccbstatus(union ccb *ccb)
+{
+ return (ccb->ccb_h.status & CAM_STATUS_MASK);
+}
+
#define MPS_SET_SINGLE_LUN(req, lun) \
do { \
bzero((req)->LUN, 8); \
@@ -156,9 +167,10 @@
void mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ);
void mpssas_discovery_end(struct mpssas_softc *sassc);
+void mpssas_prepare_for_tm(struct mps_softc *sc, struct mps_command *tm,
+ struct mpssas_target *target, lun_id_t lun_id);
void mpssas_startup_increment(struct mpssas_softc *sassc);
void mpssas_startup_decrement(struct mpssas_softc *sassc);
-struct mps_command * mpssas_alloc_tm(struct mps_softc *sc);
-void mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm);
void mpssas_firmware_event_work(void *arg, int pending);
+int mpssas_check_id(struct mpssas_softc *sassc, int id);
Modified: trunk/sys/dev/mps/mps_sas_lsi.c
===================================================================
--- trunk/sys/dev/mps/mps_sas_lsi.c 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_sas_lsi.c 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,5 +1,7 @@
+/* $MidnightBSD$ */
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/mps/mps_sas_lsi.c 322661 2017-08-18 15:38:08Z ken $");
-/* Communications core for LSI MPT2 */
+/* Communications core for Avago Technologies (LSI) MPT2 */
/* TODO Move headers to mpsvar */
#include <sys/types.h>
@@ -105,7 +107,9 @@
u16 serial_number[10]; /* 10-19 */
u16 reserved2[7]; /* 20-26 */
u16 model_number[20]; /* 27-46*/
- u16 reserved3[209]; /* 47-255*/
+ u16 reserved3[170]; /* 47-216 */
+ u16 rotational_speed; /* 217 */
+ u16 reserved4[38]; /* 218-255 */
};
static u32 event_count;
static void mpssas_fw_work(struct mps_softc *sc,
@@ -116,10 +120,14 @@
static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
u32 devinfo);
+static void mpssas_ata_id_timeout(void *data);
int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
- u64 *sas_address, u16 handle, u32 device_info);
+ u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
static int mpssas_volume_add(struct mps_softc *sc,
u16 handle);
+static void mpssas_SSU_to_SATA_devices(struct mps_softc *sc);
+static void mpssas_stop_unit_done(struct cam_periph *periph,
+ union ccb *done_ccb);
void
mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
@@ -129,7 +137,7 @@
u16 sz;
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
- mps_print_evt_sas(sc, event);
+ MPS_DPRINT_EVENT(sc, sas, event);
mpssas_record_event(sc, event);
fw_event = malloc(sizeof(struct mps_fw_event_work), M_MPT2,
@@ -191,7 +199,7 @@
struct mpssas_softc *sassc;
sassc = sc->sassc;
- mps_dprint(sc, MPS_INFO, "(%d)->(%s) Working on Event: [%x]\n",
+ mps_dprint(sc, MPS_EVENT, "(%d)->(%s) Working on Event: [%x]\n",
event_count++,__func__,fw_event->event);
switch (fw_event->event) {
case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
@@ -210,9 +218,11 @@
switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) {
case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
if (mpssas_add_device(sc,
- le16toh(phy->AttachedDevHandle), phy->LinkRate)){
- printf("%s: failed to add device with "
- "handle 0x%x\n", __func__,
+ le16toh(phy->AttachedDevHandle),
+ phy->LinkRate)){
+ mps_dprint(sc, MPS_ERROR, "%s: "
+ "failed to add device with handle "
+ "0x%x\n", __func__,
le16toh(phy->AttachedDevHandle));
mpssas_prepare_remove(sassc, le16toh(
phy->AttachedDevHandle));
@@ -276,8 +286,8 @@
element =
(Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
- id = mps_mapping_get_raid_id_from_handle
- (sc, element->VolDevHandle);
+ id = mps_mapping_get_raid_tid_from_handle(sc,
+ element->VolDevHandle);
mps_mapping_ir_config_change_event(sc, event_data);
@@ -286,7 +296,8 @@
case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
case MPI2_EVENT_IR_CHANGE_RC_ADDED:
if (!foreign_config) {
- if (mpssas_volume_add(sc, le16toh(element->VolDevHandle))){
+ if (mpssas_volume_add(sc,
+ le16toh(element->VolDevHandle))){
printf("%s: failed to add RAID "
"volume with handle 0x%x\n",
__func__, le16toh(element->
@@ -326,12 +337,16 @@
* Phys Disk of a volume has been created. Hide
* it from the OS.
*/
- targ = mpssas_find_target_by_handle(sassc, 0, element->PhysDiskDevHandle);
+ targ = mpssas_find_target_by_handle(sassc, 0,
+ element->PhysDiskDevHandle);
if (targ == NULL)
break;
- /* Set raid component flags only if it is not WD.
- * OR WrapDrive with WD_HIDE_ALWAYS/WD_HIDE_IF_VOLUME is set in NVRAM
+ /*
+ * Set raid component flags only if it is not
+ * WD. OR WrapDrive with
+ * WD_HIDE_ALWAYS/WD_HIDE_IF_VOLUME is set in
+ * NVRAM
*/
if((!sc->WD_available) ||
((sc->WD_available &&
@@ -374,10 +389,10 @@
/*
* Informational only.
*/
- mps_dprint(sc, MPS_INFO, "Received IR Volume event:\n");
+ mps_dprint(sc, MPS_EVENT, "Received IR Volume event:\n");
switch (event_data->ReasonCode) {
case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
- mps_dprint(sc, MPS_INFO, " Volume Settings "
+ mps_dprint(sc, MPS_EVENT, " Volume Settings "
"changed from 0x%x to 0x%x for Volome with "
"handle 0x%x", le32toh(event_data->PreviousValue),
le32toh(event_data->NewValue),
@@ -384,7 +399,7 @@
le16toh(event_data->VolDevHandle));
break;
case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
- mps_dprint(sc, MPS_INFO, " Volume Status "
+ mps_dprint(sc, MPS_EVENT, " Volume Status "
"changed from 0x%x to 0x%x for Volome with "
"handle 0x%x", le32toh(event_data->PreviousValue),
le32toh(event_data->NewValue),
@@ -391,7 +406,7 @@
le16toh(event_data->VolDevHandle));
break;
case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
- mps_dprint(sc, MPS_INFO, " Volume State "
+ mps_dprint(sc, MPS_EVENT, " Volume State "
"changed from 0x%x to 0x%x for Volome with "
"handle 0x%x", le32toh(event_data->PreviousValue),
le32toh(event_data->NewValue),
@@ -440,10 +455,10 @@
/*
* Informational only.
*/
- mps_dprint(sc, MPS_INFO, "Received IR Phys Disk event:\n");
+ mps_dprint(sc, MPS_EVENT, "Received IR Phys Disk event:\n");
switch (event_data->ReasonCode) {
case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
- mps_dprint(sc, MPS_INFO, " Phys Disk Settings "
+ mps_dprint(sc, MPS_EVENT, " Phys Disk Settings "
"changed from 0x%x to 0x%x for Phys Disk Number "
"%d and handle 0x%x at Enclosure handle 0x%x, Slot "
"%d", le32toh(event_data->PreviousValue),
@@ -453,7 +468,7 @@
le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
break;
case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
- mps_dprint(sc, MPS_INFO, " Phys Disk Status changed "
+ mps_dprint(sc, MPS_EVENT, " Phys Disk Status changed "
"from 0x%x to 0x%x for Phys Disk Number %d and "
"handle 0x%x at Enclosure handle 0x%x, Slot %d",
le32toh(event_data->PreviousValue),
@@ -462,7 +477,7 @@
le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
break;
case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
- mps_dprint(sc, MPS_INFO, " Phys Disk State changed "
+ mps_dprint(sc, MPS_EVENT, " Phys Disk State changed "
"from 0x%x to 0x%x for Phys Disk Number %d and "
"handle 0x%x at Enclosure handle 0x%x, Slot %d",
le32toh(event_data->PreviousValue),
@@ -518,8 +533,8 @@
/*
* Informational only.
*/
- mps_dprint(sc, MPS_INFO, "Received IR Op Status event:\n");
- mps_dprint(sc, MPS_INFO, " RAID Operation of %d is %d "
+ mps_dprint(sc, MPS_EVENT, "Received IR Op Status event:\n");
+ mps_dprint(sc, MPS_EVENT, " RAID Operation of %d is %d "
"percent complete for Volume with handle 0x%x",
event_data->RAIDOperation, event_data->PercentComplete,
le16toh(event_data->VolDevHandle));
@@ -577,7 +592,7 @@
break;
}
- mps_dprint(sc, MPS_INFO, "(%d)->(%s) Event Free: [%x]\n",event_count,__func__, fw_event->event);
+ mps_dprint(sc, MPS_EVENT, "(%d)->(%s) Event Free: [%x]\n",event_count,__func__, fw_event->event);
mpssas_fw_event_free(sc, fw_event);
}
@@ -603,14 +618,14 @@
struct mpssas_target *targ;
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t config_page;
- uint64_t sas_address, sata_sas_address;
+ uint64_t sas_address;
uint64_t parent_sas_address = 0;
- u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
u32 device_info, parent_devinfo = 0;
unsigned int id;
- int ret;
- int error = 0;
+ int ret = 1, error = 0, i;
struct mpssas_lun *lun;
+ u8 is_SATA_SSD = 0;
+ struct mps_command *cm;
sassc = sc->sassc;
mpssas_startup_increment(sassc);
@@ -642,36 +657,81 @@
}
/* TODO Check proper endianess */
sas_address = config_page.SASAddress.High;
- sas_address = (sas_address << 32) |
- config_page.SASAddress.Low;
+ sas_address = (sas_address << 32) | config_page.SASAddress.Low;
- if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE)
- == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
- if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
- ret = mpssas_get_sas_address_for_sata_disk(sc,
- &sata_sas_address, handle, device_info);
- if (!ret)
- id = mps_mapping_get_sas_id(sc,
- sata_sas_address, handle);
- else
- id = mps_mapping_get_sas_id(sc,
- sas_address, handle);
- } else
- id = mps_mapping_get_sas_id(sc, sas_address,
- handle);
- } else
- id = mps_mapping_get_sas_id(sc, sas_address, handle);
+ /*
+ * Always get SATA Identify information because this is used to
+ * determine if Start/Stop Unit should be sent to the drive when the
+ * system is shutdown.
+ */
+ if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
+ ret = mpssas_get_sas_address_for_sata_disk(sc, &sas_address,
+ handle, device_info, &is_SATA_SSD);
+ if (ret) {
+ mps_dprint(sc, MPS_INFO, "%s: failed to get disk type "
+ "(SSD or HDD) for SATA device with handle 0x%04x\n",
+ __func__, handle);
+ } else {
+ mps_dprint(sc, MPS_INFO, "SAS Address from SATA "
+ "device = %jx\n", sas_address);
+ }
+ }
+ /*
+ * use_phynum:
+ * 1 - use the PhyNum field as a fallback to the mapping logic
+ * 0 - never use the PhyNum field
+ * -1 - only use the PhyNum field
+ *
+ * Note that using the Phy number to map a device can cause device adds
+ * to fail if multiple enclosures/expanders are in the topology. For
+ * example, if two devices are in the same slot number in two different
+ * enclosures within the topology, only one of those devices will be
+ * added. PhyNum mapping should not be used if multiple enclosures are
+ * in the topology.
+ */
+ id = MPS_MAP_BAD_ID;
+ if (sc->use_phynum != -1)
+ id = mps_mapping_get_tid(sc, sas_address, handle);
if (id == MPS_MAP_BAD_ID) {
- printf("failure at %s:%d/%s()! Could not get ID for device "
- "with handle 0x%04x\n", __FILE__, __LINE__, __func__,
- handle);
- error = ENXIO;
- goto out;
+ if ((sc->use_phynum == 0)
+ || ((id = config_page.PhyNum) > sassc->maxtargets)) {
+ mps_dprint(sc, MPS_INFO, "failure at %s:%d/%s()! "
+ "Could not get ID for device with handle 0x%04x\n",
+ __FILE__, __LINE__, __func__, handle);
+ error = ENXIO;
+ goto out;
+ }
}
- mps_dprint(sc, MPS_INFO, "SAS Address from SAS device page0 = %jx\n",
+ mps_dprint(sc, MPS_MAPPING, "%s: Target ID for added device is %d.\n",
+ __func__, id);
+
+ /*
+ * Only do the ID check and reuse check if the target is not from a
+ * RAID Component. For Physical Disks of a Volume, the ID will be reused
+ * when a volume is deleted because the mapping entry for the PD will
+ * still be in the mapping table. The ID check should not be done here
+ * either since this PD is already being used.
+ */
+ targ = &sassc->targets[id];
+ if (!(targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT)) {
+ if (mpssas_check_id(sassc, id) != 0) {
+ device_printf(sc->mps_dev, "Excluding target id %d\n",
+ id);
+ error = ENXIO;
+ goto out;
+ }
+
+ if (targ->handle != 0x0) {
+ mps_dprint(sc, MPS_MAPPING, "Attempting to reuse "
+ "target id %d handle 0x%04x\n", id, targ->handle);
+ error = ENXIO;
+ goto out;
+ }
+ }
+
+ mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n",
sas_address);
- targ = &sassc->targets[id];
targ->devinfo = device_info;
targ->devname = le32toh(config_page.DeviceName.High);
targ->devname = (targ->devname << 32) |
@@ -686,6 +746,9 @@
targ->tid = id;
targ->linkrate = (linkrate>>4);
targ->flags = 0;
+ if (is_SATA_SSD) {
+ targ->flags = MPS_TARGET_IS_SATA_SSD;
+ }
TAILQ_INIT(&targ->commands);
TAILQ_INIT(&targ->timedout_commands);
while(!SLIST_EMPTY(&targ->luns)) {
@@ -696,21 +759,66 @@
SLIST_INIT(&targ->luns);
mps_describe_devinfo(targ->devinfo, devstring, 80);
- mps_dprint(sc, MPS_INFO, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
- mps_describe_table(mps_linkrate_names, targ->linkrate),
+ mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n",
+ devstring, mps_describe_table(mps_linkrate_names, targ->linkrate),
targ->handle, targ->encl_handle, targ->encl_slot);
+
+#if __FreeBSD_version < 1000039
if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
+#endif
mpssas_rescan_target(sc, targ);
- mps_dprint(sc, MPS_INFO, "Target id 0x%x added\n", targ->tid);
+ mps_dprint(sc, MPS_MAPPING, "Target id 0x%x added\n", targ->tid);
+
+ /*
+ * Check all commands to see if the SATA_ID_TIMEOUT flag has been set.
+ * If so, send a Target Reset TM to the target that was just created.
+ * An Abort Task TM should be used instead of a Target Reset, but that
+ * would be much more difficult because targets have not been fully
+ * discovered yet, and LUN's haven't been setup. So, just reset the
+ * target instead of the LUN.
+ */
+ for (i = 1; i < sc->num_reqs; i++) {
+ cm = &sc->commands[i];
+ if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) {
+ targ->timeouts++;
+ cm->cm_state = MPS_CM_STATE_TIMEDOUT;
+
+ if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) {
+ mps_dprint(sc, MPS_INFO, "%s: sending Target "
+ "Reset for stuck SATA identify command "
+ "(cm = %p)\n", __func__, cm);
+ targ->tm->cm_targ = targ;
+ mpssas_send_reset(sc, targ->tm,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
+ } else {
+ mps_dprint(sc, MPS_ERROR, "Failed to allocate "
+ "tm for Target Reset after SATA ID command "
+ "timed out (cm %p)\n", cm);
+ }
+ /*
+ * No need to check for more since the target is
+ * already being reset.
+ */
+ break;
+ }
+ }
out:
+ /*
+ * Free the commands that may not have been freed from the SATA ID call
+ */
+ for (i = 1; i < sc->num_reqs; i++) {
+ cm = &sc->commands[i];
+ if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) {
+ mps_free_command(sc, cm);
+ }
+ }
mpssas_startup_decrement(sassc);
return (error);
-
}
int
mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
- u64 *sas_address, u16 handle, u32 device_info)
+ u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD)
{
Mpi2SataPassthroughReply_t mpi_reply;
int i, rc, try_count;
@@ -730,16 +838,33 @@
ioc_status = le16toh(mpi_reply.IOCStatus)
& MPI2_IOCSTATUS_MASK;
sas_status = mpi_reply.SASStatus;
- } while ((rc == -EAGAIN || ioc_status || sas_status) &&
- (try_count < 5));
+ switch (ioc_status) {
+ case MPI2_IOCSTATUS_SUCCESS:
+ break;
+ case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+ /* No sense sleeping. this error won't get better */
+ break;
+ default:
+ if (sc->spinup_wait_time > 0) {
+ mps_dprint(sc, MPS_INFO, "Sleeping %d seconds "
+ "after SATA ID error to wait for spinup\n",
+ sc->spinup_wait_time);
+ msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
+ "mpsid", sc->spinup_wait_time * hz);
+ }
+ }
+ } while (((rc && (rc != EWOULDBLOCK)) ||
+ (ioc_status &&
+ (ioc_status != MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR))
+ || sas_status) && (try_count < 5));
if (rc == 0 && !ioc_status && !sas_status) {
- mps_dprint(sc, MPS_INFO, "%s: got SATA identify successfully "
- "for handle = 0x%x with try_count = %d\n",
- __func__, handle, try_count);
+ mps_dprint(sc, MPS_MAPPING, "%s: got SATA identify "
+ "successfully for handle = 0x%x with try_count = %d\n",
+ __func__, handle, try_count);
} else {
- mps_dprint(sc, MPS_INFO, "%s: handle = 0x%x failed\n",
- __func__, handle);
+ mps_dprint(sc, MPS_MAPPING, "%s: handle = 0x%x failed\n",
+ __func__, handle);
return -1;
}
/* Copy & byteswap the 40 byte model number to a buffer */
@@ -750,9 +875,9 @@
/* Copy & byteswap the 20 byte serial number to a buffer */
for (i = 0; i < MPT2SAS_SN_LEN; i += 2) {
buffer[MPT2SAS_MN_LEN + i] =
- ((u8 *)ata_identify.serial_number)[i + 1];
+ ((u8 *)ata_identify.serial_number)[i + 1];
buffer[MPT2SAS_MN_LEN + i + 1] =
- ((u8 *)ata_identify.serial_number)[i];
+ ((u8 *)ata_identify.serial_number)[i];
}
bufferptr = (u32 *)buffer;
/* There are 60 bytes to hash down to 8. 60 isn't divisible by 8,
@@ -779,6 +904,10 @@
(u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
(u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 |
(u64)hash_address.wwid[7];
+ if (ata_identify.rotational_speed == 1) {
+ *is_SATA_SSD = 1;
+ }
+
return 0;
}
@@ -787,7 +916,7 @@
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo)
{
Mpi2SataPassthroughRequest_t *mpi_request;
- Mpi2SataPassthroughReply_t *reply;
+ Mpi2SataPassthroughReply_t *reply = NULL;
struct mps_command *cm;
char *buffer;
int error = 0;
@@ -818,12 +947,32 @@
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = buffer;
cm->cm_length = htole32(sz);
- error = mps_request_polled(sc, cm);
- reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
+
+ /*
+ * Start a timeout counter specifically for the SATA ID command. This
+ * is used to fix a problem where the FW does not send a reply sometimes
+ * when a bad disk is in the topology. So, this is used to timeout the
+ * command so that processing can continue normally.
+ */
+ mps_dprint(sc, MPS_XINFO, "%s start timeout counter for SATA ID "
+ "command\n", __func__);
+ callout_reset(&cm->cm_callout, MPS_ATA_ID_TIMEOUT * hz,
+ mpssas_ata_id_timeout, cm);
+ error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
+ mps_dprint(sc, MPS_XINFO, "%s stop timeout counter for SATA ID "
+ "command\n", __func__);
+ /* XXX KDM need to fix the case where this command is destroyed */
+ callout_stop(&cm->cm_callout);
+
+ if (cm != NULL)
+ reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for page completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -838,11 +987,67 @@
goto out;
}
out:
- mps_free_command(sc, cm);
- free(buffer, M_MPT2);
+ /*
+ * If the SATA_ID_TIMEOUT flag has been set for this command, don't free
+ * it. The command will be freed after sending a target reset TM. If
+ * the command did timeout, use EWOULDBLOCK.
+ */
+ if ((cm != NULL)
+ && (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0)
+ mps_free_command(sc, cm);
+ else if (error == 0)
+ error = EWOULDBLOCK;
+ free(buffer, M_MPT2);
return (error);
}
+static void
+mpssas_ata_id_timeout(void *data)
+{
+ struct mps_softc *sc;
+ struct mps_command *cm;
+
+ cm = (struct mps_command *)data;
+ sc = cm->cm_sc;
+ mtx_assert(&sc->mps_mtx, MA_OWNED);
+
+ mps_dprint(sc, MPS_INFO, "%s checking ATA ID command %p sc %p\n",
+ __func__, cm, sc);
+ if ((callout_pending(&cm->cm_callout)) ||
+ (!callout_active(&cm->cm_callout))) {
+ mps_dprint(sc, MPS_INFO, "%s ATA ID command almost timed out\n",
+ __func__);
+ return;
+ }
+ callout_deactivate(&cm->cm_callout);
+
+ /*
+ * Run the interrupt handler to make sure it's not pending. This
+ * isn't perfect because the command could have already completed
+ * and been re-used, though this is unlikely.
+ */
+ mps_intr_locked(sc);
+ if (cm->cm_state == MPS_CM_STATE_FREE) {
+ mps_dprint(sc, MPS_INFO, "%s ATA ID command almost timed out\n",
+ __func__);
+ return;
+ }
+
+ mps_dprint(sc, MPS_INFO, "ATA ID command timeout cm %p\n", cm);
+
+ /*
+ * Send wakeup() to the sleeping thread that issued this ATA ID command.
+ * wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), and this
+ * will keep reinit() from being called. This way, an Abort Task TM can
+ * be issued so that the timed out command can be cleared. The Abort
+ * Task cannot be sent from here because the driver has not completed
+ * setting up targets. Instead, the command is flagged so that special
+ * handling will be used to send the abort.
+ */
+ cm->cm_flags |= MPS_CM_FLAGS_SATA_ID_TIMEOUT;
+ wakeup(cm);
+}
+
static int
mpssas_volume_add(struct mps_softc *sc, u16 handle)
{
@@ -864,7 +1069,7 @@
goto out;
}
- id = mps_mapping_get_raid_id(sc, wwid, handle);
+ id = mps_mapping_get_raid_tid(sc, wwid, handle);
if (id == MPS_MAP_BAD_ID) {
printf("%s: could not get ID for volume with handle 0x%04x and "
"WWID 0x%016llx\n", __func__, handle,
@@ -885,9 +1090,11 @@
free(lun, M_MPT2);
}
SLIST_INIT(&targ->luns);
+#if __FreeBSD_version < 1000039
if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
+#endif
mpssas_rescan_target(sc, targ);
- mps_dprint(sc, MPS_INFO, "RAID target id %d added (WWID = 0x%jx)\n",
+ mps_dprint(sc, MPS_MAPPING, "RAID target id %d added (WWID = 0x%jx)\n",
targ->tid, wwid);
out:
mpssas_startup_decrement(sassc);
@@ -895,6 +1102,131 @@
}
/**
+ * mpssas_SSU_to_SATA_devices
+ * @sc: per adapter object
+ *
+ * Looks through the target list and issues a StartStopUnit SCSI command to each
+ * SATA direct-access device. This helps to ensure that data corruption is
+ * avoided when the system is being shut down. This must be called after the IR
+ * System Shutdown RAID Action is sent if in IR mode.
+ *
+ * Return nothing.
+ */
+static void
+mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
+{
+ struct mpssas_softc *sassc = sc->sassc;
+ union ccb *ccb;
+ path_id_t pathid = cam_sim_path(sassc->sim);
+ target_id_t targetid;
+ struct mpssas_target *target;
+ char path_str[64];
+ struct timeval cur_time, start_time;
+
+ /*
+ * For each target, issue a StartStopUnit command to stop the device.
+ */
+ sc->SSU_started = TRUE;
+ sc->SSU_refcount = 0;
+ for (targetid = 0; targetid < sc->max_devices; targetid++) {
+ target = &sassc->targets[targetid];
+ if (target->handle == 0x0) {
+ continue;
+ }
+
+ ccb = xpt_alloc_ccb_nowait();
+ if (ccb == NULL) {
+ mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB to stop "
+ "unit.\n");
+ return;
+ }
+
+ /*
+ * The stop_at_shutdown flag will be set if this device is
+ * a SATA direct-access end device.
+ */
+ if (target->stop_at_shutdown) {
+ if (xpt_create_path(&ccb->ccb_h.path,
+ xpt_periph, pathid, targetid,
+ CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ mps_dprint(sc, MPS_FAULT, "Unable to create "
+ "LUN path to stop unit.\n");
+ xpt_free_ccb(ccb);
+ return;
+ }
+ xpt_path_string(ccb->ccb_h.path, path_str,
+ sizeof(path_str));
+
+ mps_dprint(sc, MPS_INFO, "Sending StopUnit: path %s "
+ "handle %d\n", path_str, target->handle);
+
+ /*
+ * Issue a START STOP UNIT command for the target.
+ * Increment the SSU counter to be used to count the
+ * number of required replies.
+ */
+ mps_dprint(sc, MPS_INFO, "Incrementing SSU count\n");
+ sc->SSU_refcount++;
+ ccb->ccb_h.target_id =
+ xpt_path_target_id(ccb->ccb_h.path);
+ ccb->ccb_h.ppriv_ptr1 = sassc;
+ scsi_start_stop(&ccb->csio,
+ /*retries*/0,
+ mpssas_stop_unit_done,
+ MSG_SIMPLE_Q_TAG,
+ /*start*/FALSE,
+ /*load/eject*/0,
+ /*immediate*/FALSE,
+ MPS_SENSE_LEN,
+ /*timeout*/10000);
+ xpt_action(ccb);
+ }
+ }
+
+ /*
+ * Wait until all of the SSU commands have completed or time has
+ * expired (60 seconds). Pause for 100ms each time through. If any
+ * command times out, the target will be reset in the SCSI command
+ * timeout routine.
+ */
+ getmicrotime(&start_time);
+ while (sc->SSU_refcount) {
+ pause("mpswait", hz/10);
+
+ getmicrotime(&cur_time);
+ if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
+ mps_dprint(sc, MPS_FAULT, "Time has expired waiting "
+ "for SSU commands to complete.\n");
+ break;
+ }
+ }
+}
+
+static void
+mpssas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb)
+{
+ struct mpssas_softc *sassc;
+ char path_str[64];
+
+ if (done_ccb == NULL)
+ return;
+
+ sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
+
+ xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
+ mps_dprint(sassc->sc, MPS_INFO, "Completing stop unit for %s\n",
+ path_str);
+
+ /*
+ * Nothing more to do except free the CCB and path. If the command
+ * timed out, an abort reset, then target reset will be issued during
+ * the SCSI Command process.
+ */
+ xpt_free_path(done_ccb->ccb_h.path);
+ xpt_free_ccb(done_ccb);
+}
+
+/**
* mpssas_ir_shutdown - IR shutdown notification
* @sc: per adapter object
*
@@ -913,12 +1245,14 @@
unsigned int id, found_volume = 0;
struct mps_command *cm;
Mpi2RaidActionRequest_t *action;
+ target_id_t targetid;
+ struct mpssas_target *target;
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
/* is IR firmware build loaded? */
if (!sc->ir_firmware)
- return;
+ goto out;
/* are there any volumes? Look at IR target IDs. */
// TODO-later, this should be looked up in the RAID config structure
@@ -943,11 +1277,11 @@
}
if (!found_volume)
- return;
+ goto out;
if ((cm = mps_alloc_command(sc)) == NULL) {
printf("%s: command alloc failed\n", __func__);
- return;
+ goto out;
}
action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
@@ -955,7 +1289,7 @@
action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
mps_lock(sc);
- mps_request_polled(sc, cm);
+ mps_wait_command(sc, &cm, 5, CAN_SLEEP);
mps_unlock(sc);
/*
@@ -963,4 +1297,49 @@
*/
if (cm)
mps_free_command(sc, cm);
+
+out:
+ /*
+ * All of the targets must have the correct value set for
+ * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable.
+ *
+ * The possible values for the 'enable_ssu' variable are:
+ * 0: disable to SSD and HDD
+ * 1: disable only to HDD (default)
+ * 2: disable only to SSD
+ * 3: enable to SSD and HDD
+ * anything else will default to 1.
+ */
+ for (targetid = 0; targetid < sc->max_devices; targetid++) {
+ target = &sc->sassc->targets[targetid];
+ if (target->handle == 0x0) {
+ continue;
+ }
+
+ if (target->supports_SSU) {
+ switch (sc->enable_ssu) {
+ case MPS_SSU_DISABLE_SSD_DISABLE_HDD:
+ target->stop_at_shutdown = FALSE;
+ break;
+ case MPS_SSU_DISABLE_SSD_ENABLE_HDD:
+ target->stop_at_shutdown = TRUE;
+ if (target->flags & MPS_TARGET_IS_SATA_SSD) {
+ target->stop_at_shutdown = FALSE;
+ }
+ break;
+ case MPS_SSU_ENABLE_SSD_ENABLE_HDD:
+ target->stop_at_shutdown = TRUE;
+ break;
+ case MPS_SSU_ENABLE_SSD_DISABLE_HDD:
+ default:
+ target->stop_at_shutdown = TRUE;
+ if ((target->flags &
+ MPS_TARGET_IS_SATA_SSD) == 0) {
+ target->stop_at_shutdown = FALSE;
+ }
+ break;
+ }
+ }
+ }
+ mpssas_SSU_to_SATA_devices(sc);
}
Modified: trunk/sys/dev/mps/mps_table.c
===================================================================
--- trunk/sys/dev/mps/mps_table.c 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_table.c 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009 Yahoo! Inc.
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/mps/mps_table.c 322661 2017-08-18 15:38:08Z ken $");
/* Debugging tables for MPT2 */
@@ -205,17 +206,18 @@
MPS_PRINTFIELD(sc, facts, IOCNumber, %d);
MPS_PRINTFIELD(sc, facts, IOCExceptions, 0x%x);
MPS_PRINTFIELD(sc, facts, MaxChainDepth, %d);
- mps_dprint_field(sc, MPS_INFO, "WhoInit: %s\n",
+ mps_print_field(sc, "WhoInit: %s\n",
mps_describe_table(mps_whoinit_names, facts->WhoInit));
MPS_PRINTFIELD(sc, facts, NumberOfPorts, %d);
+ MPS_PRINTFIELD(sc, facts, MaxMSIxVectors, %d);
MPS_PRINTFIELD(sc, facts, RequestCredit, %d);
MPS_PRINTFIELD(sc, facts, ProductID, 0x%x);
- mps_dprint_field(sc, MPS_INFO, "IOCCapabilities: %b\n",
+ mps_print_field(sc, "IOCCapabilities: %b\n",
facts->IOCCapabilities, "\20" "\3ScsiTaskFull" "\4DiagTrace"
"\5SnapBuf" "\6ExtBuf" "\7EEDP" "\10BiDirTarg" "\11Multicast"
"\14TransRetry" "\15IR" "\16EventReplay" "\17RaidAccel"
"\20MSIXIndex" "\21HostDisc");
- mps_dprint_field(sc, MPS_INFO, "FWVersion= %d-%d-%d-%d\n",
+ mps_print_field(sc, "FWVersion= %d-%d-%d-%d\n",
facts->FWVersion.Struct.Major,
facts->FWVersion.Struct.Minor,
facts->FWVersion.Struct.Unit,
@@ -225,7 +227,7 @@
MPS_PRINTFIELD(sc, facts, MaxTargets, %d);
MPS_PRINTFIELD(sc, facts, MaxSasExpanders, %d);
MPS_PRINTFIELD(sc, facts, MaxEnclosures, %d);
- mps_dprint_field(sc, MPS_INFO, "ProtocolFlags: %b\n",
+ mps_print_field(sc, "ProtocolFlags: %b\n",
facts->ProtocolFlags, "\20" "\1ScsiTarg" "\2ScsiInit");
MPS_PRINTFIELD(sc, facts, HighPriorityCredit, %d);
MPS_PRINTFIELD(sc, facts, MaxReplyDescriptorPostQueueDepth, %d);
@@ -246,15 +248,15 @@
}
void
-mps_print_event(struct mps_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event)
+mps_print_evt_generic(struct mps_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event)
{
- MPS_EVENTFIELD_START(sc, "EventReply");
- MPS_EVENTFIELD(sc, event, EventDataLength, %d);
- MPS_EVENTFIELD(sc, event, AckRequired, %d);
- mps_dprint_field(sc, MPS_EVENT, "Event: %s (0x%x)\n",
+ MPS_PRINTFIELD_START(sc, "EventReply");
+ MPS_PRINTFIELD(sc, event, EventDataLength, %d);
+ MPS_PRINTFIELD(sc, event, AckRequired, %d);
+ mps_print_field(sc, "Event: %s (0x%x)\n",
mps_describe_table(mps_event_names, event->Event), event->Event);
- MPS_EVENTFIELD(sc, event, EventContext, 0x%x);
+ MPS_PRINTFIELD(sc, event, EventContext, 0x%x);
}
void
@@ -263,7 +265,7 @@
MPS_PRINTFIELD_START(sc, "SAS Device Page 0");
MPS_PRINTFIELD(sc, buf, Slot, %d);
MPS_PRINTFIELD(sc, buf, EnclosureHandle, 0x%x);
- mps_dprint_field(sc, MPS_INFO, "SASAddress: 0x%jx\n",
+ mps_print_field(sc, "SASAddress: 0x%jx\n",
mps_to_u64(&buf->SASAddress));
MPS_PRINTFIELD(sc, buf, ParentDevHandle, 0x%x);
MPS_PRINTFIELD(sc, buf, PhyNum, %d);
@@ -271,7 +273,7 @@
MPS_PRINTFIELD(sc, buf, DevHandle, 0x%x);
MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, 0x%x);
MPS_PRINTFIELD(sc, buf, ZoneGroup, %d);
- mps_dprint_field(sc, MPS_INFO, "DeviceInfo: %b,%s\n", buf->DeviceInfo,
+ mps_print_field(sc, "DeviceInfo: %b,%s\n", buf->DeviceInfo,
"\20" "\4SataHost" "\5SmpInit" "\6StpInit" "\7SspInit"
"\10SataDev" "\11SmpTarg" "\12StpTarg" "\13SspTarg" "\14Direct"
"\15LsiDev" "\16AtapiDev" "\17SepDev",
@@ -279,7 +281,7 @@
MPS_PRINTFIELD(sc, buf, Flags, 0x%x);
MPS_PRINTFIELD(sc, buf, PhysicalPort, %d);
MPS_PRINTFIELD(sc, buf, MaxPortConnections, %d);
- mps_dprint_field(sc, MPS_INFO, "DeviceName: 0x%jx\n",
+ mps_print_field(sc, "DeviceName: 0x%jx\n",
mps_to_u64(&buf->DeviceName));
MPS_PRINTFIELD(sc, buf, PortGroups, %d);
MPS_PRINTFIELD(sc, buf, DmaGroup, %d);
@@ -290,7 +292,7 @@
mps_print_evt_sas(struct mps_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event)
{
- mps_print_event(sc, event);
+ mps_print_evt_generic(sc, event);
switch(event->Event) {
case MPI2_EVENT_SAS_DISCOVERY:
@@ -298,12 +300,12 @@
MPI2_EVENT_DATA_SAS_DISCOVERY *data;
data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)&event->EventData;
- mps_dprint_field(sc, MPS_EVENT, "Flags: %b\n", data->Flags,
+ mps_print_field(sc, "Flags: %b\n", data->Flags,
"\20" "\1InProgress" "\2DeviceChange");
- mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n",
+ mps_print_field(sc, "ReasonCode: %s\n",
mps_describe_table(mps_sasdisc_reason, data->ReasonCode));
- MPS_EVENTFIELD(sc, data, PhysicalPort, %d);
- mps_dprint_field(sc, MPS_EVENT, "DiscoveryStatus: %b\n",
+ MPS_PRINTFIELD(sc, data, PhysicalPort, %d);
+ mps_print_field(sc, "DiscoveryStatus: %b\n",
data->DiscoveryStatus, "\20"
"\1Loop" "\2UnaddressableDev" "\3DupSasAddr" "\5SmpTimeout"
"\6ExpRouteFull" "\7RouteIndexError" "\10SmpFailed"
@@ -322,26 +324,26 @@
data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
&event->EventData;
- MPS_EVENTFIELD(sc, data, EnclosureHandle, 0x%x);
- MPS_EVENTFIELD(sc, data, ExpanderDevHandle, 0x%x);
- MPS_EVENTFIELD(sc, data, NumPhys, %d);
- MPS_EVENTFIELD(sc, data, NumEntries, %d);
- MPS_EVENTFIELD(sc, data, StartPhyNum, %d);
- mps_dprint_field(sc, MPS_EVENT, "ExpStatus: %s (0x%x)\n",
+ MPS_PRINTFIELD(sc, data, EnclosureHandle, 0x%x);
+ MPS_PRINTFIELD(sc, data, ExpanderDevHandle, 0x%x);
+ MPS_PRINTFIELD(sc, data, NumPhys, %d);
+ MPS_PRINTFIELD(sc, data, NumEntries, %d);
+ MPS_PRINTFIELD(sc, data, StartPhyNum, %d);
+ mps_print_field(sc, "ExpStatus: %s (0x%x)\n",
mps_describe_table(mps_sastopo_exp, data->ExpStatus),
data->ExpStatus);
- MPS_EVENTFIELD(sc, data, PhysicalPort, %d);
+ MPS_PRINTFIELD(sc, data, PhysicalPort, %d);
for (i = 0; i < data->NumEntries; i++) {
phy = &data->PHY[i];
phynum = data->StartPhyNum + i;
- mps_dprint_field(sc, MPS_EVENT,
+ mps_print_field(sc,
"PHY[%d].AttachedDevHandle: 0x%04x\n", phynum,
phy->AttachedDevHandle);
- mps_dprint_field(sc, MPS_EVENT,
+ mps_print_field(sc,
"PHY[%d].LinkRate: %s (0x%x)\n", phynum,
mps_describe_table(mps_linkrate_names,
(phy->LinkRate >> 4) & 0xf), phy->LinkRate);
- mps_dprint_field(sc,MPS_EVENT,"PHY[%d].PhyStatus: %s\n",
+ mps_print_field(sc, "PHY[%d].PhyStatus: %s\n",
phynum, mps_describe_table(mps_phystatus_names,
phy->PhyStatus));
}
@@ -353,13 +355,13 @@
data = (MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE *)
&event->EventData;
- MPS_EVENTFIELD(sc, data, EnclosureHandle, 0x%x);
- mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n",
+ MPS_PRINTFIELD(sc, data, EnclosureHandle, 0x%x);
+ mps_print_field(sc, "ReasonCode: %s\n",
mps_describe_table(mps_sastopo_exp, data->ReasonCode));
- MPS_EVENTFIELD(sc, data, PhysicalPort, %d);
- MPS_EVENTFIELD(sc, data, NumSlots, %d);
- MPS_EVENTFIELD(sc, data, StartSlot, %d);
- MPS_EVENTFIELD(sc, data, PhyBits, 0x%x);
+ MPS_PRINTFIELD(sc, data, PhysicalPort, %d);
+ MPS_PRINTFIELD(sc, data, NumSlots, %d);
+ MPS_PRINTFIELD(sc, data, StartSlot, %d);
+ MPS_PRINTFIELD(sc, data, PhyBits, 0x%x);
break;
}
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
@@ -368,13 +370,13 @@
data = (MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
&event->EventData;
- MPS_EVENTFIELD(sc, data, TaskTag, 0x%x);
- mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n",
+ MPS_PRINTFIELD(sc, data, TaskTag, 0x%x);
+ mps_print_field(sc, "ReasonCode: %s\n",
mps_describe_table(mps_sasdev_reason, data->ReasonCode));
- MPS_EVENTFIELD(sc, data, ASC, 0x%x);
- MPS_EVENTFIELD(sc, data, ASCQ, 0x%x);
- MPS_EVENTFIELD(sc, data, DevHandle, 0x%x);
- mps_dprint_field(sc, MPS_EVENT, "SASAddress: 0x%jx\n",
+ MPS_PRINTFIELD(sc, data, ASC, 0x%x);
+ MPS_PRINTFIELD(sc, data, ASCQ, 0x%x);
+ MPS_PRINTFIELD(sc, data, DevHandle, 0x%x);
+ mps_print_field(sc, "SASAddress: 0x%jx\n",
mps_to_u64(&data->SASAddress));
}
default:
@@ -390,17 +392,17 @@
MPS_PRINTFIELD(sc, buf, NumPhys, %d);
MPS_PRINTFIELD(sc, buf, Phy, %d);
MPS_PRINTFIELD(sc, buf, NumTableEntriesProgrammed, %d);
- mps_dprint_field(sc, MPS_INFO, "ProgrammedLinkRate: %s (0x%x)\n",
+ mps_print_field(sc, "ProgrammedLinkRate: %s (0x%x)\n",
mps_describe_table(mps_linkrate_names,
(buf->ProgrammedLinkRate >> 4) & 0xf), buf->ProgrammedLinkRate);
- mps_dprint_field(sc, MPS_INFO, "HwLinkRate: %s (0x%x)\n",
+ mps_print_field(sc, "HwLinkRate: %s (0x%x)\n",
mps_describe_table(mps_linkrate_names,
(buf->HwLinkRate >> 4) & 0xf), buf->HwLinkRate);
MPS_PRINTFIELD(sc, buf, AttachedDevHandle, 0x%04x);
- mps_dprint_field(sc, MPS_INFO, "PhyInfo Reason: %s (0x%x)\n",
+ mps_print_field(sc, "PhyInfo Reason: %s (0x%x)\n",
mps_describe_table(mps_phyinfo_reason_names,
(buf->PhyInfo >> 16) & 0xf), buf->PhyInfo);
- mps_dprint_field(sc, MPS_INFO, "AttachedDeviceInfo: %b,%s\n",
+ mps_print_field(sc, "AttachedDeviceInfo: %b,%s\n",
buf->AttachedDeviceInfo, "\20" "\4SATAhost" "\5SMPinit" "\6STPinit"
"\7SSPinit" "\10SATAdev" "\11SMPtarg" "\12STPtarg" "\13SSPtarg"
"\14Direct" "\15LSIdev" "\16ATAPIdev" "\17SEPdev",
@@ -408,7 +410,7 @@
buf->AttachedDeviceInfo & 0x03));
MPS_PRINTFIELD(sc, buf, ExpanderDevHandle, 0x%04x);
MPS_PRINTFIELD(sc, buf, ChangeCount, %d);
- mps_dprint_field(sc, MPS_INFO, "NegotiatedLinkRate: %s (0x%x)\n",
+ mps_print_field(sc, "NegotiatedLinkRate: %s (0x%x)\n",
mps_describe_table(mps_linkrate_names,
buf->NegotiatedLinkRate & 0xf), buf->NegotiatedLinkRate);
MPS_PRINTFIELD(sc, buf, PhyIdentifier, %d);
@@ -415,7 +417,7 @@
MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, %d);
MPS_PRINTFIELD(sc, buf, DiscoveryInfo, 0x%x);
MPS_PRINTFIELD(sc, buf, AttachedPhyInfo, 0x%x);
- mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo Reason: %s (0x%x)\n",
+ mps_print_field(sc, "AttachedPhyInfo Reason: %s (0x%x)\n",
mps_describe_table(mps_phyinfo_reason_names,
buf->AttachedPhyInfo & 0xf), buf->AttachedPhyInfo);
MPS_PRINTFIELD(sc, buf, ZoneGroup, %d);
@@ -429,21 +431,21 @@
MPS_PRINTFIELD(sc, buf, OwnerDevHandle, 0x%04x);
MPS_PRINTFIELD(sc, buf, AttachedDevHandle, 0x%04x);
MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, %d);
- mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo Reason: %s (0x%x)\n",
+ mps_print_field(sc, "AttachedPhyInfo Reason: %s (0x%x)\n",
mps_describe_table(mps_phyinfo_reason_names,
buf->AttachedPhyInfo & 0xf), buf->AttachedPhyInfo);
- mps_dprint_field(sc, MPS_INFO, "ProgrammedLinkRate: %s (0x%x)\n",
+ mps_print_field(sc, "ProgrammedLinkRate: %s (0x%x)\n",
mps_describe_table(mps_linkrate_names,
(buf->ProgrammedLinkRate >> 4) & 0xf), buf->ProgrammedLinkRate);
- mps_dprint_field(sc, MPS_INFO, "HwLinkRate: %s (0x%x)\n",
+ mps_print_field(sc, "HwLinkRate: %s (0x%x)\n",
mps_describe_table(mps_linkrate_names,
(buf->HwLinkRate >> 4) & 0xf), buf->HwLinkRate);
MPS_PRINTFIELD(sc, buf, ChangeCount, %d);
MPS_PRINTFIELD(sc, buf, Flags, 0x%x);
- mps_dprint_field(sc, MPS_INFO, "PhyInfo Reason: %s (0x%x)\n",
+ mps_print_field(sc, "PhyInfo Reason: %s (0x%x)\n",
mps_describe_table(mps_phyinfo_reason_names,
(buf->PhyInfo >> 16) & 0xf), buf->PhyInfo);
- mps_dprint_field(sc, MPS_INFO, "NegotiatedLinkRate: %s (0x%x)\n",
+ mps_print_field(sc, "NegotiatedLinkRate: %s (0x%x)\n",
mps_describe_table(mps_linkrate_names,
buf->NegotiatedLinkRate & 0xf), buf->NegotiatedLinkRate);
}
@@ -463,10 +465,12 @@
sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4];
printf("SGL for command %p\n", cm);
+ hexdump(frame, 128, NULL, 0);
while (frame != NULL) {
- flags = sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT;
- printf("seg%d flags=0x%x len=0x%x addr=0x%jx\n", i, flags,
- sge->FlagsLength & 0xffffff, mps_to_u64(&sge->Address));
+ flags = le32toh(sge->FlagsLength) >> MPI2_SGE_FLAGS_SHIFT;
+ printf("seg%d flags=0x%02x len=0x%06x addr=0x%016jx\n",
+ i, flags, le32toh(sge->FlagsLength) & 0xffffff,
+ mps_to_u64(&sge->Address));
if (flags & (MPI2_SGE_FLAGS_END_OF_LIST |
MPI2_SGE_FLAGS_END_OF_BUFFER))
break;
@@ -475,8 +479,8 @@
if (flags & MPI2_SGE_FLAGS_LAST_ELEMENT) {
sgc = (MPI2_SGE_CHAIN32 *)sge;
printf("chain flags=0x%x len=0x%x Offset=0x%x "
- "Address=0x%x\n", sgc->Flags, sgc->Length,
- sgc->NextChainOffset, sgc->Address);
+ "Address=0x%x\n", sgc->Flags, le16toh(sgc->Length),
+ sgc->NextChainOffset, le32toh(sgc->Address));
if (chain == NULL)
chain = TAILQ_FIRST(&cm->cm_chain_list);
else
Modified: trunk/sys/dev/mps/mps_table.h
===================================================================
--- trunk/sys/dev/mps/mps_table.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_table.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009 Yahoo! Inc.
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mps_table.h 322661 2017-08-18 15:38:08Z ken $
*/
#ifndef _MPS_TABLE_H
@@ -43,7 +44,7 @@
void mps_print_iocfacts(struct mps_softc *, MPI2_IOC_FACTS_REPLY *);
void mps_print_portfacts(struct mps_softc *, MPI2_PORT_FACTS_REPLY *);
-void mps_print_event(struct mps_softc *, MPI2_EVENT_NOTIFICATION_REPLY *);
+void mps_print_evt_generic(struct mps_softc *, MPI2_EVENT_NOTIFICATION_REPLY *);
void mps_print_sasdev0(struct mps_softc *, MPI2_CONFIG_PAGE_SAS_DEV_0 *);
void mps_print_evt_sas(struct mps_softc *, MPI2_EVENT_NOTIFICATION_REPLY *);
void mps_print_expander1(struct mps_softc *, MPI2_CONFIG_PAGE_EXPANDER_1 *);
@@ -50,4 +51,14 @@
void mps_print_sasphy0(struct mps_softc *, MPI2_CONFIG_PAGE_SAS_PHY_0 *);
void mps_print_sgl(struct mps_softc *, struct mps_command *, int);
void mps_print_scsiio_cmd(struct mps_softc *, struct mps_command *);
+
+#define MPS_DPRINT_PAGE(sc, level, func, buf) \
+do { \
+ if ((sc)->mps_debug & level) \
+ mps_print_##func((sc), buf); \
+} while (0)
+
+#define MPS_DPRINT_EVENT(sc, func, buf) \
+ MPS_DPRINT_PAGE(sc, MPS_EVENT, evt_##func, buf)
+
#endif
Modified: trunk/sys/dev/mps/mps_user.c
===================================================================
--- trunk/sys/dev/mps/mps_user.c 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mps_user.c 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2008 Yahoo!, Inc.
* All rights reserved.
@@ -27,10 +28,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD userland interface
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
*/
/*-
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,13 +56,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mps_user.c 322661 2017-08-18 15:38:08Z ken $
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/mps/mps_user.c 322661 2017-08-18 15:38:08Z ken $");
#include "opt_compat.h"
@@ -90,6 +92,7 @@
#include <sys/rman.h>
#include <cam/cam.h>
+#include <cam/cam_ccb.h>
#include <cam/scsi/scsi_all.h>
#include <dev/mps/mpi/mpi2_type.h>
@@ -310,6 +313,10 @@
hdr->PageNumber = ext_page_req->header.PageNumber;
hdr->ExtPageType = ext_page_req->header.ExtPageType;
params.page_address = le32toh(ext_page_req->page_address);
+ params.buffer = NULL;
+ params.length = 0;
+ params.callback = NULL;
+
if ((error = mps_read_config_page(sc, ¶ms)) != 0) {
/*
* Leave the request. Without resetting the chip, it's
@@ -536,11 +543,6 @@
return (EINVAL);
mpi_init_sge(cm, req, &req->SGL);
- if (cmd->len == 0) {
- /* Perhaps just asking what the size of the fw is? */
- return (0);
- }
-
bzero(&tc, sizeof tc);
/*
@@ -556,6 +558,8 @@
tc.ImageOffset = 0;
tc.ImageSize = cmd->len;
+ cm->cm_flags |= MPS_CM_FLAGS_DATAIN;
+
return (mps_push_sge(cm, &tc, sizeof tc, 0));
}
@@ -672,16 +676,16 @@
cm = mps_alloc_command(sc);
if (cm == NULL) {
- mps_printf(sc, "mps_user_command: no mps requests\n");
+ mps_printf(sc, "%s: no mps requests\n", __func__);
err = ENOMEM;
- goto Ret;
+ goto RetFree;
}
mps_unlock(sc);
hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
- mps_dprint(sc, MPS_INFO, "mps_user_command: req %p %d rpl %p %d\n",
- cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len );
+ mps_dprint(sc, MPS_USER, "%s: req %p %d rpl %p %d\n", __func__,
+ cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len);
if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) {
err = EINVAL;
@@ -691,23 +695,11 @@
if (err != 0)
goto RetFreeUnlocked;
- mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X "
- "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags );
+ mps_dprint(sc, MPS_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
+ hdr->Function, hdr->MsgFlags);
- err = mps_user_setup_request(cm, cmd);
- if (err != 0) {
- mps_printf(sc, "mps_user_command: unsupported function 0x%X\n",
- hdr->Function );
- goto RetFreeUnlocked;
- }
-
if (cmd->len > 0) {
buf = malloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
- if(!buf) {
- mps_printf(sc, "Cannot allocate memory %s %d\n",
- __func__, __LINE__);
- return (ENOMEM);
- }
cm->cm_data = buf;
cm->cm_length = cmd->len;
} else {
@@ -718,23 +710,33 @@
cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+ err = mps_user_setup_request(cm, cmd);
+ if (err == EINVAL) {
+ mps_printf(sc, "%s: unsupported parameter or unsupported "
+ "function in request (function = 0x%X)\n", __func__,
+ hdr->Function);
+ }
+ if (err != 0)
+ goto RetFreeUnlocked;
+
mps_lock(sc);
- err = mps_wait_command(sc, cm, 30);
+ err = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
- if (err) {
+ if (err || (cm == NULL)) {
mps_printf(sc, "%s: invalid request: error %d\n",
__func__, err);
- goto Ret;
+ goto RetFree;
}
rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
- sz = rpl->MsgLength * 4;
+ if (rpl != NULL)
+ sz = rpl->MsgLength * 4;
+ else
+ sz = 0;
if (sz > cmd->rpl_len) {
- mps_printf(sc,
- "mps_user_command: reply buffer too small %d required %d\n",
- cmd->rpl_len, sz );
- err = EINVAL;
+ mps_printf(sc, "%s: user reply buffer (%d) smaller than "
+ "returned buffer (%d)\n", __func__, cmd->rpl_len, sz);
sz = cmd->rpl_len;
}
@@ -742,13 +744,13 @@
copyout(rpl, cmd->rpl, sz);
if (buf != NULL)
copyout(buf, cmd->buf, cmd->len);
- mps_dprint(sc, MPS_INFO, "mps_user_command: reply size %d\n", sz );
+ mps_dprint(sc, MPS_USER, "%s: reply size %d\n", __func__, sz);
RetFreeUnlocked:
mps_lock(sc);
+RetFree:
if (cm != NULL)
mps_free_command(sc, cm);
-Ret:
mps_unlock(sc);
if (buf != NULL)
free(buf, M_MPSUSER);
@@ -759,11 +761,12 @@
mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
{
MPI2_REQUEST_HEADER *hdr, tmphdr;
- MPI2_DEFAULT_REPLY *rpl;
+ MPI2_DEFAULT_REPLY *rpl = NULL;
struct mps_command *cm = NULL;
int err = 0, dir = 0, sz;
uint8_t function = 0;
u_int sense_len;
+ struct mpssas_target *targ = NULL;
/*
* Only allow one passthru command at a time. Use the MPS_FLAGS_BUSY
@@ -771,7 +774,7 @@
*/
mps_lock(sc);
if (sc->mps_flags & MPS_FLAGS_BUSY) {
- mps_dprint(sc, MPS_INFO, "%s: Only one passthru command "
+ mps_dprint(sc, MPS_USER, "%s: Only one passthru command "
"allowed at a single time.", __func__);
mps_unlock(sc);
return (EBUSY);
@@ -803,7 +806,7 @@
} else
return (EINVAL);
- mps_dprint(sc, MPS_INFO, "%s: req 0x%jx %d rpl 0x%jx %d "
+ mps_dprint(sc, MPS_USER, "%s: req 0x%jx %d rpl 0x%jx %d "
"data in 0x%jx %d data out 0x%jx %d data dir %d\n", __func__,
data->PtrRequest, data->RequestSize, data->PtrReply,
data->ReplySize, data->PtrData, data->DataSize,
@@ -823,7 +826,7 @@
}
function = tmphdr.Function;
- mps_dprint(sc, MPS_INFO, "%s: Function %02X MsgFlags %02X\n", __func__,
+ mps_dprint(sc, MPS_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
function, tmphdr.MsgFlags);
/*
@@ -845,11 +848,22 @@
task->TaskMID = cm->cm_desc.Default.SMID;
cm->cm_data = NULL;
- cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+ cm->cm_desc.HighPriority.RequestFlags =
+ MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
cm->cm_complete = NULL;
cm->cm_complete_data = NULL;
- err = mps_wait_command(sc, cm, 30);
+ targ = mpssas_find_target_by_handle(sc->sassc, 0,
+ task->DevHandle);
+ if (targ == NULL) {
+ mps_dprint(sc, MPS_INFO,
+ "%s %d : invalid handle for requested TM 0x%x \n",
+ __func__, __LINE__, task->DevHandle);
+ err = 1;
+ } else {
+ mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
+ err = mps_wait_command(sc, &cm, 30, CAN_SLEEP);
+ }
if (err != 0) {
err = EIO;
@@ -859,20 +873,19 @@
/*
* Copy the reply data and sense data to user space.
*/
- if (cm->cm_reply != NULL) {
+ if ((cm != NULL) && (cm->cm_reply != NULL)) {
rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
sz = rpl->MsgLength * 4;
if (sz > data->ReplySize) {
- mps_printf(sc, "%s: reply buffer too small: %d, "
- "required: %d\n", __func__, data->ReplySize, sz);
- err = EINVAL;
- } else {
- mps_unlock(sc);
- copyout(cm->cm_reply, PTRIN(data->PtrReply),
- data->ReplySize);
- mps_lock(sc);
+ mps_printf(sc, "%s: user reply buffer (%d) "
+ "smaller than returned buffer (%d)\n",
+ __func__, data->ReplySize, sz);
}
+ mps_unlock(sc);
+ copyout(cm->cm_reply, PTRIN(data->PtrReply),
+ data->ReplySize);
+ mps_lock(sc);
}
mpssas_free_tm(sc, cm);
goto Ret;
@@ -913,25 +926,20 @@
if (cm->cm_length != 0) {
cm->cm_data = malloc(cm->cm_length, M_MPSUSER, M_WAITOK |
M_ZERO);
- if (cm->cm_data == NULL) {
- mps_dprint(sc, MPS_FAULT, "%s: alloc failed for IOCTL "
- "passthru length %d\n", __func__, cm->cm_length);
- } else {
- cm->cm_flags = MPS_CM_FLAGS_DATAIN;
- if (data->DataOutSize) {
- cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
- err = copyin(PTRIN(data->PtrDataOut),
- cm->cm_data, data->DataOutSize);
- } else if (data->DataDirection ==
- MPS_PASS_THRU_DIRECTION_WRITE) {
- cm->cm_flags = MPS_CM_FLAGS_DATAOUT;
- err = copyin(PTRIN(data->PtrData),
- cm->cm_data, data->DataSize);
- }
- if (err != 0)
- mps_dprint(sc, MPS_FAULT, "%s: failed to copy "
- "IOCTL data from user space\n", __func__);
+ cm->cm_flags = MPS_CM_FLAGS_DATAIN;
+ if (data->DataOutSize) {
+ cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
+ err = copyin(PTRIN(data->PtrDataOut),
+ cm->cm_data, data->DataOutSize);
+ } else if (data->DataDirection ==
+ MPS_PASS_THRU_DIRECTION_WRITE) {
+ cm->cm_flags = MPS_CM_FLAGS_DATAOUT;
+ err = copyin(PTRIN(data->PtrData),
+ cm->cm_data, data->DataSize);
}
+ if (err != 0)
+ mps_dprint(sc, MPS_FAULT, "%s: failed to copy "
+ "IOCTL data from user space\n", __func__);
}
cm->cm_flags |= MPS_CM_FLAGS_SGE_SIMPLE;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
@@ -986,9 +994,9 @@
mps_lock(sc);
- err = mps_wait_command(sc, cm, 30);
+ err = mps_wait_command(sc, &cm, 30, CAN_SLEEP);
- if (err) {
+ if (err || (cm == NULL)) {
mps_printf(sc, "%s: invalid request: error %d\n", __func__,
err);
mps_unlock(sc);
@@ -1025,15 +1033,13 @@
sz = rpl->MsgLength * 4;
if (sz > data->ReplySize) {
- mps_printf(sc, "%s: reply buffer too small: %d, "
- "required: %d\n", __func__, data->ReplySize, sz);
- err = EINVAL;
- } else {
- mps_unlock(sc);
- copyout(cm->cm_reply, PTRIN(data->PtrReply),
- data->ReplySize);
- mps_lock(sc);
+ mps_printf(sc, "%s: user reply buffer (%d) smaller "
+ "than returned buffer (%d)\n", __func__,
+ data->ReplySize, sz);
}
+ mps_unlock(sc);
+ copyout(cm->cm_reply, PTRIN(data->PtrReply), data->ReplySize);
+ mps_lock(sc);
if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
(function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
@@ -1156,7 +1162,7 @@
mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
{
MPI2_DIAG_BUFFER_POST_REQUEST *req;
- MPI2_DIAG_BUFFER_POST_REPLY *reply;
+ MPI2_DIAG_BUFFER_POST_REPLY *reply = NULL;
struct mps_command *cm = NULL;
int i, status;
@@ -1203,8 +1209,8 @@
/*
* Send command synchronously.
*/
- status = mps_wait_command(sc, cm, 30);
- if (status) {
+ status = mps_wait_command(sc, &cm, 30, CAN_SLEEP);
+ if (status || (cm == NULL)) {
mps_printf(sc, "%s: invalid request: error %d\n", __func__,
status);
status = MPS_DIAG_FAILURE;
@@ -1215,12 +1221,14 @@
* Process POST reply.
*/
reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply;
- if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) {
+ if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
+ MPI2_IOCSTATUS_SUCCESS) {
status = MPS_DIAG_FAILURE;
mps_dprint(sc, MPS_FAULT, "%s: post of FW Diag Buffer failed "
"with IOCStatus = 0x%x, IOCLogInfo = 0x%x and "
- "TransferLength = 0x%x\n", __func__, reply->IOCStatus,
- reply->IOCLogInfo, reply->TransferLength);
+ "TransferLength = 0x%x\n", __func__,
+ le16toh(reply->IOCStatus), le32toh(reply->IOCLogInfo),
+ le32toh(reply->TransferLength));
goto done;
}
@@ -1233,7 +1241,8 @@
status = MPS_DIAG_SUCCESS;
done:
- mps_free_command(sc, cm);
+ if (cm != NULL)
+ mps_free_command(sc, cm);
return (status);
}
@@ -1243,7 +1252,7 @@
uint32_t diag_type)
{
MPI2_DIAG_RELEASE_REQUEST *req;
- MPI2_DIAG_RELEASE_REPLY *reply;
+ MPI2_DIAG_RELEASE_REPLY *reply = NULL;
struct mps_command *cm = NULL;
int status;
@@ -1252,8 +1261,8 @@
*/
*return_code = MPS_FW_DIAG_ERROR_RELEASE_FAILED;
if (!pBuffer->enabled) {
- mps_dprint(sc, MPS_INFO, "%s: This buffer type is not supported "
- "by the IOC", __func__);
+ mps_dprint(sc, MPS_USER, "%s: This buffer type is not "
+ "supported by the IOC", __func__);
return (MPS_DIAG_FAILURE);
}
@@ -1287,8 +1296,8 @@
/*
* Send command synchronously.
*/
- status = mps_wait_command(sc, cm, 30);
- if (status) {
+ status = mps_wait_command(sc, &cm, 30, CAN_SLEEP);
+ if (status || (cm == NULL)) {
mps_printf(sc, "%s: invalid request: error %d\n", __func__,
status);
status = MPS_DIAG_FAILURE;
@@ -1299,12 +1308,13 @@
* Process RELEASE reply.
*/
reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply;
- if ((reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) ||
- pBuffer->owned_by_firmware) {
+ if (((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
+ MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) {
status = MPS_DIAG_FAILURE;
mps_dprint(sc, MPS_FAULT, "%s: release of FW Diag Buffer "
"failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n",
- __func__, reply->IOCStatus, reply->IOCLogInfo);
+ __func__, le16toh(reply->IOCStatus),
+ le32toh(reply->IOCLogInfo));
goto done;
}
@@ -1322,6 +1332,9 @@
}
done:
+ if (cm != NULL)
+ mps_free_command(sc, cm);
+
return (status);
}
@@ -1795,7 +1808,7 @@
* Only allow one diag action at one time.
*/
if (sc->mps_flags & MPS_FLAGS_BUSY) {
- mps_dprint(sc, MPS_INFO, "%s: Only one FW diag command "
+ mps_dprint(sc, MPS_USER, "%s: Only one FW diag command "
"allowed at a single time.", __func__);
return (EBUSY);
}
@@ -1982,7 +1995,7 @@
*/
case REG_IO_READ:
case REG_IO_WRITE:
- mps_dprint(sc, MPS_INFO, "IO access is not supported. "
+ mps_dprint(sc, MPS_USER, "IO access is not supported. "
"Use memory access.");
status = EINVAL;
break;
@@ -2044,7 +2057,7 @@
data->DevHandle = dev_handle;
} else {
bus = 0;
- target = mps_mapping_get_sas_id_from_handle(sc, dev_handle);
+ target = mps_mapping_get_tid_from_handle(sc, dev_handle);
data->Bus = bus;
data->TargetID = target;
}
@@ -2075,11 +2088,6 @@
break;
case MPSIO_READ_CFG_PAGE:
mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK | M_ZERO);
- if(!mps_page) {
- mps_printf(sc, "Cannot allocate memory %s %d\n",
- __func__, __LINE__);
- return (ENOMEM);
- }
error = copyin(page_req->buf, mps_page,
sizeof(MPI2_CONFIG_PAGE_HEADER));
if (error)
@@ -2098,11 +2106,6 @@
break;
case MPSIO_READ_EXT_CFG_PAGE:
mps_page = malloc(ext_page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
- if(!mps_page) {
- mps_printf(sc, "Cannot allocate memory %s %d\n",
- __func__, __LINE__);
- return (ENOMEM);
- }
error = copyin(ext_page_req->buf, mps_page,
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
if (error)
@@ -2116,11 +2119,6 @@
break;
case MPSIO_WRITE_CFG_PAGE:
mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
- if(!mps_page) {
- mps_printf(sc, "Cannot allocate memory %s %d\n",
- __func__, __LINE__);
- return (ENOMEM);
- }
error = copyin(page_req->buf, mps_page, page_req->len);
if (error)
break;
@@ -2170,7 +2168,7 @@
printf("Port Enable did not complete after Diag "
"Reset msleep error %d.\n", msleep_ret);
else
- mps_dprint(sc, MPS_INFO,
+ mps_dprint(sc, MPS_USER,
"Hard Reset with Port Enable completed in %d seconds.\n",
(uint32_t) (time_uptime - reinit_start));
break;
Modified: trunk/sys/dev/mps/mpsvar.h
===================================================================
--- trunk/sys/dev/mps/mpsvar.h 2018-05-27 23:34:03 UTC (rev 10093)
+++ trunk/sys/dev/mps/mpsvar.h 2018-05-27 23:35:39 UTC (rev 10094)
@@ -1,6 +1,8 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009 Yahoo! Inc.
- * Copyright (c) 2011, 2012 LSI Corp.
+ * Copyright (c) 2011-2015 LSI Corp.
+ * Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,15 +26,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * LSI MPT-Fusion Host Adapter FreeBSD
+ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/mps/mpsvar.h 322661 2017-08-18 15:38:08Z ken $
*/
#ifndef _MPSVAR_H
#define _MPSVAR_H
-#define MPS_DRIVER_VERSION "14.00.00.01-fbsd"
+#define MPS_DRIVER_VERSION "21.02.00.00-fbsd"
#define MPS_DB_MAX_WAIT 2500
@@ -40,6 +42,7 @@
#define MPS_EVT_REPLY_FRAMES 32
#define MPS_REPLY_FRAMES MPS_REQ_FRAMES
#define MPS_CHAIN_FRAMES 2048
+#define MPS_MAXIO_PAGES (-1)
#define MPS_SENSE_LEN SSD_FULL_SIZE
#define MPS_MSI_COUNT 1
#define MPS_SGE64_SIZE 12
@@ -50,10 +53,14 @@
#define NO_SLEEP 0
#define MPS_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */
+#define MPS_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */
+#define MPS_MISSING_CHECK_DELAY 10 /* 10 seconds between missing check */
#define MPS_SCSI_RI_INVALID_FRAME (0x00000002)
#define MPS_STRING_LENGTH 64
+#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */
+
#include <sys/endian.h>
/*
@@ -65,7 +72,6 @@
#define MPS_MAX_MISSING_COUNT 0x0F
#define MPS_DEV_RESERVED 0x20000000
#define MPS_MAP_IN_USE 0x10000000
-#define MPS_RAID_CHANNEL 1
#define MPS_MAP_BAD_ID 0xFFFFFFFF
/*
@@ -102,7 +108,6 @@
* @phy_bits: bitfields indicating controller phys
* @dpm_entry_num: index of this device in device persistent map table
* @dev_handle: device handle for the device pointed by this entry
- * @channel: target channel
* @id: target id
* @missing_count: number of times the device not detected by driver
* @hide_flag: Hide this physical disk/not (foreign configuration)
@@ -114,8 +119,7 @@
u32 phy_bits;
u16 dpm_entry_num;
u16 dev_handle;
- u8 reserved1;
- u8 channel;
+ u16 reserved1;
u16 id;
u8 missing_count;
u8 init_complete;
@@ -231,6 +235,8 @@
#define MPS_CM_FLAGS_SMP_PASS (1 << 8)
#define MPS_CM_FLAGS_CHAIN_FAILED (1 << 9)
#define MPS_CM_FLAGS_ERROR_MASK MPS_CM_FLAGS_CHAIN_FAILED
+#define MPS_CM_FLAGS_USE_CCB (1 << 10)
+#define MPS_CM_FLAGS_SATA_ID_TIMEOUT (1 << 11)
u_int cm_state;
#define MPS_CM_STATE_FREE 0
#define MPS_CM_STATE_BUSY 1
@@ -266,18 +272,22 @@
#define MPS_FLAGS_DIAGRESET (1 << 4)
#define MPS_FLAGS_ATTACH_DONE (1 << 5)
#define MPS_FLAGS_WD_AVAILABLE (1 << 6)
+#define MPS_FLAGS_REALLOCATED (1 << 7)
u_int mps_debug;
u_int disable_msix;
u_int disable_msi;
+ u_int msi_msgs;
int tm_cmds_active;
int io_cmds_active;
int io_cmds_highwater;
int chain_free;
int max_chains;
+ int max_io_pages;
int chain_free_lowwater;
-#if __FreeBSD_version >= 900030
+ u_int enable_ssu;
+ int spinup_wait_time;
+ int use_phynum;
uint64_t chain_alloc_fail;
-#endif
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
char fw_version[16];
@@ -284,6 +294,7 @@
struct mps_command *commands;
struct mps_chain *chains;
struct callout periodic;
+ struct callout device_check_callout;
struct mpssas_softc *sassc;
char tmp_string[MPS_STRING_LENGTH];
@@ -303,7 +314,6 @@
bus_dma_tag_t buffer_dmat;
MPI2_IOC_FACTS_REPLY *facts;
- MPI2_PORT_FACTS_REPLY *pfacts;
int num_reqs;
int num_replies;
int fqdepth; /* Free queue */
@@ -369,13 +379,10 @@
uint8_t max_volumes;
uint8_t num_enc_table_entries;
uint8_t num_rsvd_entries;
- uint8_t num_channels;
uint16_t max_dpm_entries;
uint8_t is_dpm_enable;
uint8_t track_mapping_events;
uint32_t pending_map_events;
- uint8_t mt_full_retry;
- uint8_t mt_add_device_failed;
/* FW diag Buffer List */
mps_fw_diagnostic_buffer_t
@@ -414,6 +421,13 @@
uint16_t DD_block_exponent;
uint64_t DD_max_lba;
struct mps_column_map DD_column_map[MPS_MAX_DISKS_IN_VOL];
+
+ char exclude_ids[80];
+ struct timeval lastfail;
+
+ /* StartStopUnit command handling at shutdown */
+ uint32_t SSU_refcount;
+ uint8_t SSU_started;
};
struct mps_config_params {
@@ -469,11 +483,8 @@
sc->chain_free--;
if (sc->chain_free < sc->chain_free_lowwater)
sc->chain_free_lowwater = sc->chain_free;
- }
-#if __FreeBSD_version >= 900030
- else
+ } else
sc->chain_alloc_fail++;
-#endif
return (chain);
}
@@ -480,9 +491,6 @@
static __inline void
mps_free_chain(struct mps_softc *sc, struct mps_chain *chain)
{
-#if 0
- bzero(chain->chain, 128);
-#endif
sc->chain_free++;
TAILQ_INSERT_TAIL(&sc->chain_list, chain, chain_link);
}
@@ -580,15 +588,29 @@
mtx_unlock(&sc->mps_mtx);
}
-#define MPS_INFO (1 << 0)
-#define MPS_TRACE (1 << 1)
-#define MPS_FAULT (1 << 2)
-#define MPS_EVENT (1 << 3)
-#define MPS_LOG (1 << 4)
+#define MPS_INFO (1 << 0) /* Basic info */
+#define MPS_FAULT (1 << 1) /* Hardware faults */
+#define MPS_EVENT (1 << 2) /* Event data from the controller */
+#define MPS_LOG (1 << 3) /* Log data from the controller */
+#define MPS_RECOVERY (1 << 4) /* Command error recovery tracing */
+#define MPS_ERROR (1 << 5) /* Parameter errors, programming bugs */
+#define MPS_INIT (1 << 6) /* Things related to system init */
+#define MPS_XINFO (1 << 7) /* More detailed/noisy info */
+#define MPS_USER (1 << 8) /* Trace user-generated commands */
+#define MPS_MAPPING (1 << 9) /* Trace device mappings */
+#define MPS_TRACE (1 << 10) /* Function-by-function trace */
+#define MPS_SSU_DISABLE_SSD_DISABLE_HDD 0
+#define MPS_SSU_ENABLE_SSD_DISABLE_HDD 1
+#define MPS_SSU_DISABLE_SSD_ENABLE_HDD 2
+#define MPS_SSU_ENABLE_SSD_ENABLE_HDD 3
+
#define mps_printf(sc, args...) \
device_printf((sc)->mps_dev, ##args)
+#define mps_print_field(sc, msg, args...) \
+ printf("\t" msg, ##args)
+
#define mps_vprintf(sc, args...) \
do { \
if (bootverbose) \
@@ -597,29 +619,20 @@
#define mps_dprint(sc, level, msg, args...) \
do { \
- if (sc->mps_debug & level) \
- device_printf(sc->mps_dev, msg, ##args); \
+ if ((sc)->mps_debug & (level)) \
+ device_printf((sc)->mps_dev, msg, ##args); \
} while (0)
-#define mps_dprint_field(sc, level, msg, args...) \
-do { \
- if (sc->mps_debug & level) \
- printf("\t" msg, ##args); \
-} while (0)
-
#define MPS_PRINTFIELD_START(sc, tag...) \
- mps_dprint((sc), MPS_INFO, ##tag); \
- mps_dprint_field((sc), MPS_INFO, ":\n")
+ mps_printf((sc), ##tag); \
+ mps_print_field((sc), ":\n")
#define MPS_PRINTFIELD_END(sc, tag) \
- mps_dprint((sc), MPS_INFO, tag "\n")
+ mps_printf((sc), tag "\n")
#define MPS_PRINTFIELD(sc, facts, attr, fmt) \
- mps_dprint_field((sc), MPS_INFO, #attr ": " #fmt "\n", (facts)->attr)
+ mps_print_field((sc), #attr ": " #fmt "\n", (facts)->attr)
-#define MPS_EVENTFIELD_START(sc, tag...) \
- mps_dprint((sc), MPS_EVENT, ##tag); \
- mps_dprint_field((sc), MPS_EVENT, ":\n")
-#define MPS_EVENTFIELD(sc, facts, attr, fmt) \
- mps_dprint_field((sc), MPS_EVENT, #attr ": " #fmt "\n", (facts)->attr)
+#define MPS_FUNCTRACE(sc) \
+ mps_dprint((sc), MPS_TRACE, "%s\n", __func__)
#define CAN_SLEEP 1
#define NO_SLEEP 0
@@ -627,8 +640,8 @@
static __inline void
mps_from_u64(uint64_t data, U64 *mps)
{
- (mps)->High = (uint32_t)((data) >> 32);
- (mps)->Low = (uint32_t)((data) & 0xffffffff);
+ (mps)->High = htole32((uint32_t)((data) >> 32));
+ (mps)->Low = htole32((uint32_t)((data) & 0xffffffff));
}
static __inline uint64_t
@@ -635,7 +648,7 @@
mps_to_u64(U64 *data)
{
- return (((uint64_t)data->High << 32) | data->Low);
+ return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low));
}
static __inline void
@@ -661,6 +674,7 @@
int mps_pci_setup_interrupts(struct mps_softc *sc);
int mps_pci_restore(struct mps_softc *sc);
+void mps_get_tunables(struct mps_softc *sc);
int mps_attach(struct mps_softc *sc);
int mps_free(struct mps_softc *sc);
void mps_intr(void *);
@@ -685,8 +699,8 @@
MPI2_EVENT_NOTIFICATION_REPLY *event_reply);
int mps_map_command(struct mps_softc *sc, struct mps_command *cm);
-int mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout);
-int mps_request_polled(struct mps_softc *sc, struct mps_command *cm);
+int mps_wait_command(struct mps_softc *sc, struct mps_command **cm, int timeout,
+ int sleep_flag);
int mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t
*mpi_reply, Mpi2BiosPage3_t *config_page);
@@ -718,24 +732,25 @@
int mps_mapping_initialize(struct mps_softc *);
void mps_mapping_topology_change_event(struct mps_softc *,
Mpi2EventDataSasTopologyChangeList_t *);
-int mps_mapping_is_reinit_required(struct mps_softc *);
void mps_mapping_free_memory(struct mps_softc *sc);
int mps_config_set_dpm_pg0(struct mps_softc *, Mpi2ConfigReply_t *,
Mpi2DriverMappingPage0_t *, u16 );
void mps_mapping_exit(struct mps_softc *);
-void mps_mapping_check_devices(struct mps_softc *, int);
+void mps_mapping_check_devices(void *);
int mps_mapping_allocate_memory(struct mps_softc *sc);
-unsigned int mps_mapping_get_sas_id(struct mps_softc *, uint64_t , u16);
-unsigned int mps_mapping_get_sas_id_from_handle(struct mps_softc *sc,
+unsigned int mps_mapping_get_tid(struct mps_softc *, uint64_t , u16);
+unsigned int mps_mapping_get_tid_from_handle(struct mps_softc *sc,
u16 handle);
-unsigned int mps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid,
- u16 handle);
-unsigned int mps_mapping_get_raid_id_from_handle(struct mps_softc *sc,
+unsigned int mps_mapping_get_raid_tid(struct mps_softc *sc, u64 wwid,
+ u16 volHandle);
+unsigned int mps_mapping_get_raid_tid_from_handle(struct mps_softc *sc,
u16 volHandle);
void mps_mapping_enclosure_dev_status_change_event(struct mps_softc *,
Mpi2EventDataSasEnclDevStatusChange_t *event_data);
void mps_mapping_ir_config_change_event(struct mps_softc *sc,
Mpi2EventDataIrConfigChangeList_t *event_data);
+int mps_mapping_dump(SYSCTL_HANDLER_ARGS);
+int mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS);
void mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
MPI2_EVENT_NOTIFICATION_REPLY *event);
@@ -743,6 +758,12 @@
void mpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle);
int mpssas_startup(struct mps_softc *sc);
struct mpssas_target * mpssas_find_target_by_handle(struct mpssas_softc *, int, uint16_t);
+void mpssas_realloc_targets(struct mps_softc *sc, int maxtargets);
+struct mps_command * mpssas_alloc_tm(struct mps_softc *sc);
+void mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm);
+void mpssas_release_simq_reinit(struct mpssas_softc *sassc);
+int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm,
+ uint8_t type);
SYSCTL_DECL(_hw_mps);
More information about the Midnightbsd-cvs
mailing list