aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-11-08 20:44:57 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-11-08 21:29:25 -0500
commit43539c38cd8edb915d1f0e1f55dcb70638b4cc8e (patch)
tree623568ee8f87684be487145fbc7a5da16320afde
parentec68307cc5a8dc499e48693843bb42f6b6028458 (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.c29
-rw-r--r--include/linux/htirq.h5
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
26struct ht_irq_cfg { 26struct 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 */
91int ht_create_irq(struct pci_dev *dev, int idx) 93int __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 */
160int 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
183EXPORT_SYMBOL(__ht_create_irq);
165EXPORT_SYMBOL(ht_create_irq); 184EXPORT_SYMBOL(ht_create_irq);
166EXPORT_SYMBOL(ht_destroy_irq); 185EXPORT_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 */
16int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev); 16int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
17 17
18/* For drivers of buggy hardware */
19typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq,
20 struct ht_irq_msg *msg);
21int __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 */