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

Commit 37cdcd9e authored by David S. Miller's avatar David S. Miller
Browse files

[SPARC64]: Kill ino_bucket->pil



And reuse that struct member for virt_irq, which will
be used in future changesets for the implementation of
mapping between real and virtual IRQ numbers.

This nicely kills off a ton of SBUS and PCI controller
PIL assignment code which is no longer necessary.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c6387a48
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
		return 0;
	}

	return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0);
	return sun4v_build_irq(sun4v_vdev_devhandle, irq, 0);
}

static const char *cpu_mid_prop(void)
+26 −44
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY
 */
#define irq_work(__cpu)	&(trap_block[(__cpu)].irq_worklist)

static struct irqaction *irq_action[NR_IRQS+1];
static struct irqaction *irq_action[NR_IRQS];

/* This only synchronizes entities which modify IRQ handler
 * state and some selected user-level spots that want to
@@ -116,12 +116,9 @@ int show_interrupts(struct seq_file *p, void *v)
				   kstat_cpu(j).irqs[i]);
		}
#endif
		seq_printf(p, " %s:%lx", action->name,
			   get_ino_in_irqaction(action));
		for (action = action->next; action; action = action->next) {
			seq_printf(p, ", %s:%lx", action->name,
				   get_ino_in_irqaction(action));
		}
		seq_printf(p, " %s", action->name);
		for (action = action->next; action; action = action->next)
			seq_printf(p, ", %s", action->name);
		seq_putc(p, '\n');
	}
out_unlock:
@@ -245,48 +242,47 @@ void disable_irq(unsigned int irq)
	}
}

static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup,
static void build_irq_error(const char *msg, unsigned int ino, int inofixup,
			    unsigned long iclr, unsigned long imap,
			    struct ino_bucket *bucket)
{
	prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> "
		    "(%d:%d:%016lx:%016lx), halting...\n",
		    ino, bucket->pil, bucket->iclr, bucket->imap,
		    pil, inofixup, iclr, imap);
	prom_printf("IRQ: INO %04x (%016lx:%016lx) --> "
		    "(%d:%016lx:%016lx), halting...\n",
		    ino, bucket->iclr, bucket->imap,
		    inofixup, iclr, imap);
	prom_halt();
}

unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap)
unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
{
	struct ino_bucket *bucket;
	int ino;

	BUG_ON(pil == 0);
	BUG_ON(tlb_type == hypervisor);

	/* RULE: Both must be specified in all other cases. */
	if (iclr == 0UL || imap == 0UL) {
		prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
			    pil, inofixup, iclr, imap);
		prom_printf("Invalid build_irq %d %016lx %016lx\n",
			    inofixup, iclr, imap);
		prom_halt();
	}
	
	ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
	if (ino > NUM_IVECS) {
		prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
			    ino, pil, inofixup, iclr, imap);
		prom_printf("Invalid INO %04x (%d:%016lx:%016lx)\n",
			    ino, inofixup, iclr, imap);
		prom_halt();
	}

	bucket = &ivector_table[ino];
	if (bucket->flags & IBF_ACTIVE)
		build_irq_error("IRQ: Trying to build active INO bucket.\n",
				ino, pil, inofixup, iclr, imap, bucket);
				ino, inofixup, iclr, imap, bucket);

	if (bucket->irq_info) {
		if (bucket->imap != imap || bucket->iclr != iclr)
			build_irq_error("IRQ: Trying to reinit INO bucket.\n",
					ino, pil, inofixup, iclr, imap, bucket);
					ino, inofixup, iclr, imap, bucket);

		goto out;
	}
@@ -302,14 +298,13 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long
	 */
	bucket->imap  = imap;
	bucket->iclr  = iclr;
	bucket->pil   = pil;
	bucket->flags = 0;

out:
	return __irq(bucket);
}

unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags)
unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags)
{
	struct ino_bucket *bucket;
	unsigned long sysino;
@@ -328,7 +323,6 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsign
	bucket->imap = ~0UL - sysino;
	bucket->iclr = ~0UL - sysino;

	bucket->pil = pil;
	bucket->flags = flags;

	bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC);
@@ -356,17 +350,13 @@ static void atomic_bucket_insert(struct ino_bucket *bucket)

static int check_irq_sharing(int pil, unsigned long irqflags)
{
	struct irqaction *action, *tmp;
	struct irqaction *action;

	action = *(irq_action + pil);
	if (action) {
		if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
			for (tmp = action; tmp->next; tmp = tmp->next)
				;
		} else {
		if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ))
			return -EBUSY;
	}
	}
	return 0;
}

