···444444 If you have more than 8 printers, you need to increase the LP_NO445445 macro in lp.c and the PARPORT_MAX macro in parport.h.446446447447+config PPDEV448448+ tristate "Support for user-space parallel port device drivers"449449+ depends on PARPORT450450+ ---help---451451+ Saying Y to this adds support for /dev/parport device nodes. This452452+ is needed for programs that want portable access to the parallel453453+ port, for instance deviceid (which displays Plug-and-Play device454454+ IDs).455455+456456+ This is the parallel port equivalent of SCSI generic support (sg).457457+ It is safe to say N to this -- it is not needed for normal printing458458+ or parallel port CD-ROM/disk support.459459+460460+ To compile this driver as a module, choose M here: the461461+ module will be called ppdev.462462+463463+ If unsure, say N.464464+447465config ENVCTRL448466 tristate "SUNW, envctrl support"449467 depends on PCI
···7171struct irq_work_struct __irq_work[NR_CPUS];7272#define irq_work(__cpu, __pil) &(__irq_work[(__cpu)].irq_worklists[(__pil)])73737474-#ifdef CONFIG_PCI7575-/* This is a table of physical addresses used to deal with IBF_DMA_SYNC.7676- * It is used for PCI only to synchronize DMA transfers with IRQ delivery7777- * for devices behind busses other than APB on Sabre systems.7878- *7979- * Currently these physical addresses are just config space accesses8080- * to the command register for that device.8181- */8282-unsigned long pci_dma_wsync;8383-unsigned long dma_sync_reg_table[256];8484-unsigned char dma_sync_reg_table_entry = 0;8585-#endif8686-8787-/* This is based upon code in the 32-bit Sparc kernel written mostly by8888- * David Redman (djhr@tadpole.co.uk).8989- */9090-#define MAX_STATIC_ALLOC 49191-static struct irqaction static_irqaction[MAX_STATIC_ALLOC];9292-static int static_irq_count;9393-9494-/* This is exported so that fast IRQ handlers can get at it... -DaveM */9595-struct irqaction *irq_action[NR_IRQS+1] = {9696- NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,9797- NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL9898-};7474+static struct irqaction *irq_action[NR_IRQS+1];997510076/* This only synchronizes entities which modify IRQ handler10177 * state and some selected user-level spots that want to···217241 * the CPU %tick register and not by some normal vectored interrupt218242 * source. To handle this special case, we use this dummy INO bucket.219243 */244244+static struct irq_desc pil0_dummy_desc;220245static struct ino_bucket pil0_dummy_bucket = {221221- 0, /* irq_chain */222222- 0, /* pil */223223- 0, /* pending */224224- 0, /* flags */225225- 0, /* __unused */226226- NULL, /* irq_info */227227- 0UL, /* iclr */228228- 0UL, /* imap */246246+ .irq_info = &pil0_dummy_desc,229247};248248+249249+static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup,250250+ unsigned long iclr, unsigned long imap,251251+ struct ino_bucket *bucket)252252+{253253+ prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> "254254+ "(%d:%d:%016lx:%016lx), halting...\n",255255+ ino, bucket->pil, bucket->iclr, bucket->imap,256256+ pil, inofixup, iclr, imap);257257+ prom_halt();258258+}230259231260unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap)232261{···261280 prom_halt();262281 }263282283283+ bucket = &ivector_table[ino];284284+ if (bucket->flags & IBF_ACTIVE)285285+ build_irq_error("IRQ: Trying to build active INO bucket.\n",286286+ ino, pil, inofixup, iclr, imap, bucket);287287+288288+ if (bucket->irq_info) {289289+ if (bucket->imap != imap || bucket->iclr != iclr)290290+ build_irq_error("IRQ: Trying to reinit INO bucket.\n",291291+ ino, pil, inofixup, iclr, imap, bucket);292292+293293+ goto out;294294+ }295295+296296+ bucket->irq_info = kmalloc(sizeof(struct irq_desc), GFP_ATOMIC);297297+ if (!bucket->irq_info) {298298+ prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");299299+ prom_halt();300300+ }301301+ memset(bucket->irq_info, 0, sizeof(struct irq_desc));302302+264303 /* Ok, looks good, set it up. Don't touch the irq_chain or265304 * the pending flag.266305 */267267- bucket = &ivector_table[ino];268268- if ((bucket->flags & IBF_ACTIVE) ||269269- (bucket->irq_info != NULL)) {270270- /* This is a gross fatal error if it happens here. */271271- prom_printf("IRQ: Trying to reinit INO bucket, fatal error.\n");272272- prom_printf("IRQ: Request INO %04x (%d:%d:%016lx:%016lx)\n",273273- ino, pil, inofixup, iclr, imap);274274- prom_printf("IRQ: Existing (%d:%016lx:%016lx)\n",275275- bucket->pil, bucket->iclr, bucket->imap);276276- prom_printf("IRQ: Cannot continue, halting...\n");277277- prom_halt();278278- }279306 bucket->imap = imap;280307 bucket->iclr = iclr;281308 bucket->pil = pil;282309 bucket->flags = 0;283310284284- bucket->irq_info = NULL;285285-311311+out:286312 return __irq(bucket);287313}288314···307319 __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));308320}309321322322+static int check_irq_sharing(int pil, unsigned long irqflags)323323+{324324+ struct irqaction *action, *tmp;325325+326326+ action = *(irq_action + pil);327327+ if (action) {328328+ if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {329329+ for (tmp = action; tmp->next; tmp = tmp->next)330330+ ;331331+ } else {332332+ return -EBUSY;333333+ }334334+ }335335+ return 0;336336+}337337+338338+static void append_irq_action(int pil, struct irqaction *action)339339+{340340+ struct irqaction **pp = irq_action + pil;341341+342342+ while (*pp)343343+ pp = &((*pp)->next);344344+ *pp = action;345345+}346346+347347+static struct irqaction *get_action_slot(struct ino_bucket *bucket)348348+{349349+ struct irq_desc *desc = bucket->irq_info;350350+ int max_irq, i;351351+352352+ max_irq = 1;353353+ if (bucket->flags & IBF_PCI)354354+ max_irq = MAX_IRQ_DESC_ACTION;355355+ for (i = 0; i < max_irq; i++) {356356+ struct irqaction *p = &desc->action[i];357357+ u32 mask = (1 << i);358358+359359+ if (desc->action_active_mask & mask)360360+ continue;361361+362362+ desc->action_active_mask |= mask;363363+ return p;364364+ }365365+ return NULL;366366+}367367+310368int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),311369 unsigned long irqflags, const char *name, void *dev_id)312370{313313- struct irqaction *action, *tmp = NULL;371371+ struct irqaction *action;314372 struct ino_bucket *bucket = __bucket(irq);315373 unsigned long flags;316374 int pending = 0;317375318318- if ((bucket != &pil0_dummy_bucket) &&319319- (bucket < &ivector_table[0] ||320320- bucket >= &ivector_table[NUM_IVECS])) {321321- unsigned int *caller;322322-323323- __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));324324- printk(KERN_CRIT "request_irq: Old style IRQ registry attempt "325325- "from %p, irq %08x.\n", caller, irq);376376+ if (unlikely(!handler))326377 return -EINVAL;327327- } 328328- if (!handler)329329- return -EINVAL;378378+379379+ if (unlikely(!bucket->irq_info))380380+ return -ENODEV;330381331382 if ((bucket != &pil0_dummy_bucket) && (irqflags & SA_SAMPLE_RANDOM)) {332383 /*···383356384357 spin_lock_irqsave(&irq_action_lock, flags);385358386386- action = *(bucket->pil + irq_action);387387- if (action) {388388- if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ))389389- for (tmp = action; tmp->next; tmp = tmp->next)390390- ;391391- else {392392- spin_unlock_irqrestore(&irq_action_lock, flags);393393- return -EBUSY;394394- }395395- action = NULL; /* Or else! */359359+ if (check_irq_sharing(bucket->pil, irqflags)) {360360+ spin_unlock_irqrestore(&irq_action_lock, flags);361361+ return -EBUSY;396362 }397363398398- /* If this is flagged as statically allocated then we use our399399- * private struct which is never freed.400400- */401401- if (irqflags & SA_STATIC_ALLOC) {402402- if (static_irq_count < MAX_STATIC_ALLOC)403403- action = &static_irqaction[static_irq_count++];404404- else405405- printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed "406406- "using kmalloc\n", irq, name);407407- } 408408- if (action == NULL)409409- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),410410- GFP_ATOMIC);411411-364364+ action = get_action_slot(bucket);412365 if (!action) { 413366 spin_unlock_irqrestore(&irq_action_lock, flags);414367 return -ENOMEM;415368 }416369417417- if (bucket == &pil0_dummy_bucket) {418418- bucket->irq_info = action;419419- bucket->flags |= IBF_ACTIVE;420420- } else {421421- if ((bucket->flags & IBF_ACTIVE) != 0) {422422- void *orig = bucket->irq_info;423423- void **vector = NULL;424424-425425- if ((bucket->flags & IBF_PCI) == 0) {426426- printk("IRQ: Trying to share non-PCI bucket.\n");427427- goto free_and_ebusy;428428- }429429- if ((bucket->flags & IBF_MULTI) == 0) {430430- vector = kmalloc(sizeof(void *) * 4, GFP_ATOMIC);431431- if (vector == NULL)432432- goto free_and_enomem;433433-434434- /* We might have slept. */435435- if ((bucket->flags & IBF_MULTI) != 0) {436436- int ent;437437-438438- kfree(vector);439439- vector = (void **)bucket->irq_info;440440- for(ent = 0; ent < 4; ent++) {441441- if (vector[ent] == NULL) {442442- vector[ent] = action;443443- break;444444- }445445- }446446- if (ent == 4)447447- goto free_and_ebusy;448448- } else {449449- vector[0] = orig;450450- vector[1] = action;451451- vector[2] = NULL;452452- vector[3] = NULL;453453- bucket->irq_info = vector;454454- bucket->flags |= IBF_MULTI;455455- }456456- } else {457457- int ent;458458-459459- vector = (void **)orig;460460- for (ent = 0; ent < 4; ent++) {461461- if (vector[ent] == NULL) {462462- vector[ent] = action;463463- break;464464- }465465- }466466- if (ent == 4)467467- goto free_and_ebusy;468468- }469469- } else {470470- bucket->irq_info = action;471471- bucket->flags |= IBF_ACTIVE;472472- }370370+ bucket->flags |= IBF_ACTIVE;371371+ pending = 0;372372+ if (bucket != &pil0_dummy_bucket) {473373 pending = bucket->pending;474374 if (pending)475375 bucket->pending = 0;···410456 put_ino_in_irqaction(action, irq);411457 put_smpaff_in_irqaction(action, CPU_MASK_NONE);412458413413- if (tmp)414414- tmp->next = action;415415- else416416- *(bucket->pil + irq_action) = action;459459+ append_irq_action(bucket->pil, action);417460418461 enable_irq(irq);419462···419468 atomic_bucket_insert(bucket);420469 set_softint(1 << bucket->pil);421470 }471471+422472 spin_unlock_irqrestore(&irq_action_lock, flags);423423- if ((bucket != &pil0_dummy_bucket) && (!(irqflags & SA_STATIC_ALLOC)))473473+474474+ if (bucket != &pil0_dummy_bucket)424475 register_irq_proc(__irq_ino(irq));425476426477#ifdef CONFIG_SMP427478 distribute_irqs();428479#endif429480 return 0;430430-431431-free_and_ebusy:432432- kfree(action);433433- spin_unlock_irqrestore(&irq_action_lock, flags);434434- return -EBUSY;435435-436436-free_and_enomem:437437- kfree(action);438438- spin_unlock_irqrestore(&irq_action_lock, flags);439439- return -ENOMEM;440481}441482442483EXPORT_SYMBOL(request_irq);443484485485+static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id)486486+{487487+ struct ino_bucket *bucket = __bucket(irq);488488+ struct irqaction *action, **pp;489489+490490+ pp = irq_action + bucket->pil;491491+ action = *pp;492492+ if (unlikely(!action))493493+ return NULL;494494+495495+ if (unlikely(!action->handler)) {496496+ printk("Freeing free IRQ %d\n", bucket->pil);497497+ return NULL;498498+ }499499+500500+ while (action && action->dev_id != dev_id) {501501+ pp = &action->next;502502+ action = *pp;503503+ }504504+505505+ if (likely(action))506506+ *pp = action->next;507507+508508+ return action;509509+}510510+444511void free_irq(unsigned int irq, void *dev_id)445512{446513 struct irqaction *action;447447- struct irqaction *tmp = NULL;514514+ struct ino_bucket *bucket;448515 unsigned long flags;449449- struct ino_bucket *bucket = __bucket(irq), *bp;450516451451- if ((bucket != &pil0_dummy_bucket) &&452452- (bucket < &ivector_table[0] ||453453- bucket >= &ivector_table[NUM_IVECS])) {454454- unsigned int *caller;455455-456456- __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));457457- printk(KERN_CRIT "free_irq: Old style IRQ removal attempt "458458- "from %p, irq %08x.\n", caller, irq);459459- return;460460- }461461-462517 spin_lock_irqsave(&irq_action_lock, flags);463518464464- action = *(bucket->pil + irq_action);465465- if (!action->handler) {466466- printk("Freeing free IRQ %d\n", bucket->pil);467467- return;468468- }469469- if (dev_id) {470470- for ( ; action; action = action->next) {471471- if (action->dev_id == dev_id)472472- break;473473- tmp = action;474474- }475475- if (!action) {476476- printk("Trying to free free shared IRQ %d\n", bucket->pil);477477- spin_unlock_irqrestore(&irq_action_lock, flags);478478- return;479479- }480480- } else if (action->flags & SA_SHIRQ) {481481- printk("Trying to free shared IRQ %d with NULL device ID\n", bucket->pil);482482- spin_unlock_irqrestore(&irq_action_lock, flags);483483- return;484484- }485485-486486- if (action->flags & SA_STATIC_ALLOC) {487487- printk("Attempt to free statically allocated IRQ %d (%s)\n",488488- bucket->pil, action->name);489489- spin_unlock_irqrestore(&irq_action_lock, flags);490490- return;491491- }492492-493493- if (action && tmp)494494- tmp->next = action->next;495495- else496496- *(bucket->pil + irq_action) = action->next;519519+ action = unlink_irq_action(irq, dev_id);497520498521 spin_unlock_irqrestore(&irq_action_lock, flags);522522+523523+ if (unlikely(!action))524524+ return;499525500526 synchronize_irq(irq);501527502528 spin_lock_irqsave(&irq_action_lock, flags);503529530530+ bucket = __bucket(irq);504531 if (bucket != &pil0_dummy_bucket) {532532+ struct irq_desc *desc = bucket->irq_info;505533 unsigned long imap = bucket->imap;506506- void **vector, *orig;507507- int ent;534534+ int ent, i;508535509509- orig = bucket->irq_info;510510- vector = (void **)orig;536536+ for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) {537537+ struct irqaction *p = &desc->action[i];511538512512- if ((bucket->flags & IBF_MULTI) != 0) {513513- int other = 0;514514- void *orphan = NULL;515515- for (ent = 0; ent < 4; ent++) {516516- if (vector[ent] == action)517517- vector[ent] = NULL;518518- else if (vector[ent] != NULL) {519519- orphan = vector[ent];520520- other++;521521- }522522- }523523-524524- /* Only free when no other shared irq525525- * uses this bucket.526526- */527527- if (other) {528528- if (other == 1) {529529- /* Convert back to non-shared bucket. */530530- bucket->irq_info = orphan;531531- bucket->flags &= ~(IBF_MULTI);532532- kfree(vector);533533- }534534- goto out;535535- }536536- } else {537537- bucket->irq_info = NULL;538538- }539539-540540- /* This unique interrupt source is now inactive. */541541- bucket->flags &= ~IBF_ACTIVE;542542-543543- /* See if any other buckets share this bucket's IMAP544544- * and are still active.545545- */546546- for (ent = 0; ent < NUM_IVECS; ent++) {547547- bp = &ivector_table[ent];548548- if (bp != bucket &&549549- bp->imap == imap &&550550- (bp->flags & IBF_ACTIVE) != 0)539539+ if (p == action) {540540+ desc->action_active_mask &= ~(1 << i);551541 break;542542+ }552543 }553544554554- /* Only disable when no other sub-irq levels of555555- * the same IMAP are active.556556- */557557- if (ent == NUM_IVECS)558558- disable_irq(irq);545545+ if (!desc->action_active_mask) {546546+ /* This unique interrupt source is now inactive. */547547+ bucket->flags &= ~IBF_ACTIVE;548548+549549+ /* See if any other buckets share this bucket's IMAP550550+ * and are still active.551551+ */552552+ for (ent = 0; ent < NUM_IVECS; ent++) {553553+ struct ino_bucket *bp = &ivector_table[ent];554554+ if (bp != bucket &&555555+ bp->imap == imap &&556556+ (bp->flags & IBF_ACTIVE) != 0)557557+ break;558558+ }559559+560560+ /* Only disable when no other sub-irq levels of561561+ * the same IMAP are active.562562+ */563563+ if (ent == NUM_IVECS)564564+ disable_irq(irq);565565+ }559566 }560567561561-out:562562- kfree(action);563568 spin_unlock_irqrestore(&irq_action_lock, flags);564569}565570···554647}555648#endif /* CONFIG_SMP */556649557557-void catch_disabled_ivec(struct pt_regs *regs)650650+static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs)558651{559559- int cpu = smp_processor_id();560560- struct ino_bucket *bucket = __bucket(*irq_work(cpu, 0));652652+ struct irq_desc *desc = bp->irq_info;653653+ unsigned char flags = bp->flags;654654+ u32 action_mask, i;655655+ int random;561656562562- /* We can actually see this on Ultra/PCI PCI cards, which are bridges563563- * to other devices. Here a single IMAP enabled potentially multiple564564- * unique interrupt sources (which each do have a unique ICLR register.565565- *566566- * So what we do is just register that the IVEC arrived, when registered567567- * for real the request_irq() code will check the bit and signal568568- * a local CPU interrupt for it.569569- */570570-#if 0571571- printk("IVEC: Spurious interrupt vector (%x) received at (%016lx)\n",572572- bucket - &ivector_table[0], regs->tpc);573573-#endif574574- *irq_work(cpu, 0) = 0;575575- bucket->pending = 1;576576-}657657+ bp->flags |= IBF_INPROGRESS;577658578578-/* Tune this... */579579-#define FORWARD_VOLUME 12580580-581581-#ifdef CONFIG_SMP582582-583583-static inline void redirect_intr(int cpu, struct ino_bucket *bp)584584-{585585- /* Ok, here is what is going on:586586- * 1) Retargeting IRQs on Starfire is very587587- * expensive so just forget about it on them.588588- * 2) Moving around very high priority interrupts589589- * is a losing game.590590- * 3) If the current cpu is idle, interrupts are591591- * useful work, so keep them here. But do not592592- * pass to our neighbour if he is not very idle.593593- * 4) If sysadmin explicitly asks for directed intrs,594594- * Just Do It.595595- */596596- struct irqaction *ap = bp->irq_info;597597- cpumask_t cpu_mask;598598- unsigned int buddy, ticks;599599-600600- cpu_mask = get_smpaff_in_irqaction(ap);601601- cpus_and(cpu_mask, cpu_mask, cpu_online_map);602602- if (cpus_empty(cpu_mask))603603- cpu_mask = cpu_online_map;604604-605605- if (this_is_starfire != 0 ||606606- bp->pil >= 10 || current->pid == 0)659659+ if (unlikely(!(flags & IBF_ACTIVE))) {660660+ bp->pending = 1;607661 goto out;608608-609609- /* 'cpu' is the MID (ie. UPAID), calculate the MID610610- * of our buddy.611611- */612612- buddy = cpu + 1;613613- if (buddy >= NR_CPUS)614614- buddy = 0;615615-616616- ticks = 0;617617- while (!cpu_isset(buddy, cpu_mask)) {618618- if (++buddy >= NR_CPUS)619619- buddy = 0;620620- if (++ticks > NR_CPUS) {621621- put_smpaff_in_irqaction(ap, CPU_MASK_NONE);622622- goto out;623623- }624662 }625663626626- if (buddy == cpu)627627- goto out;664664+ if (desc->pre_handler)665665+ desc->pre_handler(bp,666666+ desc->pre_handler_arg1,667667+ desc->pre_handler_arg2);628668629629- /* Voo-doo programming. */630630- if (cpu_data(buddy).idle_volume < FORWARD_VOLUME)631631- goto out;669669+ action_mask = desc->action_active_mask;670670+ random = 0;671671+ for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) {672672+ struct irqaction *p = &desc->action[i];673673+ u32 mask = (1 << i);632674633633- /* This just so happens to be correct on Cheetah634634- * at the moment.635635- */636636- buddy <<= 26;675675+ if (!(action_mask & mask))676676+ continue;637677638638- /* Push it to our buddy. */639639- upa_writel(buddy | IMAP_VALID, bp->imap);678678+ action_mask &= ~mask;640679680680+ if (p->handler(__irq(bp), p->dev_id, regs) == IRQ_HANDLED)681681+ random |= p->flags;682682+683683+ if (!action_mask)684684+ break;685685+ }686686+ if (bp->pil != 0) {687687+ upa_writel(ICLR_IDLE, bp->iclr);688688+ /* Test and add entropy */689689+ if (random & SA_SAMPLE_RANDOM)690690+ add_interrupt_randomness(irq);691691+ }641692out:642642- return;693693+ bp->flags &= ~IBF_INPROGRESS;643694}644644-645645-#endif646695647696void handler_irq(int irq, struct pt_regs *regs)648697{649649- struct ino_bucket *bp, *nbp;698698+ struct ino_bucket *bp;650699 int cpu = smp_processor_id();651700652701#ifndef CONFIG_SMP···620757 clear_softint(clr_mask);621758 }622759#else623623- int should_forward = 0;624624-625760 clear_softint(1 << irq);626761#endif627762···634773#else635774 bp = __bucket(xchg32(irq_work(cpu, irq), 0));636775#endif637637- for ( ; bp != NULL; bp = nbp) {638638- unsigned char flags = bp->flags;639639- unsigned char random = 0;776776+ while (bp) {777777+ struct ino_bucket *nbp = __bucket(bp->irq_chain);640778641641- nbp = __bucket(bp->irq_chain);642779 bp->irq_chain = 0;643643-644644- bp->flags |= IBF_INPROGRESS;645645-646646- if ((flags & IBF_ACTIVE) != 0) {647647-#ifdef CONFIG_PCI648648- if ((flags & IBF_DMA_SYNC) != 0) {649649- upa_readl(dma_sync_reg_table[bp->synctab_ent]);650650- upa_readq(pci_dma_wsync);651651- }652652-#endif653653- if ((flags & IBF_MULTI) == 0) {654654- struct irqaction *ap = bp->irq_info;655655- int ret;656656-657657- ret = ap->handler(__irq(bp), ap->dev_id, regs);658658- if (ret == IRQ_HANDLED)659659- random |= ap->flags;660660- } else {661661- void **vector = (void **)bp->irq_info;662662- int ent;663663- for (ent = 0; ent < 4; ent++) {664664- struct irqaction *ap = vector[ent];665665- if (ap != NULL) {666666- int ret;667667-668668- ret = ap->handler(__irq(bp),669669- ap->dev_id,670670- regs);671671- if (ret == IRQ_HANDLED)672672- random |= ap->flags;673673- }674674- }675675- }676676- /* Only the dummy bucket lacks IMAP/ICLR. */677677- if (bp->pil != 0) {678678-#ifdef CONFIG_SMP679679- if (should_forward) {680680- redirect_intr(cpu, bp);681681- should_forward = 0;682682- }683683-#endif684684- upa_writel(ICLR_IDLE, bp->iclr);685685-686686- /* Test and add entropy */687687- if (random & SA_SAMPLE_RANDOM)688688- add_interrupt_randomness(irq);689689- }690690- } else691691- bp->pending = 1;692692-693693- bp->flags &= ~IBF_INPROGRESS;780780+ process_bucket(irq, bp, regs);781781+ bp = nbp;694782 }695783 irq_exit();696784}···769959 */770960 for (level = 1; level < NR_IRQS; level++) {771961 struct irqaction *p = irq_action[level];772772- if (level == 12) continue;962962+963963+ if (level == 12)964964+ continue;965965+773966 while(p) {774967 cpu = retarget_one_irq(p, cpu);775968 p = p->next;
+1-2
arch/sparc64/kernel/pci_psycho.c
···13031303{13041304 u64 tmp;1305130513061306- /* PROM sets the IRQ retry value too low, increase it. */13071307- psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 0xff);13061306+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 5);1308130713091308 /* Enable arbiter for all PCI slots. */13101309 tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL);
+26-20
arch/sparc64/kernel/pci_sabre.c
···595595 return ret;596596}597597598598+/* When a device lives behind a bridge deeper in the PCI bus topology599599+ * than APB, a special sequence must run to make sure all pending DMA600600+ * transfers at the time of IRQ delivery are visible in the coherency601601+ * domain by the cpu. This sequence is to perform a read on the far602602+ * side of the non-APB bridge, then perform a read of Sabre's DMA603603+ * write-sync register.604604+ */605605+static void sabre_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)606606+{607607+ struct pci_dev *pdev = _arg1;608608+ unsigned long sync_reg = (unsigned long) _arg2;609609+ u16 _unused;610610+611611+ pci_read_config_word(pdev, PCI_VENDOR_ID, &_unused);612612+ sabre_read(sync_reg);613613+}614614+598615static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,599616 struct pci_dev *pdev,600617 unsigned int ino)···656639 if (pdev) {657640 struct pcidev_cookie *pcp = pdev->sysdata;658641659659- /* When a device lives behind a bridge deeper in the660660- * PCI bus topology than APB, a special sequence must661661- * run to make sure all pending DMA transfers at the662662- * time of IRQ delivery are visible in the coherency663663- * domain by the cpu. This sequence is to perform664664- * a read on the far side of the non-APB bridge, then665665- * perform a read of Sabre's DMA write-sync register.666666- *667667- * Currently, the PCI_CONFIG register for the device668668- * is used for this read from the far side of the bridge.669669- */670642 if (pdev->bus->number != pcp->pbm->pci_first_busno) {671671- bucket->flags |= IBF_DMA_SYNC;672672- bucket->synctab_ent = dma_sync_reg_table_entry++;673673- dma_sync_reg_table[bucket->synctab_ent] =674674- (unsigned long) sabre_pci_config_mkaddr(675675- pcp->pbm,676676- pdev->bus->number, pdev->devfn, PCI_COMMAND);643643+ struct pci_controller_info *p = pcp->pbm->parent;644644+ struct irq_desc *d = bucket->irq_info;645645+646646+ d->pre_handler = sabre_wsync_handler;647647+ d->pre_handler_arg1 = pdev;648648+ d->pre_handler_arg2 = (void *)649649+ p->pbm_A.controller_regs + SABRE_WRSYNC;677650 }678651 }679652 return __irq(bucket);···16331626 */16341627 p->pbm_A.controller_regs = pr_regs[0].phys_addr;16351628 p->pbm_B.controller_regs = pr_regs[0].phys_addr;16361636- pci_dma_wsync = p->pbm_A.controller_regs + SABRE_WRSYNC;1637162916381638- printk("PCI: Found SABRE, main regs at %016lx, wsync at %016lx\n",16391639- p->pbm_A.controller_regs, pci_dma_wsync);16301630+ printk("PCI: Found SABRE, main regs at %016lx\n",16311631+ p->pbm_A.controller_regs);1640163216411633 /* Clear interrupts */16421634
···1616#include <asm/pil.h>1717#include <asm/ptrace.h>18181919+struct ino_bucket;2020+2121+#define MAX_IRQ_DESC_ACTION 42222+2323+struct irq_desc {2424+ void (*pre_handler)(struct ino_bucket *, void *, void *);2525+ void *pre_handler_arg1;2626+ void *pre_handler_arg2;2727+ u32 action_active_mask;2828+ struct irqaction action[MAX_IRQ_DESC_ACTION];2929+};3030+1931/* You should not mess with this directly. That's the job of irq.c.2032 *2133 * If you make changes here, please update hand coded assembler of···5442 /* Miscellaneous flags. */5543/*0x06*/unsigned char flags;56445757- /* This is used to deal with IBF_DMA_SYNC on5858- * Sabre systems.5959- */6060-/*0x07*/unsigned char synctab_ent;4545+ /* Currently unused. */4646+/*0x07*/unsigned char __pad;61476262- /* Reference to handler for this IRQ. If this is6363- * non-NULL this means it is active and should be6464- * serviced. Else the pending member is set to one6565- * and later registry of the interrupt checks for6666- * this condition.6767- *6868- * Normally this is just an irq_action structure.6969- * But, on PCI, if multiple interrupt sources behind7070- * a bridge have multiple interrupt sources that share7171- * the same INO bucket, this points to an array of7272- * pointers to four IRQ action structures.7373- */7474-/*0x08*/void *irq_info;4848+ /* Reference to IRQ descriptor for this bucket. */4949+/*0x08*/struct irq_desc *irq_info;75507651 /* Sun5 Interrupt Clear Register. */7752/*0x10*/unsigned long iclr;···6768/*0x18*/unsigned long imap;68696970};7070-7171-#ifdef CONFIG_PCI7272-extern unsigned long pci_dma_wsync;7373-extern unsigned long dma_sync_reg_table[256];7474-extern unsigned char dma_sync_reg_table_entry;7575-#endif76717772/* IMAP/ICLR register defines */7873#define IMAP_VALID 0x80000000 /* IRQ Enabled */···8390#define ICLR_PENDING 0x00000003 /* Pending state */84918592/* Only 8-bits are available, be careful. -DaveM */8686-#define IBF_DMA_SYNC 0x01 /* DMA synchronization behind PCI bridge needed. */8787-#define IBF_PCI 0x02 /* Indicates PSYCHO/SABRE/SCHIZO PCI interrupt. */8888-#define IBF_ACTIVE 0x04 /* This interrupt is active and has a handler. */8989-#define IBF_MULTI 0x08 /* On PCI, indicates shared bucket. */9090-#define IBF_INPROGRESS 0x10 /* IRQ is being serviced. */9393+#define IBF_PCI 0x02 /* PSYCHO/SABRE/SCHIZO PCI interrupt. */9494+#define IBF_ACTIVE 0x04 /* Interrupt is active and has a handler.*/9595+#define IBF_INPROGRESS 0x10 /* IRQ is being serviced. */91969297#define NUM_IVECS (IMAP_INR + 1)9398extern struct ino_bucket ivector_table[NUM_IVECS];
+3
include/asm-sparc64/pbm.h
···145145 /* Physical address base of PBM registers. */146146 unsigned long pbm_regs;147147148148+ /* Physical address of DMA sync register, if any. */149149+ unsigned long sync_reg;150150+148151 /* Opaque 32-bit system bus Port ID. */149152 u32 portid;150153
-15
include/asm-sparc64/signal.h
···162162#define MINSIGSTKSZ 4096163163#define SIGSTKSZ 16384164164165165-#ifdef __KERNEL__166166-/*167167- * DJHR168168- * SA_STATIC_ALLOC is used for the SPARC system to indicate that this169169- * interrupt handler's irq structure should be statically allocated170170- * by the request_irq routine.171171- * The alternative is that arch/sparc/kernel/irq.c has carnal knowledge172172- * of interrupt usage and that sucks. Also without a flag like this173173- * it may be possible for the free_irq routine to attempt to free174174- * statically allocated data.. which is NOT GOOD.175175- *176176- */177177-#define SA_STATIC_ALLOC 0x80178178-#endif179179-180165#include <asm-generic/signal.h>181166182167struct __new_sigaction {