Page MenuHomeFreeBSD

D42232.id128848.diff
No OneTemporary

D42232.id128848.diff

diff --git a/sys/x86/x86/msi.c b/sys/x86/x86/msi.c
--- a/sys/x86/x86/msi.c
+++ b/sys/x86/x86/msi.c
@@ -116,10 +116,11 @@
struct msi_intsrc *msi_first; /* First source in group. */
u_int msi_irq; /* IRQ cookie. */
u_int msi_msix; /* MSI-X message. */
- u_int msi_vector:8; /* IDT vector. */
u_int msi_cpu; /* Local APIC ID. (g) */
+ u_int msi_vector:8; /* IDT vector. */
u_int msi_count:8; /* Messages in this group. (g) */
u_int msi_maxcount:8; /* Alignment for this group. (g) */
+ u_int msi_enabled:8; /* Enabled messages in this group. (g) */
u_int *msi_irqs; /* Group's IRQ list. (g) */
u_int msi_remap_cookie;
};
@@ -199,12 +200,39 @@
lapic_eoi();
}
+static void
+msi_enable_group(struct msi_intsrc *msi)
+{
+ MPASS(msi->msi_first == msi);
+
+ if (msi->msi_enabled == 0) {
+ for (u_int i = 0; i < msi->msi_count; i++)
+ apic_enable_vector(msi->msi_cpu, msi->msi_vector + i);
+ }
+ msi->msi_enabled++;
+}
+
static void
msi_enable_intr(struct intsrc *isrc)
{
struct msi_intsrc *msi = (struct msi_intsrc *)isrc;
- apic_enable_vector(msi->msi_cpu, msi->msi_vector);
+ if (msi->msi_first != msi || msi->msi_count != 1)
+ msi_enable_group(msi->msi_first);
+ else
+ apic_enable_vector(msi->msi_cpu, msi->msi_vector);
+}
+
+static void
+msi_disable_group(struct msi_intsrc *msi)
+{
+ MPASS(msi->msi_first == msi);
+
+ msi->msi_enabled--;
+ if (msi->msi_enabled == 0) {
+ for (u_int i = 0; i < msi->msi_count; i++)
+ apic_disable_vector(msi->msi_cpu, msi->msi_vector + i);
+ }
}
static void
@@ -212,7 +240,10 @@
{
struct msi_intsrc *msi = (struct msi_intsrc *)isrc;
- apic_disable_vector(msi->msi_cpu, msi->msi_vector);
+ if (msi->msi_first != msi || msi->msi_count != 1)
+ msi_disable_group(msi->msi_first);
+ else
+ apic_disable_vector(msi->msi_cpu, msi->msi_vector);
}
static int
@@ -277,13 +308,13 @@
/* Must be set before BUS_REMAP_INTR as it may call back into MSI. */
msi->msi_cpu = apic_id;
msi->msi_vector = vector;
- if (msi->msi_intsrc.is_handlers > 0)
+ if (msi->msi_count > 1) {
+ if (msi->msi_enabled > 0) {
+ for (i = 0; i < msi->msi_count; i++)
+ apic_enable_vector(apic_id, vector + i);
+ }
+ } else if (msi->msi_intsrc.is_handlers > 0)
apic_enable_vector(msi->msi_cpu, msi->msi_vector);
- for (i = 1; i < msi->msi_count; i++) {
- sib = (struct msi_intsrc *)intr_lookup_source(msi->msi_irqs[i]);
- if (sib->msi_intsrc.is_handlers > 0)
- apic_enable_vector(apic_id, vector + i);
- }
error = BUS_REMAP_INTR(device_get_parent(msi->msi_dev), msi->msi_dev,
msi->msi_irq);
if (error == 0) {
@@ -317,13 +348,16 @@
* to prevent races where we could miss an interrupt. If BUS_REMAP_INTR
* failed then we disable and free the new, unused vector(s).
*/
- if (msi->msi_intsrc.is_handlers > 0)
+ if (msi->msi_count > 1) {
+ if (msi->msi_enabled > 0) {
+ for (i = 0; i < msi->msi_count; i++)
+ apic_disable_vector(old_id, old_vector + i);
+ }
+ } else if (msi->msi_intsrc.is_handlers > 0)
apic_disable_vector(old_id, old_vector);
apic_free_vector(old_id, old_vector, msi->msi_irq);
for (i = 1; i < msi->msi_count; i++) {
sib = (struct msi_intsrc *)intr_lookup_source(msi->msi_irqs[i]);
- if (sib->msi_intsrc.is_handlers > 0)
- apic_disable_vector(old_id, old_vector + i);
apic_free_vector(old_id, old_vector + i, msi->msi_irqs[i]);
}
return (error);

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 22, 9:51 AM (4 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31969429
Default Alt Text
D42232.id128848.diff (3 KB)

Event Timeline