@@ -425,12 +415,12 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_
	 	 * installing a new handler, but is this really a problem,
	 	 * only the sysadmin is able to do this.
	 	 */
		rand_initialize_irq(irq);
		rand_initialize_irq(PIL_DEVICE_IRQ);
	}

	spin_lock_irqsave(&irq_action_lock, flags);

	if (check_irq_sharing(bucket->pil, irqflags)) {
	if (check_irq_sharing(PIL_DEVICE_IRQ, irqflags)) {
		spin_unlock_irqrestore(&irq_action_lock, flags);
		return -EBUSY;
	}
@@ -454,7 +444,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_
	put_ino_in_irqaction(action, irq);
	put_smpaff_in_irqaction(action, CPU_MASK_NONE);

	append_irq_action(bucket->pil, action);
	append_irq_action(PIL_DEVICE_IRQ, action);

	enable_irq(irq);

@@ -478,16 +468,15 @@ EXPORT_SYMBOL(request_irq);

static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id)
{
	struct ino_bucket *bucket = __bucket(irq);
	struct irqaction *action, **pp;

	pp = irq_action + bucket->pil;
	pp = irq_action + PIL_DEVICE_IRQ;
	action = *pp;
	if (unlikely(!action))
		return NULL;

	if (unlikely(!action->handler)) {
		printk("Freeing free IRQ %d\n", bucket->pil);
		printk("Freeing free IRQ %d\n", PIL_DEVICE_IRQ);
		return NULL;
	}

@@ -648,7 +637,7 @@ static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs)

	/* Test and add entropy */
	if (random & SA_SAMPLE_RANDOM)
		add_interrupt_randomness(bp->pil);
		add_interrupt_randomness(PIL_DEVICE_IRQ);
