staging: gasket: interrupt: allow device driver to manage interrupts

Add interrupt type DEVICE_MANAGED, indicating that the device driver
manages interrupt setup and handling.  Future non-PCI wire interrupts
will use this type, calling gasket_handle_interrupt(), which is now made
non-static, to call into the gasket framework in order to update sysfs
files for interrupt counts and other framework interfaces.

Change-Id: Ie0be3d950ed2706f7ada848c19ddf7017e9623b2
Signed-off-by: Todd Poynor <toddpoynor@google.com>
diff --git a/drivers/staging/gasket/gasket_core.h b/drivers/staging/gasket/gasket_core.h
index 56805d3..ef7cf16 100644
--- a/drivers/staging/gasket/gasket_core.h
+++ b/drivers/staging/gasket/gasket_core.h
@@ -56,6 +56,7 @@
 /* Type of the interrupt supported by the device. */
 enum gasket_interrupt_type {
 	PCI_MSIX = 0,
+	DEVICE_MANAGED = 1, /* Managed externally in device driver */
 };
 
 /*
diff --git a/drivers/staging/gasket/gasket_interrupt.c b/drivers/staging/gasket/gasket_interrupt.c
index 9d0ad2c..915146c 100644
--- a/drivers/staging/gasket/gasket_interrupt.c
+++ b/drivers/staging/gasket/gasket_interrupt.c
@@ -93,6 +93,9 @@
 
 	dev_dbg(gasket_dev->dev, "Running interrupt setup\n");
 
+	if (interrupt_data->type == DEVICE_MANAGED)
+		return; /* device driver handles setup */
+
 	/* Setup the MSIX table. */
 
 	for (i = 0; i < interrupt_data->num_interrupts; i++) {
@@ -145,7 +148,7 @@
 	}
 }
 
-static void
+void
 gasket_handle_interrupt(struct gasket_interrupt_data *interrupt_data,
 			int interrupt_index)
 {
@@ -340,7 +343,6 @@
 	interrupt_data->interrupts = driver_desc->interrupts;
 	interrupt_data->interrupt_bar_index = driver_desc->interrupt_bar_index;
 	interrupt_data->pack_width = driver_desc->interrupt_pack_width;
-	interrupt_data->num_configured = 0;
 
 	interrupt_data->eventfd_ctxs = kcalloc(driver_desc->num_interrupts,
 					       sizeof(struct eventfd_ctx *),
@@ -369,6 +371,11 @@
 		force_msix_interrupt_unmasking(gasket_dev);
 		break;
 
+	case DEVICE_MANAGED:  /* Device driver manages IRQ init */
+		interrupt_data->num_configured = interrupt_data->num_interrupts;
+		ret = 0;
+		break;
+
 	default:
 		ret = -EINVAL;
 	}
@@ -426,6 +433,10 @@
 		force_msix_interrupt_unmasking(gasket_dev);
 		break;
 
+	case DEVICE_MANAGED: /* Device driver manages IRQ reinit */
+		ret = 0;
+		break;
+
 	default:
 		ret = -EINVAL;
 	}
@@ -471,6 +482,9 @@
 		gasket_interrupt_msix_cleanup(interrupt_data);
 		break;
 
+	case DEVICE_MANAGED: /* Device driver manages IRQ cleanup */
+		break;
+
 	default:
 		break;
 	}
diff --git a/drivers/staging/gasket/gasket_interrupt.h b/drivers/staging/gasket/gasket_interrupt.h
index 85526a1..b17b723 100644
--- a/drivers/staging/gasket/gasket_interrupt.h
+++ b/drivers/staging/gasket/gasket_interrupt.h
@@ -45,6 +45,11 @@
  */
 int gasket_interrupt_reinit(struct gasket_dev *gasket_dev);
 
+/* Handle gasket interrupt processing, called from an external handler. */
+void
+gasket_handle_interrupt(struct gasket_interrupt_data *interrupt_data,
+			int interrupt_index);
+
 /*
  * Reset the counts stored in the interrupt subsystem.
  * @gasket_dev: The Gasket information structure for this device.