svn commit: r220117 - projects/altix/sys/ia64/ia64

Marcel Moolenaar marcel at FreeBSD.org
Tue Mar 29 00:06:02 UTC 2011


Author: marcel
Date: Tue Mar 29 00:06:02 2011
New Revision: 220117
URL: http://svn.freebsd.org/changeset/base/220117

Log:
  Slightly rework the interrupt setup code to eliminate the hard
  dependency on I/O SAPICs.

Modified:
  projects/altix/sys/ia64/ia64/interrupt.c

Modified: projects/altix/sys/ia64/ia64/interrupt.c
==============================================================================
--- projects/altix/sys/ia64/ia64/interrupt.c	Mon Mar 28 23:08:18 2011	(r220116)
+++ projects/altix/sys/ia64/ia64/interrupt.c	Tue Mar 29 00:06:02 2011	(r220117)
@@ -190,13 +190,35 @@ ia64_intr_unmask(void *arg)
 	sapic_unmask(i->sapic, i->irq);
 }
 
+static int
+ia64_create_event(struct ia64_intr *i, u_int xiv, const char *name)
+{
+	char *intrname;
+	int error;
+
+	error = intr_event_create(&i->event, (void *)(uintptr_t)xiv, 0,
+	    i->irq, ia64_intr_mask, ia64_intr_unmask, ia64_intr_eoi, NULL,
+	    "irq%u:", i->irq);
+	if (error)
+		return (error);
+
+	i->cntp = intrcnt + xiv;
+	if (name != NULL && *name != '\0') {
+		/* XXX needs abstraction. Too error prone. */
+		intrname = intrnames + xiv * INTRNAME_LEN;
+		memset(intrname, ' ', INTRNAME_LEN - 1);
+		bcopy(name, intrname, strlen(name));
+	}
+
+	return (0);
+}
+
 int
 ia64_setup_intr(const char *name, int irq, driver_filter_t filter,
     driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
 {
 	struct ia64_intr *i;
 	struct sapic *sa;
-	char *intrname;
 	u_int prio, xiv;
 	int error;
 
@@ -209,65 +231,94 @@ ia64_setup_intr(const char *name, int ir
 	/* Get the I/O SAPIC and XIV that corresponds to the IRQ. */
 	sa = sapic_lookup(irq, &xiv);
 	if (sa == NULL) {
-		/* XXX unlock */
-		printf("XXX %s: no I/O SAPIC -- can't setup IRQ %u\n",
-		    __func__, irq);
-		return (0);
-	}
-
-	if (xiv == 0) {
-		/* XXX unlock */
-		i = malloc(sizeof(struct ia64_intr), M_DEVBUF,
-		    M_ZERO | M_WAITOK);
-		/* XXX lock */
-		sa = sapic_lookup(irq, &xiv);
-		KASSERT(sa != NULL, ("sapic_lookup"));
-		if (xiv != 0)
-			free(i, M_DEVBUF);
-	}
-
-	/*
-	 * If the IRQ has no XIV assigned to it yet, assign one based
-	 * on the priority.
-	 */
-	if (xiv == 0) {
-		xiv = ia64_xiv_alloc(prio, IA64_XIV_IRQ, ia64_ih_irq);
-		if (xiv == 0) {
+		/* XXX assume SGI Altix... */
+		xiv = irq;
+		i = ia64_intrs[xiv];
+		if (i == NULL) {
 			/* XXX unlock */
-			free(i, M_DEVBUF);
-			return (ENOSPC);
-		}
 
-		error = intr_event_create(&i->event, (void *)(uintptr_t)xiv,
-		    0, irq, ia64_intr_mask, ia64_intr_unmask, ia64_intr_eoi,
-		    NULL, "irq%u:", irq);
-		if (error) {
-			ia64_xiv_free(xiv, IA64_XIV_IRQ);
-			/* XXX unlock */
-			free(i, M_DEVBUF);
-			return (error);
-		}
+			i = malloc(sizeof(struct ia64_intr), M_DEVBUF,
+			    M_ZERO | M_WAITOK);
 
-		i->sapic = sa;
-		i->irq = irq;
-		i->cntp = intrcnt + xiv;
-		ia64_intrs[xiv] = i;
-
-		/* XXX unlock */
-
-		sapic_enable(sa, irq, xiv);
-
-		if (name != NULL && *name != '\0') {
-			/* XXX needs abstraction. Too error prone. */
-			intrname = intrnames + xiv * INTRNAME_LEN;
-			memset(intrname, ' ', INTRNAME_LEN - 1);
-			bcopy(name, intrname, strlen(name));
+			/* XXX lock */
+
+			if (ia64_intrs[xiv] == NULL) {
+				error = ia64_xiv_reserve(xiv, IA64_XIV_IRQ,
+				    ia64_ih_irq);
+				if (error) {
+					/* XXX unlock */
+
+					free(i, M_DEVBUF);
+					return (error);
+				}
+
+				i->irq = irq;
+				error = ia64_create_event(i, xiv, name);
+				if (error != 0) {
+					ia64_xiv_free(xiv, IA64_XIV_IRQ);
+
+					/* XXX unlock */
+
+					free(i, M_DEVBUF);
+					return (error);
+				}
+
+				// sgisn_register_intr();
+				ia64_intrs[xiv] = i;
+			} else {
+				free(i, M_DEVBUF);
+				i = ia64_intrs[xiv];
+			}
 		}
 	} else {
-		i = ia64_intrs[xiv];
-		/* XXX unlock */
+		if (xiv == 0) {
+			/* XXX unlock */
+
+			i = malloc(sizeof(struct ia64_intr), M_DEVBUF,
+			    M_ZERO | M_WAITOK);
+
+			/* XXX lock */
+
+			/*
+			 * Make sure some other thread hasn't registered an
+			 * event for the same IRQ while the window was open.
+			 */
+			sa = sapic_lookup(irq, &xiv);
+			KASSERT(sa != NULL, ("sapic_lookup"));
+			if (xiv != 0) {
+				free(i, M_DEVBUF);
+				i = ia64_intrs[xiv];
+			} else {
+				xiv = ia64_xiv_alloc(prio, IA64_XIV_IRQ,
+				    ia64_ih_irq);
+				if (xiv == 0) {
+					/* XXX unlock */
+
+					free(i, M_DEVBUF);
+					return (ENOSPC);
+				}
+
+				i->irq = irq;
+				error = ia64_create_event(i, xiv, name);
+				if (error != 0) {
+					ia64_xiv_free(xiv, IA64_XIV_IRQ);
+
+					/* XXX unlock */
+
+					free(i, M_DEVBUF);
+					return (error);
+				}
+
+				i->sapic = sa;
+				sapic_enable(sa, irq, xiv);
+				ia64_intrs[xiv] = i;
+			}
+		} else
+			i = ia64_intrs[xiv];
 	}
 
+	/* XXX unlock */
+
 	KASSERT(i != NULL, ("XIV mapping bug"));
 
 	error = intr_event_add_handler(i->event, name, filter, handler, arg,


More information about the svn-src-projects mailing list