diff options
-rw-r--r-- | arch/i386/kernel/io_apic.c | 26 | ||||
-rw-r--r-- | arch/x86_64/kernel/io_apic.c | 31 | ||||
-rw-r--r-- | drivers/pci/htirq.c | 72 | ||||
-rw-r--r-- | include/linux/htirq.h | 11 |
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 | ||
2625 | static void target_ht_irq(unsigned int irq, unsigned int dest) | 2625 | static 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 | ||
2641 | static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) | 2639 | 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) | |||
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 | ||
1956 | static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) | 1956 | static 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 | ||
1972 | static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) | 1970 | 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) | |||
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 | ||
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 | |||
42 | void 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 | ||
52 | u32 read_ht_irq_low(unsigned int irq) | 34 | void 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 | ||
64 | u32 read_ht_irq_high(unsigned int irq) | 51 | void 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 | ||
76 | void mask_ht_irq(unsigned int irq) | 57 | void 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 | ||
92 | void unmask_ht_irq(unsigned int irq) | 69 | void 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 | ||
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 | /* Helper functions.. */ | 9 | /* Helper functions.. */ |
5 | void write_ht_irq_low(unsigned int irq, u32 data); | 10 | void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); |
6 | void write_ht_irq_high(unsigned int irq, u32 data); | 11 | void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); |
7 | u32 read_ht_irq_low(unsigned int irq); | ||
8 | u32 read_ht_irq_high(unsigned int irq); | ||
9 | void mask_ht_irq(unsigned int irq); | 12 | void mask_ht_irq(unsigned int irq); |
10 | void unmask_ht_irq(unsigned int irq); | 13 | void unmask_ht_irq(unsigned int irq); |
11 | 14 | ||