Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+12 −14
Original line number Diff line number Diff line
@@ -2624,18 +2624,16 @@ void arch_teardown_msi_irq(unsigned int irq)

static void target_ht_irq(unsigned int irq, unsigned int dest)
{
	u32 low, high;
	low  = read_ht_irq_low(irq);
	high = read_ht_irq_high(irq);
	struct ht_irq_msg msg;
	fetch_ht_irq_msg(irq, &msg);

	low  &= ~(HT_IRQ_LOW_DEST_ID_MASK);
	high &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
	msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK);
	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);

	low  |= HT_IRQ_LOW_DEST_ID(dest);
	high |= HT_IRQ_HIGH_DEST_ID(dest);
	msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest);
	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);

	write_ht_irq_low(irq, low);
	write_ht_irq_high(irq, high);
	write_ht_irq_msg(irq, &msg);
}

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);
	if (vector >= 0) {
		u32 low, high;
		struct ht_irq_msg msg;
		unsigned dest;
		cpumask_t tmp;

@@ -2681,9 +2679,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
		cpu_set(vector >> 8, 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_VECTOR(vector) |
			((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_IRQ_MASKED;

		write_ht_irq_low(irq, low);
		write_ht_irq_high(irq, high);
		write_ht_irq_msg(irq, &msg);

		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
					      handle_edge_irq, "edge");
+15 −16
Original line number Diff line number Diff line
@@ -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)
{
	u32 low, high;
	low  = read_ht_irq_low(irq);
	high = read_ht_irq_high(irq);
	struct ht_irq_msg msg;
	fetch_ht_irq_msg(irq, &msg);

	low  &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
	high &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);

	low  |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
	high |= HT_IRQ_HIGH_DEST_ID(dest);
	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);

	write_ht_irq_low(irq, low);
	write_ht_irq_high(irq, high);
	write_ht_irq_msg(irq, &msg);
}

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);

	target_ht_irq(irq, dest, vector & 0xff);
	target_ht_irq(irq, dest, vector);
	set_native_irq_info(irq, mask);
}
#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);
	if (vector >= 0) {
		u32 low, high;
		struct ht_irq_msg msg;
		unsigned dest;

		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_VECTOR(vector) |
			((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 |
			((INT_DELIVERY_MODE != dest_LowestPrio) ?
				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_high(irq, high);
		write_ht_irq_msg(irq, &msg);

		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
					      handle_edge_irq, "edge");
+24 −48
Original line number Diff line number Diff line
@@ -27,82 +27,55 @@ struct ht_irq_cfg {
	struct pci_dev *dev;
	unsigned pos;
	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);
	unsigned long 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_dword(cfg->dev, cfg->pos + 4, data);
	spin_unlock_irqrestore(&ht_irq_lock, flags);
		pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo);
	}

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);
	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, data);
	spin_unlock_irqrestore(&ht_irq_lock, flags);
		pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi);
	}

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_read_config_dword(cfg->dev, cfg->pos + 4, &data);
	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);
	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;
	*msg = cfg->msg;
}

void mask_ht_irq(unsigned int irq)
{
	struct ht_irq_cfg *cfg;
	unsigned long flags;
	u32 data;
	struct ht_irq_msg msg;

	cfg = get_irq_data(irq);

	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);
	data |= 1;
	pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
	spin_unlock_irqrestore(&ht_irq_lock, flags);
	msg = cfg->msg;
	msg.address_lo |= 1;
	write_ht_irq_msg(irq, &msg);
}

void unmask_ht_irq(unsigned int irq)
{
	struct ht_irq_cfg *cfg;
	unsigned long flags;
	u32 data;
	struct ht_irq_msg msg;

	cfg = get_irq_data(irq);

	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);
	data &= ~1;
	pci_write_config_dword(cfg->dev, cfg->pos + 4, data);
	spin_unlock_irqrestore(&ht_irq_lock, flags);
	msg = cfg->msg;
	msg.address_lo &= ~1;
	write_ht_irq_msg(irq, &msg);
}

/**
@@ -152,6 +125,9 @@ int ht_create_irq(struct pci_dev *dev, int idx)
	cfg->dev = dev;
	cfg->pos = pos;
	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();
	if (irq < 0) {
+7 −4
Original line number Diff line number Diff line
#ifndef 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.. */
void write_ht_irq_low(unsigned int irq, u32 data);
void write_ht_irq_high(unsigned int irq, u32 data);
u32  read_ht_irq_low(unsigned int irq);
u32  read_ht_irq_high(unsigned int irq);
void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
void mask_ht_irq(unsigned int irq);
void unmask_ht_irq(unsigned int irq);