Commit ec68307c authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds

[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: default avatarEric W. Biederman <ebiederm@xmission.com>
Cc: Andi Kleen <ak@suse.de>
Acked-by: default avatarBryan O'Sullivan <bos@pathscale.com>
Cc: <olson@pathscale.com>
Cc: Roland Dreier <rolandd@cisco.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 64d9fe69
...@@ -2624,18 +2624,16 @@ void arch_teardown_msi_irq(unsigned int irq) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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)
{
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);
pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
spin_unlock_irqrestore(&ht_irq_lock, flags);
}
void write_ht_irq_high(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);
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); if (cfg->msg.address_lo != msg->address_lo) {
pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
spin_unlock_irqrestore(&ht_irq_lock, flags);
}
u32 read_ht_irq_low(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); pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx);
pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo);
}
if (cfg->msg.address_hi != msg->address_hi) {
pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1);
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);
return data; cfg->msg = *msg;
} }
u32 read_ht_irq_high(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 + 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) ...@@ -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) {
......
#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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment