aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/io_apic.c26
-rw-r--r--arch/x86_64/kernel/io_apic.c31
-rw-r--r--drivers/pci/htirq.c72
-rw-r--r--include/linux/htirq.h11
4 files changed, 58 insertions, 82 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 507983c513c3..ad84bc2802a6 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -2624,18 +2624,16 @@ void arch_teardown_msi_irq(unsigned int irq)
2624 2624
2625static void target_ht_irq(unsigned int irq, unsigned int dest) 2625static void target_ht_irq(unsigned int irq, unsigned int dest)
2626{ 2626{
2627 u32 low, high; 2627 struct ht_irq_msg msg;
2628 low = read_ht_irq_low(irq); 2628 fetch_ht_irq_msg(irq, &msg);
2629 high = read_ht_irq_high(irq);
2630 2629
2631 low &= ~(HT_IRQ_LOW_DEST_ID_MASK); 2630 msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK);
2632 high &= ~(HT_IRQ_HIGH_DEST_ID_MASK); 2631 msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
2633 2632
2634 low |= HT_IRQ_LOW_DEST_ID(dest); 2633 msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest);
2635 high |= HT_IRQ_HIGH_DEST_ID(dest); 2634 msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
2636 2635
2637 write_ht_irq_low(irq, low); 2636 write_ht_irq_msg(irq, &msg);
2638 write_ht_irq_high(irq, high);
2639} 2637}
2640 2638
2641static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) 2639static 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)
2673 2671
2674 vector = assign_irq_vector(irq); 2672 vector = assign_irq_vector(irq);
2675 if (vector >= 0) { 2673 if (vector >= 0) {
2676 u32 low, high; 2674 struct ht_irq_msg msg;
2677 unsigned dest; 2675 unsigned dest;
2678 cpumask_t tmp; 2676 cpumask_t tmp;
2679 2677
@@ -2681,9 +2679,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
2681 cpu_set(vector >> 8, tmp); 2679 cpu_set(vector >> 8, tmp);
2682 dest = cpu_mask_to_apicid(tmp); 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 HT_IRQ_LOW_DEST_ID(dest) | 2686 HT_IRQ_LOW_DEST_ID(dest) |
2688 HT_IRQ_LOW_VECTOR(vector) | 2687 HT_IRQ_LOW_VECTOR(vector) |
2689 ((INT_DEST_MODE == 0) ? 2688 ((INT_DEST_MODE == 0) ?
@@ -2695,8 +2694,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
2695 HT_IRQ_LOW_MT_ARBITRATED) | 2694 HT_IRQ_LOW_MT_ARBITRATED) |
2696 HT_IRQ_LOW_IRQ_MASKED; 2695 HT_IRQ_LOW_IRQ_MASKED;
2697 2696
2698 write_ht_irq_low(irq, low); 2697 write_ht_irq_msg(irq, &msg);
2699 write_ht_irq_high(irq, high);
2700 2698
2701 set_irq_chip_and_handler_name(irq, &ht_irq_chip, 2699 set_irq_chip_and_handler_name(irq, &ht_irq_chip,
2702 handle_edge_irq, "edge"); 2700 handle_edge_irq, "edge");
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 3b8f9c68ad3c..41bfc49301ad 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1955,18 +1955,16 @@ void arch_teardown_msi_irq(unsigned int irq)
1955 1955
1956static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) 1956static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
1957{ 1957{
1958 u32 low, high; 1958 struct ht_irq_msg msg;
1959 low = read_ht_irq_low(irq); 1959 fetch_ht_irq_msg(irq, &msg);
1960 high = read_ht_irq_high(irq);
1961 1960
1962 low &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); 1961 msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
1963 high &= ~(HT_IRQ_HIGH_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); 1964 msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
1966 high |= HT_IRQ_HIGH_DEST_ID(dest); 1965 msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
1967 1966
1968 write_ht_irq_low(irq, low); 1967 write_ht_irq_msg(irq, &msg);
1969 write_ht_irq_high(irq, high);
1970} 1968}
1971 1969
1972static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) 1970static 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)
1987 1985
1988 dest = cpu_mask_to_apicid(tmp); 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 set_native_irq_info(irq, mask); 1989 set_native_irq_info(irq, mask);
1992} 1990}
1993#endif 1991#endif
@@ -2010,14 +2008,15 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
2010 2008
2011 vector = assign_irq_vector(irq, TARGET_CPUS, &tmp); 2009 vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
2012 if (vector >= 0) { 2010 if (vector >= 0) {
2013 u32 low, high; 2011 struct ht_irq_msg msg;
2014 unsigned dest; 2012 unsigned dest;
2015 2013
2016 dest = cpu_mask_to_apicid(tmp); 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 HT_IRQ_LOW_DEST_ID(dest) | 2020 HT_IRQ_LOW_DEST_ID(dest) |
2022 HT_IRQ_LOW_VECTOR(vector) | 2021 HT_IRQ_LOW_VECTOR(vector) |
2023 ((INT_DEST_MODE == 0) ? 2022 ((INT_DEST_MODE == 0) ?
@@ -2026,10 +2025,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
2026 HT_IRQ_LOW_RQEOI_EDGE | 2025 HT_IRQ_LOW_RQEOI_EDGE |
2027 ((INT_DELIVERY_MODE != dest_LowestPrio) ? 2026 ((INT_DELIVERY_MODE != dest_LowestPrio) ?
2028 HT_IRQ_LOW_MT_FIXED : 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); 2031 write_ht_irq_msg(irq, &msg);
2032 write_ht_irq_high(irq, high);
2033 2032
2034 set_irq_chip_and_handler_name(irq, &ht_irq_chip, 2033 set_irq_chip_and_handler_name(irq, &ht_irq_chip,
2035 handle_edge_irq, "edge"); 2034 handle_edge_irq, "edge");
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 0e27f2404a83..e346fe31f97a 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -27,82 +27,55 @@ struct ht_irq_cfg {
27 struct pci_dev *dev; 27 struct pci_dev *dev;
28 unsigned pos; 28 unsigned pos;
29 unsigned idx; 29 unsigned idx;
30 struct ht_irq_msg msg;
30}; 31};
31 32
32void 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
42void write_ht_irq_high(unsigned int irq, u32 data)
43{
44 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 33
52u32 read_ht_irq_low(unsigned int irq) 34void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
53{ 35{
54 struct ht_irq_cfg *cfg = get_irq_data(irq); 36 struct ht_irq_cfg *cfg = get_irq_data(irq);
55 unsigned long flags; 37 unsigned long flags;
56 u32 data;
57 spin_lock_irqsave(&ht_irq_lock, flags); 38 spin_lock_irqsave(&ht_irq_lock, flags);
58 pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); 39 if (cfg->msg.address_lo != msg->address_lo) {
59 pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); 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 }
60 spin_unlock_irqrestore(&ht_irq_lock, flags); 47 spin_unlock_irqrestore(&ht_irq_lock, flags);
61 return data; 48 cfg->msg = *msg;
62} 49}
63 50
64u32 read_ht_irq_high(unsigned int irq) 51void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
65{ 52{
66 struct ht_irq_cfg *cfg = get_irq_data(irq); 53 struct ht_irq_cfg *cfg = get_irq_data(irq);
67 unsigned long flags; 54 *msg = cfg->msg;
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} 55}
75 56
76void mask_ht_irq(unsigned int irq) 57void mask_ht_irq(unsigned int irq)
77{ 58{
78 struct ht_irq_cfg *cfg; 59 struct ht_irq_cfg *cfg;
79 unsigned long flags; 60 struct ht_irq_msg msg;
80 u32 data;
81 61
82 cfg = get_irq_data(irq); 62 cfg = get_irq_data(irq);
83 63
84 spin_lock_irqsave(&ht_irq_lock, flags); 64 msg = cfg->msg;
85 pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); 65 msg.address_lo |= 1;
86 pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); 66 write_ht_irq_msg(irq, &msg);
87 data |= 1;
88 pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
89 spin_unlock_irqrestore(&ht_irq_lock, flags);
90} 67}
91 68
92void unmask_ht_irq(unsigned int irq) 69void unmask_ht_irq(unsigned int irq)
93{ 70{
94 struct ht_irq_cfg *cfg; 71 struct ht_irq_cfg *cfg;
95 unsigned long flags; 72 struct ht_irq_msg msg;
96 u32 data;
97 73
98 cfg = get_irq_data(irq); 74 cfg = get_irq_data(irq);
99 75
100 spin_lock_irqsave(&ht_irq_lock, flags); 76 msg = cfg->msg;
101 pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); 77 msg.address_lo &= ~1;
102 pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); 78 write_ht_irq_msg(irq, &msg);
103 data &= ~1;
104 pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
105 spin_unlock_irqrestore(&ht_irq_lock, flags);
106} 79}
107 80
108/** 81/**
@@ -152,6 +125,9 @@ int ht_create_irq(struct pci_dev *dev, int idx)
152 cfg->dev = dev; 125 cfg->dev = dev;
153 cfg->pos = pos; 126 cfg->pos = pos;
154 cfg->idx = 0x10 + (idx * 2); 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 irq = create_irq(); 132 irq = create_irq();
157 if (irq < 0) { 133 if (irq < 0) {
diff --git a/include/linux/htirq.h b/include/linux/htirq.h
index 1f15ce279a23..108f0d91e11e 100644
--- a/include/linux/htirq.h
+++ b/include/linux/htirq.h
@@ -1,11 +1,14 @@
1#ifndef LINUX_HTIRQ_H 1#ifndef LINUX_HTIRQ_H
2#define LINUX_HTIRQ_H 2#define LINUX_HTIRQ_H
3 3
4struct 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/* Helper functions.. */ 9/* Helper functions.. */
5void write_ht_irq_low(unsigned int irq, u32 data); 10void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
6void write_ht_irq_high(unsigned int irq, u32 data); 11void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
7u32 read_ht_irq_low(unsigned int irq);
8u32 read_ht_irq_high(unsigned int irq);
9void mask_ht_irq(unsigned int irq); 12void mask_ht_irq(unsigned int irq);
10void unmask_ht_irq(unsigned int irq); 13void unmask_ht_irq(unsigned int irq);
11 14