Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Dec 2011 17:55:00 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r228310 - projects/head_mfi/sys/dev/mfi
Message-ID:  <201112061755.pB6Ht0Im002069@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Dec  6 17:54:59 2011
New Revision: 228310
URL: http://svn.freebsd.org/changeset/base/228310

Log:
  Move mfi_decode_evt() call from interrupt thread to the taskqueue. Call from
  the interrupt thread leads to panic on attempt to sleep on SX lock.

Modified:
  projects/head_mfi/sys/dev/mfi/mfi.c
  projects/head_mfi/sys/dev/mfi/mfivar.h

Modified: projects/head_mfi/sys/dev/mfi/mfi.c
==============================================================================
--- projects/head_mfi/sys/dev/mfi/mfi.c	Tue Dec  6 17:30:15 2011	(r228309)
+++ projects/head_mfi/sys/dev/mfi/mfi.c	Tue Dec  6 17:54:59 2011	(r228310)
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/uio.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
+#include <sys/taskqueue.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -96,6 +97,7 @@ static void	mfi_startup(void *arg);
 static void	mfi_intr(void *arg);
 static void	mfi_ldprobe(struct mfi_softc *sc);
 static void	mfi_syspdprobe(struct mfi_softc *sc);
+static void	mfi_handle_evt(void *context, int pending);
 static int	mfi_aen_register(struct mfi_softc *sc, int seq, int locale);
 static void	mfi_aen_complete(struct mfi_command *);
 static int	mfi_add_ld(struct mfi_softc *sc, int);
@@ -368,6 +370,8 @@ mfi_attach(struct mfi_softc *sc)
 	sx_init(&sc->mfi_config_lock, "MFI config");
 	TAILQ_INIT(&sc->mfi_ld_tqh);
 	TAILQ_INIT(&sc->mfi_syspd_tqh);
+	TAILQ_INIT(&sc->mfi_evt_queue);
+	TASK_INIT(&sc->mfi_evt_task, 0, mfi_handle_evt, sc);
 	TAILQ_INIT(&sc->mfi_aen_pids);
 	TAILQ_INIT(&sc->mfi_cam_ccbq);
 
@@ -1462,6 +1466,10 @@ static void
 mfi_decode_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail,uint8_t probe_sys_pd)
 {
 	struct mfi_system_pd *syspd = NULL;
+
+	device_printf(sc->mfi_dev, "%d (%s/0x%04x/%s) - %s\n", detail->seq,
+	    format_timestamp(detail->time), detail->evt_class.members.locale,
+	    format_class(detail->evt_class.members.evt_class), detail->description);
 	switch (detail->arg_type) {
 	case MR_EVT_ARGS_NONE:
 #define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
@@ -1527,10 +1535,41 @@ mfi_decode_evt(struct mfi_softc *sc, str
 		}
 		break;
 	}
+}
 
-	device_printf(sc->mfi_dev, "%d (%s/0x%04x/%s) - %s\n", detail->seq,
-	    format_timestamp(detail->time), detail->evt_class.members.locale,
-	    format_class(detail->evt_class.members.evt_class), detail->description);
+static void
+mfi_queue_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail,
+    uint8_t probe_sys_pd)
+{
+	struct mfi_evt_queue_elm *elm;
+
+	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+	elm = malloc(sizeof(*elm), M_MFIBUF, M_NOWAIT|M_ZERO);
+	if (elm == NULL)
+		return;
+	elm->probe_sys_pd = probe_sys_pd;
+	memcpy(&elm->detail, detail, sizeof(*detail));
+	TAILQ_INSERT_TAIL(&sc->mfi_evt_queue, elm, link);
+	taskqueue_enqueue(taskqueue_swi, &sc->mfi_evt_task);
+}
+
+static void
+mfi_handle_evt(void *context, int pending)
+{
+	TAILQ_HEAD(,mfi_evt_queue_elm) queue;
+	struct mfi_softc *sc;
+	struct mfi_evt_queue_elm *elm;
+
+	sc = context;
+	TAILQ_INIT(&queue);
+	mtx_lock(&sc->mfi_io_lock);
+	TAILQ_CONCAT(&queue, &sc->mfi_evt_queue, link);
+	mtx_unlock(&sc->mfi_io_lock);
+	while ((elm = TAILQ_FIRST(&queue)) != NULL) {
+		TAILQ_REMOVE(&queue, elm, link);
+		mfi_decode_evt(sc, &elm->detail, elm->probe_sys_pd);
+		free(elm, M_MFIBUF);
+	}
 }
 
 static int
@@ -1616,13 +1655,7 @@ mfi_aen_complete(struct mfi_command *cm)
 			selwakeup(&sc->mfi_select);
 		}
 		detail = cm->cm_data;
-		/*
-		 * XXX If this function is too expensive or is recursive, then
-		 * events should be put onto a queue and processed later.
-		 */
-		mtx_unlock(&sc->mfi_io_lock);
-		mfi_decode_evt(sc, detail,1);
-		mtx_lock(&sc->mfi_io_lock);
+		mfi_queue_evt(sc, detail, 1);
 		seq = detail->seq + 1;
 		TAILQ_FOREACH_SAFE(mfi_aen_entry, &sc->mfi_aen_pids, aen_link, tmp) {
 			TAILQ_REMOVE(&sc->mfi_aen_pids, mfi_aen_entry,
@@ -1738,7 +1771,9 @@ mfi_parse_entries(struct mfi_softc *sc, 
 				else if (el->event[i].seq < start_seq)
 					break;
 			}
-			mfi_decode_evt(sc, &el->event[i], 0);
+			mtx_lock(&sc->mfi_io_lock);
+			mfi_queue_evt(sc, &el->event[i], 0);
+			mtx_unlock(&sc->mfi_io_lock);
 		}
 		seq = el->event[el->count - 1].seq + 1;
 	}

Modified: projects/head_mfi/sys/dev/mfi/mfivar.h
==============================================================================
--- projects/head_mfi/sys/dev/mfi/mfivar.h	Tue Dec  6 17:30:15 2011	(r228309)
+++ projects/head_mfi/sys/dev/mfi/mfivar.h	Tue Dec  6 17:54:59 2011	(r228310)
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/sx.h>
 
 #include <sys/types.h>
+#include <sys/taskqueue.h>
 #include <machine/atomic.h>
 
 /*
@@ -136,6 +137,13 @@ struct mfi_system_pd {
 	struct disk	*pd_disk;
 	int		pd_flags;
 };
+
+struct mfi_evt_queue_elm {
+	TAILQ_ENTRY(mfi_evt_queue_elm)	link;
+	uint8_t				probe_sys_pd;
+	struct mfi_evt_detail		detail;
+};
+
 struct mfi_aen {
 	TAILQ_ENTRY(mfi_aen) aen_link;
 	struct proc			*p;
@@ -208,6 +216,8 @@ struct mfi_softc {
 	bus_addr_t			mfi_tb_ioc_init_busaddr;
 	union mfi_frame			*mfi_tb_init;
 
+	TAILQ_HEAD(,mfi_evt_queue_elm)	mfi_evt_queue;
+	struct task			mfi_evt_task;
 	TAILQ_HEAD(,mfi_aen)		mfi_aen_pids;
 	struct mfi_command		*mfi_aen_cm;
 	struct mfi_command		*mfi_skinny_cm;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112061755.pB6Ht0Im002069>