|
@@ -132,6 +132,16 @@ static void free_masks(struct irq_desc *desc)
|
|
static inline void free_masks(struct irq_desc *desc) { }
|
|
static inline void free_masks(struct irq_desc *desc) { }
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+void irq_lock_sparse(void)
|
|
|
|
+{
|
|
|
|
+ mutex_lock(&sparse_irq_lock);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void irq_unlock_sparse(void)
|
|
|
|
+{
|
|
|
|
+ mutex_unlock(&sparse_irq_lock);
|
|
|
|
+}
|
|
|
|
+
|
|
static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
|
|
static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
|
|
{
|
|
{
|
|
struct irq_desc *desc;
|
|
struct irq_desc *desc;
|
|
@@ -168,6 +178,12 @@ static void free_desc(unsigned int irq)
|
|
|
|
|
|
unregister_irq_proc(irq, desc);
|
|
unregister_irq_proc(irq, desc);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * sparse_irq_lock protects also show_interrupts() and
|
|
|
|
+ * kstat_irq_usr(). Once we deleted the descriptor from the
|
|
|
|
+ * sparse tree we can free it. Access in proc will fail to
|
|
|
|
+ * lookup the descriptor.
|
|
|
|
+ */
|
|
mutex_lock(&sparse_irq_lock);
|
|
mutex_lock(&sparse_irq_lock);
|
|
delete_irq_desc(irq);
|
|
delete_irq_desc(irq);
|
|
mutex_unlock(&sparse_irq_lock);
|
|
mutex_unlock(&sparse_irq_lock);
|
|
@@ -574,6 +590,15 @@ void kstat_incr_irq_this_cpu(unsigned int irq)
|
|
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
|
|
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * kstat_irqs_cpu - Get the statistics for an interrupt on a cpu
|
|
|
|
+ * @irq: The interrupt number
|
|
|
|
+ * @cpu: The cpu number
|
|
|
|
+ *
|
|
|
|
+ * Returns the sum of interrupt counts on @cpu since boot for
|
|
|
|
+ * @irq. The caller must ensure that the interrupt is not removed
|
|
|
|
+ * concurrently.
|
|
|
|
+ */
|
|
unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
|
unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
|
{
|
|
{
|
|
struct irq_desc *desc = irq_to_desc(irq);
|
|
struct irq_desc *desc = irq_to_desc(irq);
|
|
@@ -582,6 +607,14 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
|
*per_cpu_ptr(desc->kstat_irqs, cpu) : 0;
|
|
*per_cpu_ptr(desc->kstat_irqs, cpu) : 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * kstat_irqs - Get the statistics for an interrupt
|
|
|
|
+ * @irq: The interrupt number
|
|
|
|
+ *
|
|
|
|
+ * Returns the sum of interrupt counts on all cpus since boot for
|
|
|
|
+ * @irq. The caller must ensure that the interrupt is not removed
|
|
|
|
+ * concurrently.
|
|
|
|
+ */
|
|
unsigned int kstat_irqs(unsigned int irq)
|
|
unsigned int kstat_irqs(unsigned int irq)
|
|
{
|
|
{
|
|
struct irq_desc *desc = irq_to_desc(irq);
|
|
struct irq_desc *desc = irq_to_desc(irq);
|
|
@@ -594,3 +627,22 @@ unsigned int kstat_irqs(unsigned int irq)
|
|
sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
|
|
sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
|
|
return sum;
|
|
return sum;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * kstat_irqs_usr - Get the statistics for an interrupt
|
|
|
|
+ * @irq: The interrupt number
|
|
|
|
+ *
|
|
|
|
+ * Returns the sum of interrupt counts on all cpus since boot for
|
|
|
|
+ * @irq. Contrary to kstat_irqs() this can be called from any
|
|
|
|
+ * preemptible context. It's protected against concurrent removal of
|
|
|
|
+ * an interrupt descriptor when sparse irqs are enabled.
|
|
|
|
+ */
|
|
|
|
+unsigned int kstat_irqs_usr(unsigned int irq)
|
|
|
|
+{
|
|
|
|
+ int sum;
|
|
|
|
+
|
|
|
|
+ irq_lock_sparse();
|
|
|
|
+ sum = kstat_irqs(irq);
|
|
|
|
+ irq_unlock_sparse();
|
|
|
|
+ return sum;
|
|
|
|
+}
|