[PATCH] htirq: refactor so we only have one function that writes to the chip
This refactoring actually optimizes the code a little by caching the value that we think the device is programmed with instead of reading it back from the hardware. Which simplifies the code a little and should speed things up a bit. This patch introduces the concept of a ht_irq_msg and modifies the architecture read/write routines to update this code. There is a minor consistency fix here as well as x86_64 forgot to initialize the htirq as masked. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Andi Kleen <ak@suse.de> Acked-by: Bryan O'Sullivan <bos@pathscale.com> Cc: <olson@pathscale.com> Cc: Roland Dreier <rolandd@cisco.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
64d9fe6973
commit
ec68307cc5
|
@ -2624,18 +2624,16 @@ void arch_teardown_msi_irq(unsigned int irq)
|
||||||
|
|
||||||
static void target_ht_irq(unsigned int irq, unsigned int dest)
|
static void target_ht_irq(unsigned int irq, unsigned int dest)
|
||||||
{
|
{
|
||||||
u32 low, high;
|
struct ht_irq_msg msg;
|
||||||
low = read_ht_irq_low(irq);
|
fetch_ht_irq_msg(irq, &msg);
|
||||||
high = read_ht_irq_high(irq);
|
|
||||||
|
|
||||||
low &= ~(HT_IRQ_LOW_DEST_ID_MASK);
|
msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK);
|
||||||
high &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
|
msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
|
||||||
|
|
||||||
low |= HT_IRQ_LOW_DEST_ID(dest);
|
msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest);
|
||||||
high |= HT_IRQ_HIGH_DEST_ID(dest);
|
msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
|
||||||
|
|
||||||
write_ht_irq_low(irq, low);
|
write_ht_irq_msg(irq, &msg);
|
||||||
write_ht_irq_high(irq, high);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
|
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)
|
||||||
|
|
||||||
vector = assign_irq_vector(irq);
|
vector = assign_irq_vector(irq);
|
||||||
if (vector >= 0) {
|
if (vector >= 0) {
|
||||||
u32 low, high;
|
struct ht_irq_msg msg;
|
||||||
unsigned dest;
|
unsigned dest;
|
||||||
cpumask_t tmp;
|
cpumask_t tmp;
|
||||||
|
|
||||||
|
@ -2681,9 +2679,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
|
||||||
cpu_set(vector >> 8, tmp);
|
cpu_set(vector >> 8, tmp);
|
||||||
dest = cpu_mask_to_apicid(tmp);
|
dest = cpu_mask_to_apicid(tmp);
|
||||||
|
|
||||||
high = HT_IRQ_HIGH_DEST_ID(dest);
|
msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
|
||||||
|
|
||||||
low = HT_IRQ_LOW_BASE |
|
msg.address_lo =
|
||||||
|
HT_IRQ_LOW_BASE |
|
||||||
HT_IRQ_LOW_DEST_ID(dest) |
|
HT_IRQ_LOW_DEST_ID(dest) |
|
||||||
HT_IRQ_LOW_VECTOR(vector) |
|
HT_IRQ_LOW_VECTOR(vector) |
|
||||||
((INT_DEST_MODE == 0) ?
|
((INT_DEST_MODE == 0) ?
|
||||||
|
@ -2695,8 +2694,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
|
||||||
HT_IRQ_LOW_MT_ARBITRATED) |
|
HT_IRQ_LOW_MT_ARBITRATED) |
|
||||||
HT_IRQ_LOW_IRQ_MASKED;
|
HT_IRQ_LOW_IRQ_MASKED;
|
||||||
|
|
||||||
write_ht_irq_low(irq, low);
|
write_ht_irq_msg(irq, &msg);
|
||||||
write_ht_irq_high(irq, high);
|
|
||||||
|
|
||||||
set_irq_chip_and_handler_name(irq, &ht_irq_chip,
|
set_irq_chip_and_handler_name(irq, &ht_irq_chip,
|
||||||
handle_edge_irq, "edge");
|
handle_edge_irq, "edge");
|
||||||
|
|
|
@ -1955,18 +1955,16 @@ void arch_teardown_msi_irq(unsigned int irq)
|
||||||
|
|
||||||
static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
|
static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
|
||||||
{
|
{
|
||||||
u32 low, high;
|
struct ht_irq_msg msg;
|
||||||
low = read_ht_irq_low(irq);
|
fetch_ht_irq_msg(irq, &msg);
|
||||||
high = read_ht_irq_high(irq);
|
|
||||||
|
|
||||||
low &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
|
msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
|
||||||
high &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
|
msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
|
||||||
|
|
||||||
low |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
|
msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
|
||||||
high |= HT_IRQ_HIGH_DEST_ID(dest);
|
msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
|
||||||
|
|
||||||
write_ht_irq_low(irq, low);
|
write_ht_irq_msg(irq, &msg);
|
||||||
write_ht_irq_high(irq, high);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
|
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)
|
||||||
|
|
||||||
dest = cpu_mask_to_apicid(tmp);
|
dest = cpu_mask_to_apicid(tmp);
|
||||||
|
|
||||||
target_ht_irq(irq, dest, vector & 0xff);
|
target_ht_irq(irq, dest, vector);
|
||||||
set_native_irq_info(irq, mask);
|
set_native_irq_info(irq, mask);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2010,14 +2008,15 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
|
||||||
|
|
||||||
vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
|
vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
|
||||||
if (vector >= 0) {
|
if (vector >= 0) {
|
||||||
u32 low, high;
|
struct ht_irq_msg msg;
|
||||||
unsigned dest;
|
unsigned dest;
|
||||||
|
|
||||||
dest = cpu_mask_to_apicid(tmp);
|
dest = cpu_mask_to_apicid(tmp);
|
||||||
|
|
||||||
high = HT_IRQ_HIGH_DEST_ID(dest);
|
msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
|
||||||
|
|
||||||
low = HT_IRQ_LOW_BASE |
|
msg.address_lo =
|
||||||
|
HT_IRQ_LOW_BASE |
|
||||||
HT_IRQ_LOW_DEST_ID(dest) |
|
HT_IRQ_LOW_DEST_ID(dest) |
|
||||||
HT_IRQ_LOW_VECTOR(vector) |
|
HT_IRQ_LOW_VECTOR(vector) |
|
||||||
((INT_DEST_MODE == 0) ?
|
((INT_DEST_MODE == 0) ?
|
||||||
|
@ -2026,10 +2025,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
|
||||||
HT_IRQ_LOW_RQEOI_EDGE |
|
HT_IRQ_LOW_RQEOI_EDGE |
|
||||||
((INT_DELIVERY_MODE != dest_LowestPrio) ?
|
((INT_DELIVERY_MODE != dest_LowestPrio) ?
|
||||||
HT_IRQ_LOW_MT_FIXED :
|
HT_IRQ_LOW_MT_FIXED :
|
||||||
HT_IRQ_LOW_MT_ARBITRATED);
|
HT_IRQ_LOW_MT_ARBITRATED) |
|
||||||
|
HT_IRQ_LOW_IRQ_MASKED;
|
||||||
|
|
||||||
write_ht_irq_low(irq, low);
|
write_ht_irq_msg(irq, &msg);
|
||||||
write_ht_irq_high(irq, high);
|
|
||||||
|
|
||||||
set_irq_chip_and_handler_name(irq, &ht_irq_chip,
|
set_irq_chip_and_handler_name(irq, &ht_irq_chip,
|
||||||
handle_edge_irq, "edge");
|
handle_edge_irq, "edge");
|
||||||
|
|
|
@ -27,82 +27,55 @@ struct ht_irq_cfg {
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
|
struct ht_irq_msg msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
void write_ht_irq_low(unsigned int irq, u32 data)
|
|
||||||
|
void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
|
||||||
{
|
{
|
||||||
struct ht_irq_cfg *cfg = get_irq_data(irq);
|
struct ht_irq_cfg *cfg = get_irq_data(irq);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
spin_lock_irqsave(&ht_irq_lock, flags);
|
spin_lock_irqsave(&ht_irq_lock, flags);
|
||||||
|
if (cfg->msg.address_lo != msg->address_lo) {
|
||||||
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
|
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
|
||||||
pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
|
pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo);
|
||||||
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
|
||||||
}
|
}
|
||||||
|
if (cfg->msg.address_hi != msg->address_hi) {
|
||||||
void write_ht_irq_high(unsigned int irq, u32 data)
|
|
||||||
{
|
|
||||||
struct ht_irq_cfg *cfg = get_irq_data(irq);
|
|
||||||
unsigned long flags;
|
|
||||||
spin_lock_irqsave(&ht_irq_lock, flags);
|
|
||||||
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, data);
|
pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi);
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
||||||
|
cfg->msg = *msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 read_ht_irq_low(unsigned int irq)
|
void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
|
||||||
{
|
{
|
||||||
struct ht_irq_cfg *cfg = get_irq_data(irq);
|
struct ht_irq_cfg *cfg = get_irq_data(irq);
|
||||||
unsigned long flags;
|
*msg = cfg->msg;
|
||||||
u32 data;
|
|
||||||
spin_lock_irqsave(&ht_irq_lock, flags);
|
|
||||||
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
|
|
||||||
pci_read_config_dword(cfg->dev, cfg->pos + 4, &data);
|
|
||||||
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 read_ht_irq_high(unsigned int irq)
|
|
||||||
{
|
|
||||||
struct ht_irq_cfg *cfg = get_irq_data(irq);
|
|
||||||
unsigned long flags;
|
|
||||||
u32 data;
|
|
||||||
spin_lock_irqsave(&ht_irq_lock, flags);
|
|
||||||
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1);
|
|
||||||
pci_read_config_dword(cfg->dev, cfg->pos + 4, &data);
|
|
||||||
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mask_ht_irq(unsigned int irq)
|
void mask_ht_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct ht_irq_cfg *cfg;
|
struct ht_irq_cfg *cfg;
|
||||||
unsigned long flags;
|
struct ht_irq_msg msg;
|
||||||
u32 data;
|
|
||||||
|
|
||||||
cfg = get_irq_data(irq);
|
cfg = get_irq_data(irq);
|
||||||
|
|
||||||
spin_lock_irqsave(&ht_irq_lock, flags);
|
msg = cfg->msg;
|
||||||
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
|
msg.address_lo |= 1;
|
||||||
pci_read_config_dword(cfg->dev, cfg->pos + 4, &data);
|
write_ht_irq_msg(irq, &msg);
|
||||||
data |= 1;
|
|
||||||
pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
|
|
||||||
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmask_ht_irq(unsigned int irq)
|
void unmask_ht_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct ht_irq_cfg *cfg;
|
struct ht_irq_cfg *cfg;
|
||||||
unsigned long flags;
|
struct ht_irq_msg msg;
|
||||||
u32 data;
|
|
||||||
|
|
||||||
cfg = get_irq_data(irq);
|
cfg = get_irq_data(irq);
|
||||||
|
|
||||||
spin_lock_irqsave(&ht_irq_lock, flags);
|
msg = cfg->msg;
|
||||||
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
|
msg.address_lo &= ~1;
|
||||||
pci_read_config_dword(cfg->dev, cfg->pos + 4, &data);
|
write_ht_irq_msg(irq, &msg);
|
||||||
data &= ~1;
|
|
||||||
pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
|
|
||||||
spin_unlock_irqrestore(&ht_irq_lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -152,6 +125,9 @@ int ht_create_irq(struct pci_dev *dev, int idx)
|
||||||
cfg->dev = dev;
|
cfg->dev = dev;
|
||||||
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. */
|
||||||
|
cfg->msg.address_lo = 0xffffffff;
|
||||||
|
cfg->msg.address_hi = 0xffffffff;
|
||||||
|
|
||||||
irq = create_irq();
|
irq = create_irq();
|
||||||
if (irq < 0) {
|
if (irq < 0) {
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#ifndef LINUX_HTIRQ_H
|
#ifndef LINUX_HTIRQ_H
|
||||||
#define LINUX_HTIRQ_H
|
#define LINUX_HTIRQ_H
|
||||||
|
|
||||||
|
struct ht_irq_msg {
|
||||||
|
u32 address_lo; /* low 32 bits of the ht irq message */
|
||||||
|
u32 address_hi; /* high 32 bits of the it irq message */
|
||||||
|
};
|
||||||
|
|
||||||
/* Helper functions.. */
|
/* Helper functions.. */
|
||||||
void write_ht_irq_low(unsigned int irq, u32 data);
|
void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
|
||||||
void write_ht_irq_high(unsigned int irq, u32 data);
|
void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
|
||||||
u32 read_ht_irq_low(unsigned int irq);
|
|
||||||
u32 read_ht_irq_high(unsigned int irq);
|
|
||||||
void mask_ht_irq(unsigned int irq);
|
void mask_ht_irq(unsigned int irq);
|
||||||
void unmask_ht_irq(unsigned int irq);
|
void unmask_ht_irq(unsigned int irq);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue