[PATCH] htirq: refactor so we only have one function that writes to the chip
authorEric W. Biederman <ebiederm@xmission.com>
Thu, 9 Nov 2006 01:44:57 +0000 (17:44 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 9 Nov 2006 02:29:24 +0000 (18:29 -0800)
This refactoring actually optimizes the code a little by caching the value
that we think the device is programmed with instead of reading it back from
the hardware.  Which simplifies the code a little and should speed things up a
bit.

This patch introduces the concept of a ht_irq_msg and modifies the
architecture read/write routines to update this code.

There is a minor consistency fix here as well as x86_64 forgot to initialize
the htirq as masked.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Andi Kleen <ak@suse.de>
Acked-by: Bryan O'Sullivan <bos@pathscale.com>
Cc: <olson@pathscale.com>
Cc: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/io_apic.c
arch/x86_64/kernel/io_apic.c
drivers/pci/htirq.c
include/linux/htirq.h

index 507983c..ad84bc2 100644 (file)
@@ -2624,18 +2624,16 @@ void arch_teardown_msi_irq(unsigned int irq)
 
 static void target_ht_irq(unsigned int irq, unsigned int dest)
 {
-       u32 low, high;
-       low  = read_ht_irq_low(irq);
-       high = read_ht_irq_high(irq);
+       struct ht_irq_msg msg;
+       fetch_ht_irq_msg(irq, &msg);
 
-       low  &= ~(HT_IRQ_LOW_DEST_ID_MASK);
-       high &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
+       msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK);
+       msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
 
-       low  |= HT_IRQ_LOW_DEST_ID(dest);
-       high |= HT_IRQ_HIGH_DEST_ID(dest);
+       msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest);
+       msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
 
-       write_ht_irq_low(irq, low);
-       write_ht_irq_high(irq, high);
+       write_ht_irq_msg(irq, &msg);
 }
 
 static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
@@ -2673,7 +2671,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 
        vector = assign_irq_vector(irq);
        if (vector >= 0) {
-               u32 low, high;
+               struct ht_irq_msg msg;
                unsigned dest;
                cpumask_t tmp;
 
@@ -2681,9 +2679,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
                cpu_set(vector >> 8, tmp);
                dest = cpu_mask_to_apicid(tmp);
 
-               high =  HT_IRQ_HIGH_DEST_ID(dest);
+               msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
 
-               low =   HT_IRQ_LOW_BASE |
+               msg.address_lo =
+                       HT_IRQ_LOW_BASE |
                        HT_IRQ_LOW_DEST_ID(dest) |
                        HT_IRQ_LOW_VECTOR(vector) |
                        ((INT_DEST_MODE == 0) ?
@@ -2695,8 +2694,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
                                HT_IRQ_LOW_MT_ARBITRATED) |
                        HT_IRQ_LOW_IRQ_MASKED;
 
-               write_ht_irq_low(irq, low);
-               write_ht_irq_high(irq, high);
+               write_ht_irq_msg(irq, &msg);
 
                set_irq_chip_and_handler_name(irq, &ht_irq_chip,
                                              handle_edge_irq, "edge");
index 3b8f9c6..41bfc49 100644 (file)
@@ -1955,18 +1955,16 @@ void arch_teardown_msi_irq(unsigned int irq)
 
 static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
 {
-       u32 low, high;
-       low  = read_ht_irq_low(irq);
-       high = read_ht_irq_high(irq);
+       struct ht_irq_msg msg;
+       fetch_ht_irq_msg(irq, &msg);
 
-       low  &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
-       high &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
+       msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
+       msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
 
-       low  |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
-       high |= HT_IRQ_HIGH_DEST_ID(dest);
+       msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
+       msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
 
-       write_ht_irq_low(irq, low);
-       write_ht_irq_high(irq, high);
+       write_ht_irq_msg(irq, &msg);
 }
 
 static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
@@ -1987,7 +1985,7 @@ static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
 
        dest = cpu_mask_to_apicid(tmp);
 
-       target_ht_irq(irq, dest, vector & 0xff);
+       target_ht_irq(irq, dest, vector);
        set_native_irq_info(irq, mask);
 }
 #endif
