Commit ec68307cc5a8dc499e48693843bb42f6b6028458
Committed by
Linus Torvalds
1 parent
64d9fe6973
Exists in
master
and in
39 other branches
[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>
Showing 4 changed files with 58 additions and 82 deletions Side-by-side Diff
arch/i386/kernel/io_apic.c
... | ... | @@ -2624,18 +2624,16 @@ |
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) |
... | ... | @@ -2673,7 +2671,7 @@ |
2673 | 2671 | |
2674 | 2672 | vector = assign_irq_vector(irq); |
2675 | 2673 | if (vector >= 0) { |
2676 | - u32 low, high; | |
2674 | + struct ht_irq_msg msg; | |
2677 | 2675 | unsigned dest; |
2678 | 2676 | cpumask_t tmp; |
2679 | 2677 | |
2680 | 2678 | |
... | ... | @@ -2681,9 +2679,10 @@ |
2681 | 2679 | cpu_set(vector >> 8, tmp); |
2682 | 2680 | dest = cpu_mask_to_apicid(tmp); |
2683 | 2681 | |
2684 | - high = HT_IRQ_HIGH_DEST_ID(dest); | |
2682 | + msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); | |
2685 | 2683 | |
2686 | - low = HT_IRQ_LOW_BASE | | |
2684 | + msg.address_lo = | |
2685 | + HT_IRQ_LOW_BASE | | |
2687 | 2686 | HT_IRQ_LOW_DEST_ID(dest) | |
2688 | 2687 | HT_IRQ_LOW_VECTOR(vector) | |
2689 | 2688 | ((INT_DEST_MODE == 0) ? |
... | ... | @@ -2695,8 +2694,7 @@ |
2695 | 2694 | HT_IRQ_LOW_MT_ARBITRATED) | |
2696 | 2695 | HT_IRQ_LOW_IRQ_MASKED; |
2697 | 2696 | |
2698 | - write_ht_irq_low(irq, low); | |
2699 | - write_ht_irq_high(irq, high); | |
2697 | + write_ht_irq_msg(irq, &msg); | |
2700 | 2698 | |
2701 | 2699 | set_irq_chip_and_handler_name(irq, &ht_irq_chip, |
2702 | 2700 | handle_edge_irq, "edge"); |
arch/x86_64/kernel/io_apic.c
... | ... | @@ -1955,18 +1955,16 @@ |
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) |
... | ... | @@ -1987,7 +1985,7 @@ |
1987 | 1985 | |
1988 | 1986 | dest = cpu_mask_to_apicid(tmp); |
1989 | 1987 | |
1990 | - target_ht_irq(irq, dest, vector & 0xff); | |
1988 | + target_ht_irq(irq, dest, vector); | |
1991 | 1989 | set_native_irq_info(irq, mask); |
1992 | 1990 | } |
1993 | 1991 | #endif |
1994 | 1992 | |
1995 | 1993 | |
... | ... | @@ -2010,14 +2008,15 @@ |
2010 | 2008 | |
2011 | 2009 | vector = assign_irq_vector(irq, TARGET_CPUS, &tmp); |
2012 | 2010 | if (vector >= 0) { |
2013 | - u32 low, high; | |
2011 | + struct ht_irq_msg msg; | |
2014 | 2012 | unsigned dest; |
2015 | 2013 | |
2016 | 2014 | dest = cpu_mask_to_apicid(tmp); |
2017 | 2015 | |
2018 | - high = HT_IRQ_HIGH_DEST_ID(dest); | |
2016 | + msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); | |
2019 | 2017 | |
2020 | - low = HT_IRQ_LOW_BASE | | |
2018 | + msg.address_lo = | |
2019 | + HT_IRQ_LOW_BASE | | |
2021 | 2020 | HT_IRQ_LOW_DEST_ID(dest) | |
2022 | 2021 | HT_IRQ_LOW_VECTOR(vector) | |
2023 | 2022 | ((INT_DEST_MODE == 0) ? |
2024 | 2023 | |
... | ... | @@ -2026,10 +2025,10 @@ |
2026 | 2025 | HT_IRQ_LOW_RQEOI_EDGE | |
2027 | 2026 | ((INT_DELIVERY_MODE != dest_LowestPrio) ? |
2028 | 2027 | HT_IRQ_LOW_MT_FIXED : |
2029 | - HT_IRQ_LOW_MT_ARBITRATED); | |
2028 | + HT_IRQ_LOW_MT_ARBITRATED) | | |
2029 | + HT_IRQ_LOW_IRQ_MASKED; | |
2030 | 2030 | |
2031 | - write_ht_irq_low(irq, low); | |
2032 | - write_ht_irq_high(irq, high); | |
2031 | + write_ht_irq_msg(irq, &msg); | |
2033 | 2032 | |
2034 | 2033 | set_irq_chip_and_handler_name(irq, &ht_irq_chip, |
2035 | 2034 | handle_edge_irq, "edge"); |
drivers/pci/htirq.c
... | ... | @@ -27,82 +27,55 @@ |
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 | - struct ht_irq_cfg *cfg = get_irq_data(irq); | |
35 | - unsigned long flags; | |
36 | - 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 | - spin_unlock_irqrestore(&ht_irq_lock, flags); | |
40 | -} | |
41 | 33 | |
42 | -void write_ht_irq_high(unsigned int irq, u32 data) | |
34 | +void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) | |
43 | 35 | { |
44 | 36 | struct ht_irq_cfg *cfg = get_irq_data(irq); |
45 | 37 | unsigned long flags; |
46 | 38 | 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); | |
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 | + } | |
49 | 47 | spin_unlock_irqrestore(&ht_irq_lock, flags); |
48 | + cfg->msg = *msg; | |
50 | 49 | } |
51 | 50 | |
52 | -u32 read_ht_irq_low(unsigned int irq) | |
51 | +void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) | |
53 | 52 | { |
54 | 53 | 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; | |
54 | + *msg = cfg->msg; | |
62 | 55 | } |
63 | 56 | |
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; | |
74 | -} | |
75 | - | |
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 | /** |
... | ... | @@ -152,6 +125,9 @@ |
152 | 125 | cfg->dev = dev; |
153 | 126 | cfg->pos = pos; |
154 | 127 | cfg->idx = 0x10 + (idx * 2); |
128 | + /* Initialize msg to a value that will never match the first write. */ | |
129 | + cfg->msg.address_lo = 0xffffffff; | |
130 | + cfg->msg.address_hi = 0xffffffff; | |
155 | 131 | |
156 | 132 | irq = create_irq(); |
157 | 133 | if (irq < 0) { |
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 |