[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>

authored by Eric W. Biederman and committed by Linus Torvalds 43539c38 ec68307c

+29 -5
+24 -5
drivers/pci/htirq.c
··· 25 26 struct ht_irq_cfg { 27 struct pci_dev *dev; 28 unsigned pos; 29 unsigned idx; 30 struct ht_irq_msg msg; ··· 46 pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); 47 pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); 48 } 49 spin_unlock_irqrestore(&ht_irq_lock, flags); 50 cfg->msg = *msg; 51 } ··· 83 } 84 85 /** 86 - * ht_create_irq - create an irq and attach it to a device. 87 * @dev: The hypertransport device to find the irq capability on. 88 * @idx: Which of the possible irqs to attach to. 89 - * 90 - * ht_create_irq is needs to be called for all hypertransport devices 91 - * that generate irqs. 92 * 93 * The irq number of the new irq or a negative error value is returned. 94 */ 95 - int ht_create_irq(struct pci_dev *dev, int idx) 96 { 97 struct ht_irq_cfg *cfg; 98 unsigned long flags; ··· 125 return -ENOMEM; 126 127 cfg->dev = dev; 128 cfg->pos = pos; 129 cfg->idx = 0x10 + (idx * 2); 130 /* Initialize msg to a value that will never match the first write. */ ··· 148 } 149 150 /** 151 * ht_destroy_irq - destroy an irq created with ht_create_irq 152 * 153 * This reverses ht_create_irq removing the specified irq from ··· 180 kfree(cfg); 181 } 182 183 EXPORT_SYMBOL(ht_create_irq); 184 EXPORT_SYMBOL(ht_destroy_irq);
··· 25 26 struct ht_irq_cfg { 27 struct pci_dev *dev; 28 + /* Update callback used to cope with buggy hardware */ 29 + ht_irq_update_t *update; 30 unsigned pos; 31 unsigned idx; 32 struct ht_irq_msg msg; ··· 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 } 47 + if (cfg->update) 48 + cfg->update(cfg->dev, irq, msg); 49 spin_unlock_irqrestore(&ht_irq_lock, flags); 50 cfg->msg = *msg; 51 } ··· 79 } 80 81 /** 82 + * __ht_create_irq - create an irq and attach it to a device. 83 * @dev: The hypertransport device to find the irq capability on. 84 * @idx: Which of the possible irqs to attach to. 85 + * @update: Function to be called when changing the htirq message 86 * 87 * The irq number of the new irq or a negative error value is returned. 88 */ 89 + int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) 90 { 91 struct ht_irq_cfg *cfg; 92 unsigned long flags; ··· 123 return -ENOMEM; 124 125 cfg->dev = dev; 126 + cfg->update = update; 127 cfg->pos = pos; 128 cfg->idx = 0x10 + (idx * 2); 129 /* Initialize msg to a value that will never match the first write. */ ··· 145 } 146 147 /** 148 + * ht_create_irq - create an irq and attach it to a device. 149 + * @dev: The hypertransport device to find the irq capability on. 150 + * @idx: Which of the possible irqs to attach to. 151 + * 152 + * ht_create_irq needs to be called for all hypertransport devices 153 + * that generate irqs. 154 + * 155 + * The irq number of the new irq or a negative error value is returned. 156 + */ 157 + int ht_create_irq(struct pci_dev *dev, int idx) 158 + { 159 + return __ht_create_irq(dev, idx, NULL); 160 + } 161 + 162 + /** 163 * ht_destroy_irq - destroy an irq created with ht_create_irq 164 * 165 * This reverses ht_create_irq removing the specified irq from ··· 162 kfree(cfg); 163 } 164 165 + EXPORT_SYMBOL(__ht_create_irq); 166 EXPORT_SYMBOL(ht_create_irq); 167 EXPORT_SYMBOL(ht_destroy_irq);
+5
include/linux/htirq.h
··· 15 /* The arch hook for getting things started */ 16 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev); 17 18 #endif /* LINUX_HTIRQ_H */
··· 15 /* The arch hook for getting things started */ 16 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev); 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 + 23 #endif /* LINUX_HTIRQ_H */