@@ -2010,14 +2008,15 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 
        vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
        if (vector >= 0) {
-               u32 low, high;
+               struct ht_irq_msg msg;
                unsigned dest;
 
                dest = cpu_mask_to_apicid(tmp);
 
-               high =  HT_IRQ_HIGH_DEST_ID(dest);
+               msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
 
-               low =   HT_IRQ_LOW_BASE |
+               msg.address_lo =
+                       HT_IRQ_LOW_BASE |
                        HT_IRQ_LOW_DEST_ID(dest) |
                        HT_IRQ_LOW_VECTOR(vector) |
                        ((INT_DEST_MODE == 0) ?
@@ -2026,10 +2025,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
                        HT_IRQ_LOW_RQEOI_EDGE |
                        ((INT_DELIVERY_MODE != dest_LowestPrio) ?
                                HT_IRQ_LOW_MT_FIXED :
-                               HT_IRQ_LOW_MT_ARBITRATED);
+                               HT_IRQ_LOW_MT_ARBITRATED) |
+                       HT_IRQ_LOW_IRQ_MASKED;
 
-               write_ht_irq_low(irq, low);
-               write_ht_irq_high(irq, high);
+               write_ht_irq_msg(irq, &msg);
 
                set_irq_chip_and_handler_name(irq, &ht_irq_chip,
                                              handle_edge_irq, "edge");
index 0e27f24..e346fe3 100644 (file)
@@ -27,82 +27,55 @@ struct ht_irq_cfg {
        struct pci_dev *dev;
        unsigned pos;
        unsigned idx;
+       struct ht_irq_msg msg;
 };
 
-void write_ht_irq_low(unsigned int irq, u32 data)
-{
-       struct ht_irq_cfg *cfg = get_irq_data(irq);
-       unsigned long flags;
-       spin_lock_irqsave(&ht_irq_lock, flags);
-       pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
-       pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
-       spin_unlock_irqrestore(&ht_irq_lock, flags);
-}
-
-void write_ht_irq_high(unsigned int irq, u32 data)
-{
-       struct ht_irq_cfg *cfg = get_irq_data(irq);
-       unsigned long flags;
-       spin_lock_irqsave(&ht_irq_lock, flags);
-       pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1);
-       pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
-       spin_unlock_irqrestore(&ht_irq_lock, flags);
-}
 
-u32 read_ht_irq_low(unsigned int irq)
+void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
 {
        struct ht_irq_cfg *cfg = get_irq_data(irq);
        unsigned long flags;
-       u32 data;
        spin_lock_irqsave(&ht_irq_lock, flags);
-       pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
-       pci_read_config_dword(cfg->dev, cfg->pos + 4, &data);
+       if (cfg->msg.address_lo != msg->address_lo) {
+               pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
+               pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo);
+       }
+       if (cfg->msg.address_hi != msg->address_hi) {
+               pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1);
+               pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi);
+       }
        spin_unlock_irqrestore(&ht_irq_lock, flags);
-       return data;
+       cfg->msg = *msg;
 }
 
-u32 read_ht_irq_high(unsigned int irq)
+void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
 {
        struct ht_irq_cfg *cfg = get_irq_data(irq);
-       unsigned long flags;
-       u32 data;
-       spin_lock_irqsave(&ht_irq_lock, flags);
-       pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1);
-       pci_read_config_dword(cfg->dev, cfg->pos + 4, &data);
-       spin_unlock_irqrestore(&ht_irq_lock, flags);
-       return data;
+       *msg = cfg->msg;
 }
 
 void mask_ht_irq(unsigned int irq)
 {
        struct ht_irq_cfg *cfg;
-       unsigned long flags;
-       u32 data;
+       struct ht_irq_msg msg;
 
        cfg = get_irq_data(irq);
 
-       spin_lock_irqsave(&ht_irq_lock, flags);
-       pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
-       pci_read_config_dword(cfg->dev, cfg->pos + 4, &data);
-       data |= 1;
-       pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
-       spin_unlock_irqrestore(&ht_irq_lock, flags);
+       msg = cfg->msg;
+       msg.address_lo |= 1;
+       write_ht_irq_msg(irq, &msg);
 }
 
 void unmask_ht_irq(unsigned int irq)
 {
        struct ht_irq_cfg *cfg;
-       unsigned long flags;
-       u32 data;
+       struct ht_irq_msg msg;
 
        cfg = get_irq_data(irq);
 
-       spin_lock_irqsave(&ht_irq_lock, flags);
-       pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
-       pci_read_config_dword(cfg->dev, cfg->pos + 4, &data);
-       data &= ~1;
-       pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
-       spin_unlock_irqrestore(&ht_irq_lock, flags);
+       msg = cfg->msg;
+       msg.address_lo &= ~1;
+       write_ht_irq_msg(irq, &msg);
 }
 
 /**
@@ -152,6 +125,9 @@ int ht_create_irq(struct pci_dev *dev, int idx)
        cfg->dev = dev;
        cfg->pos = pos;
        cfg->idx = 0x10 + (idx * 2);
+       /* Initialize msg to a value that will never match the first write. */
+       cfg->msg.address_lo = 0xffffffff;
+       cfg->msg.address_hi = 0xffffffff;
 
        irq = create_irq();
        if (irq < 0) {
index 1f15ce2..108f0d9 100644 (file)
@@ -1,11 +1,14 @@
 #ifndef LINUX_HTIRQ_H
 #define LINUX_HTIRQ_H
 
+struct ht_irq_msg {
+       u32     address_lo;     /* low 32 bits of the ht irq message */
+       u32     address_hi;     /* high 32 bits of the it irq message */
+};
+
 /* Helper functions.. */
-void write_ht_irq_low(unsigned int irq, u32 data);
-void write_ht_irq_high(unsigned int irq, u32 data);
-u32  read_ht_irq_low(unsigned int irq);
-u32  read_ht_irq_high(unsigned int irq);
+void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
+void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
 void mask_ht_irq(unsigned int irq);
 void unmask_ht_irq(unsigned int irq);