diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-11-08 20:44:57 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-11-08 21:29:25 -0500 |
commit | 43539c38cd8edb915d1f0e1f55dcb70638b4cc8e (patch) | |
tree | 623568ee8f87684be487145fbc7a5da16320afde | |
parent | ec68307cc5a8dc499e48693843bb42f6b6028458 (diff) |
[PATCH] htirq: allow buggy drivers of buggy hardware to write the registers
This patch adds a variant of ht_create_irq __ht_create_irq that takes an
aditional parameter update that is a function that is called whenever we want
to write to a drivers htirq configuration registers.
This is needed to support the ipath_iba6110 because it's registers in the
proper location are not actually conected to the hardware that controlls
interrupt delivery.
[bos@serpentine.com: fixes]
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Andi Kleen <ak@suse.de>
Cc: <olson@pathscale.com>
Cc: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/pci/htirq.c | 29 | ||||
-rw-r--r-- | include/linux/htirq.h | 5 |
2 files changed, 29 insertions, 5 deletions
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index e346fe31f97a..0a8d1cce9fa0 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c | |||
@@ -25,6 +25,8 @@ static DEFINE_SPINLOCK(ht_irq_lock); | |||
25 | 25 | ||
26 | struct ht_irq_cfg { | 26 | struct ht_irq_cfg { |
27 | struct pci_dev *dev; | 27 | struct pci_dev *dev; |
28 | /* Update callback used to cope with buggy hardware */ | ||
29 | ht_irq_update_t *update; | ||
28 | unsigned pos; | 30 | unsigned pos; |
29 | unsigned idx; | 31 | unsigned idx; |
30 | struct ht_irq_msg msg; | 32 | struct ht_irq_msg msg; |
@@ -44,6 +46,8 @@ void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) | |||
44 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | 46 | 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); | 47 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); |
46 | } | 48 | } |
49 | if (cfg->update) | ||
50 | cfg->update(cfg->dev, irq, msg); | ||
47 | spin_unlock_irqrestore(&ht_irq_lock, flags); | 51 | spin_unlock_irqrestore(&ht_irq_lock, flags); |
48 | cfg->msg = *msg; | 52 | cfg->msg = *msg; |
49 | } | 53 | } |
@@ -79,16 +83,14 @@ void unmask_ht_irq(unsigned int irq) | |||
79 | } | 83 | } |
80 | 84 | ||
81 | /** | 85 | /** |
82 | * ht_create_irq - create an irq and attach it to a device. | 86 | * __ht_create_irq - create an irq and attach it to a device. |
83 | * @dev: The hypertransport device to find the irq capability on. | 87 | * @dev: The hypertransport device to find the irq capability on. |
84 | * @idx: Which of the possible irqs to attach to. | 88 | * @idx: Which of the possible irqs to attach to. |
85 | * | 89 | * @update: Function to be called when changing the htirq message |
86 | * ht_create_irq is needs to be called for all hypertransport devices | ||
87 | * that generate irqs. | ||
88 | * | 90 | * |
89 | * The irq number of the new irq or a negative error value is returned. | 91 | * The irq number of the new irq or a negative error value is returned. |
90 | */ | 92 | */ |
91 | int ht_create_irq(struct pci_dev *dev, int idx) | 93 | int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) |
92 | { | 94 | { |
93 | struct ht_irq_cfg *cfg; | 95 | struct ht_irq_cfg *cfg; |
94 | unsigned long flags; | 96 | unsigned long flags; |
@@ -123,6 +125,7 @@ int ht_create_irq(struct pci_dev *dev, int idx) | |||
123 | return -ENOMEM; | 125 | return -ENOMEM; |
124 | 126 | ||
125 | cfg->dev = dev; | 127 | cfg->dev = dev; |
128 | cfg->update = update; | ||
126 | cfg->pos = pos; | 129 | cfg->pos = pos; |
127 | cfg->idx = 0x10 + (idx * 2); | 130 | cfg->idx = 0x10 + (idx * 2); |
128 | /* Initialize msg to a value that will never match the first write. */ | 131 | /* Initialize msg to a value that will never match the first write. */ |
@@ -145,6 +148,21 @@ int ht_create_irq(struct pci_dev *dev, int idx) | |||
145 | } | 148 | } |
146 | 149 | ||
147 | /** | 150 | /** |
151 | * ht_create_irq - create an irq and attach it to a device. | ||
152 | * @dev: The hypertransport device to find the irq capability on. | ||
153 | * @idx: Which of the possible irqs to attach to. | ||
154 | * | ||
155 | * ht_create_irq needs to be called for all hypertransport devices | ||
156 | * that generate irqs. | ||
157 | * | ||
158 | * The irq number of the new irq or a negative error value is returned. | ||
159 | */ | ||
160 | int ht_create_irq(struct pci_dev *dev, int idx) | ||
161 | { | ||
162 | return __ht_create_irq(dev, idx, NULL); | ||
163 | } | ||
164 | |||
165 | /** | ||
148 | * ht_destroy_irq - destroy an irq created with ht_create_irq | 166 | * ht_destroy_irq - destroy an irq created with ht_create_irq |
149 | * | 167 | * |
150 | * This reverses ht_create_irq removing the specified irq from | 168 | * This reverses ht_create_irq removing the specified irq from |
@@ -162,5 +180,6 @@ void ht_destroy_irq(unsigned int irq) | |||
162 | kfree(cfg); | 180 | kfree(cfg); |
163 | } | 181 | } |
164 | 182 | ||
183 | EXPORT_SYMBOL(__ht_create_irq); | ||
165 | EXPORT_SYMBOL(ht_create_irq); | 184 | EXPORT_SYMBOL(ht_create_irq); |
166 | EXPORT_SYMBOL(ht_destroy_irq); | 185 | EXPORT_SYMBOL(ht_destroy_irq); |
diff --git a/include/linux/htirq.h b/include/linux/htirq.h index 108f0d91e11e..c96ea46737d0 100644 --- a/include/linux/htirq.h +++ b/include/linux/htirq.h | |||
@@ -15,4 +15,9 @@ void unmask_ht_irq(unsigned int irq); | |||
15 | /* The arch hook for getting things started */ | 15 | /* The arch hook for getting things started */ |
16 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev); | 16 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev); |
17 | 17 | ||
18 | /* For drivers of buggy hardware */ | ||
19 | typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq, | ||
20 | struct ht_irq_msg *msg); | ||
21 | int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update); | ||
22 | |||
18 | #endif /* LINUX_HTIRQ_H */ | 23 | #endif /* LINUX_HTIRQ_H */ |