[PATCH] htirq: refactor so we only have one function that writes to the chip

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>

authored by Eric W. Biederman and committed by Linus Torvalds ec68307c 64d9fe69

+59 -83
+12 -14
arch/i386/kernel/io_apic.c
··· 2624 2624 2625 2625 static void target_ht_irq(unsigned int irq, unsigned int dest) 2626 2626 { 2627 - u32 low, high; 2628 - low = read_ht_irq_low(irq); 2629 - high = read_ht_irq_high(irq); 2627 + struct ht_irq_msg msg; 2628 + fetch_ht_irq_msg(irq, &msg); 2630 2629 2631 - low &= ~(HT_IRQ_LOW_DEST_ID_MASK); 2632 - high &= ~(HT_IRQ_HIGH_DEST_ID_MASK); 2630 + msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK); 2631 + msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); 2633 2632 2634 - low |= HT_IRQ_LOW_DEST_ID(dest); 2635 - high |= HT_IRQ_HIGH_DEST_ID(dest); 2633 + msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest); 2634 + msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); 2636 2635 2637 - write_ht_irq_low(irq, low); 2638 - write_ht_irq_high(irq, high); 2636 + write_ht_irq_msg(irq, &msg); 2639 2637 } 2640 2638 2641 2639 static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) ··· 2671 2673 2672 2674 vector = assign_irq_vector(irq); 2673 2675 if (vector >= 0) { 2674 - u32 low, high; 2676 + struct ht_irq_msg msg; 2675 2677 unsigned dest; 2676 2678 cpumask_t tmp; 2677 2679 ··· 2679 2681 cpu_set(vector >> 8, tmp); 2680 2682 dest = cpu_mask_to_apicid(tmp); 2681 2683 2682 - high = HT_IRQ_HIGH_DEST_ID(dest); 2684 + msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); 2683 2685 2684 - low = HT_IRQ_LOW_BASE | 2686 + msg.address_lo = 2687 + HT_IRQ_LOW_BASE | 2685 2688 HT_IRQ_LOW_DEST_ID(dest) | 2686 2689 HT_IRQ_LOW_VECTOR(vector) | 2687 2690 ((INT_DEST_MODE == 0) ? ··· 2694 2695 HT_IRQ_LOW_MT_ARBITRATED) | 2695 2696 HT_IRQ_LOW_IRQ_MASKED; 2696 2697 2697 - write_ht_irq_low(irq, low); 2698 - write_ht_irq_high(irq, high); 2698 + write_ht_irq_msg(irq, &msg); 2699 2699 2700 2700 set_irq_chip_and_handler_name(irq, &ht_irq_chip, 2701 2701 handle_edge_irq, "edge");
+15 -16
arch/x86_64/kernel/io_apic.c
··· 1955 1955 1956 1956 static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) 1957 1957 { 1958 - u32 low, high; 1959 - low = read_ht_irq_low(irq); 1960 - high = read_ht_irq_high(irq); 1958 + struct ht_irq_msg msg; 1959 + fetch_ht_irq_msg(irq, &msg); 1961 1960 1962 - low &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); 1963 - high &= ~(HT_IRQ_HIGH_DEST_ID_MASK); 1961 + msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); 1962 + msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); 1964 1963 1965 - low |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); 1966 - high |= HT_IRQ_HIGH_DEST_ID(dest); 1964 + msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); 1965 + msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); 1967 1966 1968 - write_ht_irq_low(irq, low); 1969 - write_ht_irq_high(irq, high); 1967 + write_ht_irq_msg(irq, &msg); 1970 1968 } 1971 1969 1972 1970 static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) ··· 1985 1987 1986 1988 dest = cpu_mask_to_apicid(tmp); 1987 1989 1988 - target_ht_irq(irq, dest, vector & 0xff); 1990 + target_ht_irq(irq, dest, vector); 1989 1991 set_native_irq_info(irq, mask); 1990 1992 } 1991 1993 #endif ··· 2008 2010 2009 2011 vector = assign_irq_vector(irq, TARGET_CPUS, &tmp); 2010 2012 if (vector >= 0) { 2011 - u32 low, high; 2013 + struct ht_irq_msg msg; 2012 2014 unsigned dest; 2013 2015 2014 2016 dest = cpu_mask_to_apicid(tmp); 2015 2017 2016 - high = HT_IRQ_HIGH_DEST_ID(dest); 2018 + msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); 2017 2019 2018 - low = HT_IRQ_LOW_BASE | 2020 + msg.address_lo = 2021 + HT_IRQ_LOW_BASE | 2019 2022 HT_IRQ_LOW_DEST_ID(dest) | 2020 2023 HT_IRQ_LOW_VECTOR(vector) | 2021 2024 ((INT_DEST_MODE == 0) ? ··· 2025 2026 HT_IRQ_LOW_RQEOI_EDGE | 2026 2027 ((INT_DELIVERY_MODE != dest_LowestPrio) ? 2027 2028 HT_IRQ_LOW_MT_FIXED : 2028 - HT_IRQ_LOW_MT_ARBITRATED); 2029 + HT_IRQ_LOW_MT_ARBITRATED) | 2030 + HT_IRQ_LOW_IRQ_MASKED; 2029 2031 2030 - write_ht_irq_low(irq, low); 2031 - write_ht_irq_high(irq, high); 2032 + write_ht_irq_msg(irq, &msg); 2032 2033 2033 2034 set_irq_chip_and_handler_name(irq, &ht_irq_chip, 2034 2035 handle_edge_irq, "edge");
+25 -49
drivers/pci/htirq.c
··· 27 27 struct pci_dev *dev; 28 28 unsigned pos; 29 29 unsigned idx; 30 + struct ht_irq_msg msg; 30 31 }; 31 32 32 - void write_ht_irq_low(unsigned int irq, u32 data) 33 + 34 + void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) 33 35 { 34 36 struct ht_irq_cfg *cfg = get_irq_data(irq); 35 37 unsigned long flags; 36 38 spin_lock_irqsave(&ht_irq_lock, flags); 37 - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); 38 - pci_write_config_dword(cfg->dev, cfg->pos + 4, data); 39 + if (cfg->msg.address_lo != msg->address_lo) { 40 + pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); 41 + pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo); 42 + } 43 + if (cfg->msg.address_hi != msg->address_hi) { 44 + pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); 45 + pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); 46 + } 39 47 spin_unlock_irqrestore(&ht_irq_lock, flags); 48 + cfg->msg = *msg; 40 49 } 41 50 42 - void write_ht_irq_high(unsigned int irq, u32 data) 51 + void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) 43 52 { 44 53 struct ht_irq_cfg *cfg = get_irq_data(irq); 45 - unsigned long flags; 46 - spin_lock_irqsave(&ht_irq_lock, flags); 47 - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); 48 - pci_write_config_dword(cfg->dev, cfg->pos + 4, data); 49 - spin_unlock_irqrestore(&ht_irq_lock, flags); 50 - } 51 - 52 - u32 read_ht_irq_low(unsigned int irq) 53 - { 54 - struct ht_irq_cfg *cfg = get_irq_data(irq); 55 - unsigned long flags; 56 - u32 data; 57 - spin_lock_irqsave(&ht_irq_lock, flags); 58 - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); 59 - pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); 60 - spin_unlock_irqrestore(&ht_irq_lock, flags); 61 - return data; 62 - } 63 - 64 - u32 read_ht_irq_high(unsigned int irq) 65 - { 66 - struct ht_irq_cfg *cfg = get_irq_data(irq); 67 - unsigned long flags; 68 - u32 data; 69 - spin_lock_irqsave(&ht_irq_lock, flags); 70 - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); 71 - pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); 72 - spin_unlock_irqrestore(&ht_irq_lock, flags); 73 - return data; 54 + *msg = cfg->msg; 74 55 } 75 56 76 57 void mask_ht_irq(unsigned int irq) 77 58 { 78 59 struct ht_irq_cfg *cfg; 79 - unsigned long flags; 80 - u32 data; 60 + struct ht_irq_msg msg; 81 61 82 62 cfg = get_irq_data(irq); 83 63 84 - spin_lock_irqsave(&ht_irq_lock, flags); 85 - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); 86 - pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); 87 - data |= 1; 88 - pci_write_config_dword(cfg->dev, cfg->pos + 4, data); 89 - spin_unlock_irqrestore(&ht_irq_lock, flags); 64 + msg = cfg->msg; 65 + msg.address_lo |= 1; 66 + write_ht_irq_msg(irq, &msg); 90 67 } 91 68 92 69 void unmask_ht_irq(unsigned int irq) 93 70 { 94 71 struct ht_irq_cfg *cfg; 95 - unsigned long flags; 96 - u32 data; 72 + struct ht_irq_msg msg; 97 73 98 74 cfg = get_irq_data(irq); 99 75 100 - spin_lock_irqsave(&ht_irq_lock, flags); 101 - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); 102 - pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); 103 - data &= ~1; 104 - pci_write_config_dword(cfg->dev, cfg->pos + 4, data); 105 - spin_unlock_irqrestore(&ht_irq_lock, flags); 76 + msg = cfg->msg; 77 + msg.address_lo &= ~1; 78 + write_ht_irq_msg(irq, &msg); 106 79 } 107 80 108 81 /** ··· 125 152 cfg->dev = dev; 126 153 cfg->pos = pos; 127 154 cfg->idx = 0x10 + (idx * 2); 155 + /* Initialize msg to a value that will never match the first write. */ 156 + cfg->msg.address_lo = 0xffffffff; 157 + cfg->msg.address_hi = 0xffffffff; 128 158 129 159 irq = create_irq(); 130 160 if (irq < 0) {
+7 -4
include/linux/htirq.h
··· 1 1 #ifndef LINUX_HTIRQ_H 2 2 #define LINUX_HTIRQ_H 3 3 4 + struct ht_irq_msg { 5 + u32 address_lo; /* low 32 bits of the ht irq message */ 6 + u32 address_hi; /* high 32 bits of the it irq message */ 7 + }; 8 + 4 9 /* Helper functions.. */ 5 - void write_ht_irq_low(unsigned int irq, u32 data); 6 - void write_ht_irq_high(unsigned int irq, u32 data); 7 - u32 read_ht_irq_low(unsigned int irq); 8 - u32 read_ht_irq_high(unsigned int irq); 10 + void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); 11 + void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); 9 12 void mask_ht_irq(unsigned int irq); 10 13 void unmask_ht_irq(unsigned int irq); 11 14