mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 01:54:00 +00:00
[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>
This commit is contained in:
parent
ec68307cc5
commit
43539c38cd
@ -25,6 +25,8 @@ static DEFINE_SPINLOCK(ht_irq_lock);
|
|||||||
|
|
||||||
struct ht_irq_cfg {
|
struct ht_irq_cfg {
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
|
/* Update callback used to cope with buggy hardware */
|
||||||
|
ht_irq_update_t *update;
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
struct ht_irq_msg msg;
|
struct ht_irq_msg msg;
|
||||||
@ -44,6 +46,8 @@ void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
|
|||||||
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1);
|
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1);
|
||||||
pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi);
|
pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi);
|
||||||
}
|
}
|
||||||
|
if (cfg->update)
|
||||||
|
cfg->update(cfg->dev, irq, msg);
|
||||||
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
||||||
cfg->msg = *msg;
|
cfg->msg = *msg;
|
||||||
}
|
}
|
||||||
@ -79,16 +83,14 @@ void unmask_ht_irq(unsigned int irq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ht_create_irq - create an irq and attach it to a device.
|
* __ht_create_irq - create an irq and attach it to a device.
|
||||||
* @dev: The hypertransport device to find the irq capability on.
|
* @dev: The hypertransport device to find the irq capability on.
|
||||||
* @idx: Which of the possible irqs to attach to.
|
* @idx: Which of the possible irqs to attach to.
|
||||||
*
|
* @update: Function to be called when changing the htirq message
|
||||||
* ht_create_irq is needs to be called for all hypertransport devices
|
|
||||||
* that generate irqs.
|
|
||||||
*
|
*
|
||||||
* The irq number of the new irq or a negative error value is returned.
|
* The irq number of the new irq or a negative error value is returned.
|
||||||
*/
|
*/
|
||||||
int ht_create_irq(struct pci_dev *dev, int idx)
|
int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
|
||||||
{
|
{
|
||||||
struct ht_irq_cfg *cfg;
|
struct ht_irq_cfg *cfg;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -123,6 +125,7 @@ int ht_create_irq(struct pci_dev *dev, int idx)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
cfg->dev = dev;
|
cfg->dev = dev;
|
||||||
|
cfg->update = update;
|
||||||
cfg->pos = pos;
|
cfg->pos = pos;
|
||||||
cfg->idx = 0x10 + (idx * 2);
|
cfg->idx = 0x10 + (idx * 2);
|
||||||
/* Initialize msg to a value that will never match the first write. */
|
/* Initialize msg to a value that will never match the first write. */
|
||||||
@ -144,6 +147,21 @@ int ht_create_irq(struct pci_dev *dev, int idx)
|
|||||||
return irq;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ht_create_irq - create an irq and attach it to a device.
|
||||||
|
* @dev: The hypertransport device to find the irq capability on.
|
||||||
|
* @idx: Which of the possible irqs to attach to.
|
||||||
|
*
|
||||||
|
* ht_create_irq needs to be called for all hypertransport devices
|
||||||
|
* that generate irqs.
|
||||||
|
*
|
||||||
|
* The irq number of the new irq or a negative error value is returned.
|
||||||
|
*/
|
||||||
|
int ht_create_irq(struct pci_dev *dev, int idx)
|
||||||
|
{
|
||||||
|
return __ht_create_irq(dev, idx, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ht_destroy_irq - destroy an irq created with ht_create_irq
|
* ht_destroy_irq - destroy an irq created with ht_create_irq
|
||||||
*
|
*
|
||||||
@ -162,5 +180,6 @@ void ht_destroy_irq(unsigned int irq)
|
|||||||
kfree(cfg);
|
kfree(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(__ht_create_irq);
|
||||||
EXPORT_SYMBOL(ht_create_irq);
|
EXPORT_SYMBOL(ht_create_irq);
|
||||||
EXPORT_SYMBOL(ht_destroy_irq);
|
EXPORT_SYMBOL(ht_destroy_irq);
|
||||||
|
@ -15,4 +15,9 @@ void unmask_ht_irq(unsigned int irq);
|
|||||||
/* The arch hook for getting things started */
|
/* The arch hook for getting things started */
|
||||||
int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
|
int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
|
||||||
|
|
||||||
|
/* For drivers of buggy hardware */
|
||||||
|
typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq,
|
||||||
|
struct ht_irq_msg *msg);
|
||||||
|
int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update);
|
||||||
|
|
||||||
#endif /* LINUX_HTIRQ_H */
|
#endif /* LINUX_HTIRQ_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user