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>