Commit ec68307cc5a8dc499e48693843bb42f6b6028458

Authored by Eric W. Biederman
Committed by Linus Torvalds
1 parent 64d9fe6973

[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");
... ... @@ -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