out:
	bp->flags &= ~IBF_INPROGRESS;
}
@@ -691,7 +680,7 @@ void handler_irq(int irq, struct pt_regs *regs)
	while (bp) {
		struct ino_bucket *nbp = __bucket(bp->irq_chain);

		kstat_this_cpu.irqs[bp->pil]++;
		kstat_this_cpu.irqs[bp->virt_irq]++;

		bp->irq_chain = 0;
		process_bucket(bp, regs);
@@ -817,16 +806,9 @@ static void distribute_irqs(void)
	spin_lock_irqsave(&irq_action_lock, flags);
	cpu = 0;

	/*
	 * Skip the timer at [0], and very rare error/power intrs at [15].
	 * Also level [12], it causes problems on Ex000 systems.
	 */
	for (level = 1; level < NR_IRQS; level++) {
		struct irqaction *p = irq_action[level];

		if (level == 12)
			continue;

		while(p) {
			cpu = retarget_one_irq(p, cpu);
			p = p->next;
+2 −75
Original line number Diff line number Diff line
@@ -276,74 +276,6 @@ static unsigned long __onboard_imap_off[] = {
	((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
			(PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))

/* PCI PSYCHO INO number to Sparc PIL level. */
static unsigned char psycho_pil_table[] = {
/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D */
/*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D */
/*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D */
/*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D */
/*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D */
/*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D */
/*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D */
/*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D */
/*0x20*/5,		/* SCSI				*/
/*0x21*/5,		/* Ethernet			*/
/*0x22*/8,		/* Parallel Port		*/
/*0x23*/13,		/* Audio Record			*/
/*0x24*/14,		/* Audio Playback		*/
/*0x25*/15,		/* PowerFail			*/
/*0x26*/5,		/* second SCSI			*/
/*0x27*/11,		/* Floppy			*/
/*0x28*/5,		/* Spare Hardware		*/
/*0x29*/9,		/* Keyboard			*/
/*0x2a*/5,		/* Mouse			*/
/*0x2b*/12,		/* Serial			*/
/*0x2c*/10,		/* Timer 0			*/
/*0x2d*/11,		/* Timer 1			*/
/*0x2e*/15,		/* Uncorrectable ECC		*/
/*0x2f*/15,		/* Correctable ECC		*/
/*0x30*/15,		/* PCI Bus A Error		*/
/*0x31*/15,		/* PCI Bus B Error		*/
/*0x32*/15,		/* Power Management		*/
};

static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
{
	int ret;

	ret = psycho_pil_table[ino];
	if (ret == 0 && pdev == NULL) {
		ret = 5;
	} else if (ret == 0) {
		switch ((pdev->class >> 16) & 0xff) {
		case PCI_BASE_CLASS_STORAGE:
			ret = 5;
			break;

		case PCI_BASE_CLASS_NETWORK:
			ret = 6;
			break;

		case PCI_BASE_CLASS_DISPLAY:
			ret = 9;
			break;

		case PCI_BASE_CLASS_MULTIMEDIA:
		case PCI_BASE_CLASS_MEMORY:
		case PCI_BASE_CLASS_BRIDGE:
		case PCI_BASE_CLASS_SERIAL:
			ret = 10;
			break;

		default:
			ret = 5;
			break;
		};
	}

	return ret;
}

static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
				     struct pci_dev *pdev,
				     unsigned int ino)
@@ -351,7 +283,7 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
	struct ino_bucket *bucket;
	unsigned long imap, iclr;
	unsigned long imap_off, iclr_off;
	int pil, inofixup = 0;
	int inofixup = 0;

	ino &= PCI_IRQ_INO;
	if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
@@ -367,11 +299,6 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
	}

	/* Now build the IRQ bucket. */
	pil = psycho_ino_to_pil(pdev, ino);

	if (PIL_RESERVED(pil))
		BUG();

	imap = pbm->controller_regs + imap_off;
	imap += 4;

@@ -382,7 +309,7 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
	if ((ino & 0x20) == 0)
		inofixup = ino & 0x03;

	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
	bucket = __bucket(build_irq(inofixup, iclr, imap));
	bucket->flags |= IBF_PCI;

	return __irq(bucket);
+2 −79
Original line number Diff line number Diff line
@@ -523,78 +523,6 @@ static unsigned long __onboard_imap_off[] = {
	((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
			(SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))

/* PCI SABRE INO number to Sparc PIL level. */
static unsigned char sabre_pil_table[] = {
/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D */
/*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D */
/*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D */
/*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D */
/*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D */
/*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D */
/*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D */
/*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D */
/*0x20*/5,		/* SCSI				*/
/*0x21*/5,		/* Ethernet			*/
/*0x22*/8,		/* Parallel Port		*/
/*0x23*/13,		/* Audio Record			*/
/*0x24*/14,		/* Audio Playback		*/
/*0x25*/15,		/* PowerFail			*/
/*0x26*/5,		/* second SCSI			*/
/*0x27*/11,		/* Floppy			*/
/*0x28*/5,		/* Spare Hardware		*/
/*0x29*/9,		/* Keyboard			*/
/*0x2a*/5,		/* Mouse			*/
/*0x2b*/12,		/* Serial			*/
/*0x2c*/10,		/* Timer 0			*/
/*0x2d*/11,		/* Timer 1			*/
/*0x2e*/15,		/* Uncorrectable ECC		*/
/*0x2f*/15,		/* Correctable ECC		*/
/*0x30*/15,		/* PCI Bus A Error		*/
/*0x31*/15,		/* PCI Bus B Error		*/
/*0x32*/15,		/* Power Management		*/
};

static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
{
	int ret;

	if (pdev &&
	    pdev->vendor == PCI_VENDOR_ID_SUN &&
	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
		return 9;

	ret = sabre_pil_table[ino];
	if (ret == 0 && pdev == NULL) {
		ret = 5;
	} else if (ret == 0) {
		switch ((pdev->class >> 16) & 0xff) {
		case PCI_BASE_CLASS_STORAGE:
			ret = 5;
			break;

		case PCI_BASE_CLASS_NETWORK:
			ret = 6;
			break;

		case PCI_BASE_CLASS_DISPLAY:
			ret = 9;
			break;

		case PCI_BASE_CLASS_MULTIMEDIA:
		case PCI_BASE_CLASS_MEMORY:
		case PCI_BASE_CLASS_BRIDGE:
		case PCI_BASE_CLASS_SERIAL:
			ret = 10;
			break;

		default:
			ret = 5;
			break;
		};
	}
	return ret;
}

/* When a device lives behind a bridge deeper in the PCI bus topology
 * than APB, a special sequence must run to make sure all pending DMA
 * transfers at the time of IRQ delivery are visible in the coherency
@@ -619,7 +547,7 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm,
	struct ino_bucket *bucket;
	unsigned long imap, iclr;
	unsigned long imap_off, iclr_off;
	int pil, inofixup = 0;
	int inofixup = 0;

	ino &= PCI_IRQ_INO;
	if (ino < SABRE_ONBOARD_IRQ_BASE) {
@@ -635,11 +563,6 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm,
	}

	/* Now build the IRQ bucket. */
	pil = sabre_ino_to_pil(pdev, ino);

	if (PIL_RESERVED(pil))
		BUG();

	imap = pbm->controller_regs + imap_off;
	imap += 4;

@@ -650,7 +573,7 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm,
	if ((ino & 0x20) == 0)
		inofixup = ino & 0x03;

	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
	bucket = __bucket(build_irq(inofixup, iclr, imap));
	bucket->flags |= IBF_PCI;

	if (pdev) {
+2 −102
Original line number Diff line number Diff line
@@ -232,101 +232,6 @@ static unsigned long schizo_iclr_offset(unsigned long ino)
	return SCHIZO_ICLR_BASE + (ino * 8UL);
}

/* PCI SCHIZO INO number to Sparc PIL level.  This table only matters for
 * INOs which will not have an associated PCI device struct, ie. onboard
 * EBUS devices and PCI controller internal error interrupts.
 */
static unsigned char schizo_pil_table[] = {
/*0x00*/0, 0, 0, 0,	/* PCI slot 0  Int A, B, C, D	*/
/*0x04*/0, 0, 0, 0,	/* PCI slot 1  Int A, B, C, D	*/
/*0x08*/0, 0, 0, 0,	/* PCI slot 2  Int A, B, C, D	*/
/*0x0c*/0, 0, 0, 0,	/* PCI slot 3  Int A, B, C, D	*/
/*0x10*/0, 0, 0, 0,	/* PCI slot 4  Int A, B, C, D	*/
/*0x14*/0, 0, 0, 0,	/* PCI slot 5  Int A, B, C, D	*/
/*0x18*/5,		/* SCSI				*/
/*0x19*/5,		/* second SCSI			*/
/*0x1a*/0,		/* UNKNOWN			*/
/*0x1b*/0,		/* UNKNOWN			*/
/*0x1c*/8,		/* Parallel			*/
/*0x1d*/5,		/* Ethernet			*/
/*0x1e*/8,		/* Firewire-1394		*/
/*0x1f*/9,		/* USB				*/
/*0x20*/13,		/* Audio Record			*/
/*0x21*/14,		/* Audio Playback		*/
/*0x22*/12,		/* Serial			*/
/*0x23*/5,		/* EBUS I2C 			*/
/*0x24*/10,		/* RTC Clock			*/
/*0x25*/11,		/* Floppy			*/
/*0x26*/0,		/* UNKNOWN			*/
/*0x27*/0,		/* UNKNOWN			*/
/*0x28*/0,		/* UNKNOWN			*/
/*0x29*/0,		/* UNKNOWN			*/
/*0x2a*/10,		/* UPA 1			*/
/*0x2b*/10,		/* UPA 2			*/
/*0x2c*/0,		/* UNKNOWN			*/
/*0x2d*/0,		/* UNKNOWN			*/
/*0x2e*/0,		/* UNKNOWN			*/
/*0x2f*/0,		/* UNKNOWN			*/
/*0x30*/15,		/* Uncorrectable ECC		*/
/*0x31*/15,		/* Correctable ECC		*/
/*0x32*/15,		/* PCI Bus A Error		*/
/*0x33*/15,		/* PCI Bus B Error		*/
/*0x34*/15,		/* Safari Bus Error		*/
/*0x35*/0,		/* Reserved			*/
/*0x36*/0,		/* Reserved			*/
/*0x37*/0,		/* Reserved			*/
/*0x38*/0,		/* Reserved for NewLink		*/
/*0x39*/0,		/* Reserved for NewLink		*/
/*0x3a*/0,		/* Reserved for NewLink		*/
/*0x3b*/0,		/* Reserved for NewLink		*/
/*0x3c*/0,		/* Reserved for NewLink		*/
/*0x3d*/0,		/* Reserved for NewLink		*/
/*0x3e*/0,		/* Reserved for NewLink		*/
/*0x3f*/0,		/* Reserved for NewLink		*/
};

static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
{
	int ret;

	if (pdev &&
	    pdev->vendor == PCI_VENDOR_ID_SUN &&
	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
		return 9;

	ret = schizo_pil_table[ino];
	if (ret == 0 && pdev == NULL) {
		ret = 5;
	} else if (ret == 0) {
		switch ((pdev->class >> 16) & 0xff) {
		case PCI_BASE_CLASS_STORAGE:
			ret = 5;
			break;

		case PCI_BASE_CLASS_NETWORK:
			ret = 6;
			break;

		case PCI_BASE_CLASS_DISPLAY:
			ret = 9;
			break;

		case PCI_BASE_CLASS_MULTIMEDIA:
		case PCI_BASE_CLASS_MEMORY:
		case PCI_BASE_CLASS_BRIDGE:
		case PCI_BASE_CLASS_SERIAL:
			ret = 10;
			break;

		default:
			ret = 5;
			break;
		};
	}

	return ret;
}

static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
{
	unsigned long sync_reg = (unsigned long) _arg2;
@@ -372,17 +277,12 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
	struct ino_bucket *bucket;
	unsigned long imap, iclr;
	unsigned long imap_off, iclr_off;
	int pil, ign_fixup;
	int ign_fixup;

	ino &= PCI_IRQ_INO;
	imap_off = schizo_imap_offset(ino);

	/* Now build the IRQ bucket. */
	pil = schizo_ino_to_pil(pdev, ino);

	if (PIL_RESERVED(pil))
		BUG();

	imap = pbm->pbm_regs + imap_off;
	imap += 4;

@@ -405,7 +305,7 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
			ign_fixup = (1 << 6);
	}

	bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap));
	bucket = __bucket(build_irq(ign_fixup, iclr, imap));
	bucket->flags |= IBF_PCI;

	if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
Loading