irq.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:35k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: irq.c,v 1.112 2001/11/16 00:04:54 kanoj Exp $
  2.  * irq.c: UltraSparc IRQ handling/init/registry.
  3.  *
  4.  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
  5.  * Copyright (C) 1998  Eddie C. Dost    (ecd@skynet.be)
  6.  * Copyright (C) 1998  Jakub Jelinek    (jj@ultra.linux.cz)
  7.  */
  8. #include <linux/config.h>
  9. #include <linux/ptrace.h>
  10. #include <linux/errno.h>
  11. #include <linux/kernel_stat.h>
  12. #include <linux/signal.h>
  13. #include <linux/mm.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/slab.h>
  16. #include <linux/random.h>
  17. #include <linux/init.h>
  18. #include <linux/delay.h>
  19. #include <linux/proc_fs.h>
  20. #include <linux/kbd_ll.h>
  21. #include <asm/ptrace.h>
  22. #include <asm/processor.h>
  23. #include <asm/atomic.h>
  24. #include <asm/system.h>
  25. #include <asm/irq.h>
  26. #include <asm/sbus.h>
  27. #include <asm/iommu.h>
  28. #include <asm/upa.h>
  29. #include <asm/oplib.h>
  30. #include <asm/timer.h>
  31. #include <asm/smp.h>
  32. #include <asm/hardirq.h>
  33. #include <asm/softirq.h>
  34. #include <asm/starfire.h>
  35. #include <asm/uaccess.h>
  36. #include <asm/cache.h>
  37. #ifdef CONFIG_SMP
  38. static void distribute_irqs(void);
  39. #endif
  40. /* UPA nodes send interrupt packet to UltraSparc with first data reg
  41.  * value low 5 (7 on Starfire) bits holding the IRQ identifier being
  42.  * delivered.  We must translate this into a non-vector IRQ so we can
  43.  * set the softint on this cpu.
  44.  *
  45.  * To make processing these packets efficient and race free we use
  46.  * an array of irq buckets below.  The interrupt vector handler in
  47.  * entry.S feeds incoming packets into per-cpu pil-indexed lists.
  48.  * The IVEC handler does not need to act atomically, the PIL dispatch
  49.  * code uses CAS to get an atomic snapshot of the list and clear it
  50.  * at the same time.
  51.  */
  52. struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES)));
  53. #ifndef CONFIG_SMP
  54. unsigned int __up_workvec[16] __attribute__ ((aligned (SMP_CACHE_BYTES)));
  55. #define irq_work(__cpu, __pil) &(__up_workvec[(void)(__cpu), (__pil)])
  56. #else
  57. #define irq_work(__cpu, __pil) &(cpu_data[(__cpu)].irq_worklists[(__pil)])
  58. #endif
  59. #ifdef CONFIG_PCI
  60. /* This is a table of physical addresses used to deal with IBF_DMA_SYNC.
  61.  * It is used for PCI only to synchronize DMA transfers with IRQ delivery
  62.  * for devices behind busses other than APB on Sabre systems.
  63.  *
  64.  * Currently these physical addresses are just config space accesses
  65.  * to the command register for that device.
  66.  */
  67. unsigned long pci_dma_wsync;
  68. unsigned long dma_sync_reg_table[256];
  69. unsigned char dma_sync_reg_table_entry = 0;
  70. #endif
  71. /* This is based upon code in the 32-bit Sparc kernel written mostly by
  72.  * David Redman (djhr@tadpole.co.uk).
  73.  */
  74. #define MAX_STATIC_ALLOC 4
  75. static struct irqaction static_irqaction[MAX_STATIC_ALLOC];
  76. static int static_irq_count;
  77. /* This is exported so that fast IRQ handlers can get at it... -DaveM */
  78. struct irqaction *irq_action[NR_IRQS+1] = {
  79.   NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
  80.   NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
  81. };
  82. static void register_irq_proc (unsigned int irq);
  83. /*
  84.  * Upper 2b of irqaction->flags holds the ino.
  85.  * irqaction->mask holds the smp affinity information.
  86.  */
  87. #define put_ino_in_irqaction(action, irq) 
  88. action->flags &= 0xffffffffffffUL; 
  89. if (__bucket(irq) == &pil0_dummy_bucket) 
  90. action->flags |= 0xdeadUL << 48;  
  91. else 
  92. action->flags |= __irq_ino(irq) << 48;
  93. #define get_ino_in_irqaction(action) (action->flags >> 48)
  94. #define put_smpaff_in_irqaction(action, smpaff) (action)->mask = (smpaff)
  95. #define get_smpaff_in_irqaction(action)  ((action)->mask)
  96. int get_irq_list(char *buf)
  97. {
  98. int i, len = 0;
  99. struct irqaction *action;
  100. #ifdef CONFIG_SMP
  101. int j;
  102. #endif
  103. for(i = 0; i < (NR_IRQS + 1); i++) {
  104. if(!(action = *(i + irq_action)))
  105. continue;
  106. len += sprintf(buf + len, "%3d: ", i);
  107. #ifndef CONFIG_SMP
  108. len += sprintf(buf + len, "%10u ", kstat_irqs(i));
  109. #else
  110. for (j = 0; j < smp_num_cpus; j++)
  111. len += sprintf(buf + len, "%10u ",
  112.        kstat.irqs[cpu_logical_map(j)][i]);
  113. #endif
  114. len += sprintf(buf + len, " %s:%lx", action->name, 
  115. get_ino_in_irqaction(action));
  116. for(action = action->next; action; action = action->next) {
  117. len += sprintf(buf+len, ", %s:%lx", action->name, 
  118. get_ino_in_irqaction(action));
  119. }
  120. len += sprintf(buf + len, "n");
  121. }
  122. return len;
  123. }
  124. /* Now these are always passed a true fully specified sun4u INO. */
  125. void enable_irq(unsigned int irq)
  126. {
  127. struct ino_bucket *bucket = __bucket(irq);
  128. unsigned long imap;
  129. unsigned long tid;
  130. imap = bucket->imap;
  131. if (imap == 0UL)
  132. return;
  133. if (tlb_type == cheetah || tlb_type == cheetah_plus) {
  134. /* We set it to our Safari AID. */
  135. __asm__ __volatile__("ldxa [%%g0] %1, %0"
  136.      : "=r" (tid)
  137.      : "i" (ASI_SAFARI_CONFIG));
  138. tid = ((tid & (0x3ffUL<<17)) << 9);
  139. tid &= IMAP_AID_SAFARI;
  140. } else if (this_is_starfire == 0) {
  141. /* We set it to our UPA MID. */
  142. __asm__ __volatile__("ldxa [%%g0] %1, %0"
  143.      : "=r" (tid)
  144.      : "i" (ASI_UPA_CONFIG));
  145. tid = ((tid & UPA_CONFIG_MID) << 9);
  146. tid &= IMAP_TID_UPA;
  147. } else {
  148. tid = (starfire_translate(imap, current->processor) << 26);
  149. tid &= IMAP_TID_UPA;
  150. }
  151. /* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
  152.  * of this SYSIO's preconfigured IGN in the SYSIO Control
  153.  * Register, the hardware just mirrors that value here.
  154.  * However for Graphics and UPA Slave devices the full
  155.  * IMAP_INR field can be set by the programmer here.
  156.  *
  157.  * Things like FFB can now be handled via the new IRQ mechanism.
  158.  */
  159. upa_writel(tid | IMAP_VALID, imap);
  160. }
  161. /* This now gets passed true ino's as well. */
  162. void disable_irq(unsigned int irq)
  163. {
  164. struct ino_bucket *bucket = __bucket(irq);
  165. unsigned long imap;
  166. imap = bucket->imap;
  167. if (imap != 0UL) {
  168. u32 tmp;
  169. /* NOTE: We do not want to futz with the IRQ clear registers
  170.  *       and move the state to IDLE, the SCSI code does call
  171.  *       disable_irq() to assure atomicity in the queue cmd
  172.  *       SCSI adapter driver code.  Thus we'd lose interrupts.
  173.  */
  174. tmp = upa_readl(imap);
  175. tmp &= ~IMAP_VALID;
  176. upa_writel(tmp, imap);
  177. }
  178. }
  179. /* The timer is the one "weird" interrupt which is generated by
  180.  * the CPU %tick register and not by some normal vectored interrupt
  181.  * source.  To handle this special case, we use this dummy INO bucket.
  182.  */
  183. static struct ino_bucket pil0_dummy_bucket = {
  184. 0, /* irq_chain */
  185. 0, /* pil */
  186. 0, /* pending */
  187. 0, /* flags */
  188. 0, /* __unused */
  189. NULL, /* irq_info */
  190. 0UL, /* iclr */
  191. 0UL, /* imap */
  192. };
  193. unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap)
  194. {
  195. struct ino_bucket *bucket;
  196. int ino;
  197. if(pil == 0) {
  198. if(iclr != 0UL || imap != 0UL) {
  199. prom_printf("Invalid dummy bucket for PIL0 (%lx:%lx)n",
  200.     iclr, imap);
  201. prom_halt();
  202. }
  203. return __irq(&pil0_dummy_bucket);
  204. }
  205. /* RULE: Both must be specified in all other cases. */
  206. if (iclr == 0UL || imap == 0UL) {
  207. prom_printf("Invalid build_irq %d %d %016lx %016lxn",
  208.     pil, inofixup, iclr, imap);
  209. prom_halt();
  210. }
  211. ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
  212. if(ino > NUM_IVECS) {
  213. prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)n",
  214.     ino, pil, inofixup, iclr, imap);
  215. prom_halt();
  216. }
  217. /* Ok, looks good, set it up.  Don't touch the irq_chain or
  218.  * the pending flag.
  219.  */
  220. bucket = &ivector_table[ino];
  221. if ((bucket->flags & IBF_ACTIVE) ||
  222.     (bucket->irq_info != NULL)) {
  223. /* This is a gross fatal error if it happens here. */
  224. prom_printf("IRQ: Trying to reinit INO bucket, fatal error.n");
  225. prom_printf("IRQ: Request INO %04x (%d:%d:%016lx:%016lx)n",
  226.     ino, pil, inofixup, iclr, imap);
  227. prom_printf("IRQ: Existing (%d:%016lx:%016lx)n",
  228.     bucket->pil, bucket->iclr, bucket->imap);
  229. prom_printf("IRQ: Cannot continue, halting...n");
  230. prom_halt();
  231. }
  232. bucket->imap  = imap;
  233. bucket->iclr  = iclr;
  234. bucket->pil   = pil;
  235. bucket->flags = 0;
  236. bucket->irq_info = NULL;
  237. return __irq(bucket);
  238. }
  239. static void atomic_bucket_insert(struct ino_bucket *bucket)
  240. {
  241. unsigned long pstate;
  242. unsigned int *ent;
  243. __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
  244. __asm__ __volatile__("wrpr %0, %1, %%pstate"
  245.      : : "r" (pstate), "i" (PSTATE_IE));
  246. ent = irq_work(smp_processor_id(), bucket->pil);
  247. bucket->irq_chain = *ent;
  248. *ent = __irq(bucket);
  249. __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
  250. }
  251. int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
  252. unsigned long irqflags, const char *name, void *dev_id)
  253. {
  254. struct irqaction *action, *tmp = NULL;
  255. struct ino_bucket *bucket = __bucket(irq);
  256. unsigned long flags;
  257. int pending = 0;
  258. if ((bucket != &pil0_dummy_bucket) &&
  259.     (bucket < &ivector_table[0] ||
  260.      bucket >= &ivector_table[NUM_IVECS])) {
  261. unsigned int *caller;
  262. __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
  263. printk(KERN_CRIT "request_irq: Old style IRQ registry attempt "
  264.        "from %p, irq %08x.n", caller, irq);
  265. return -EINVAL;
  266. }
  267. if(!handler)
  268.     return -EINVAL;
  269. if ((bucket != &pil0_dummy_bucket) && (irqflags & SA_SAMPLE_RANDOM)) {
  270. /*
  271.    * This function might sleep, we want to call it first,
  272.    * outside of the atomic block. In SA_STATIC_ALLOC case,
  273.  * random driver's kmalloc will fail, but it is safe.
  274.  * If already initialized, random driver will not reinit.
  275.    * Yes, this might clear the entropy pool if the wrong
  276.    * driver is attempted to be loaded, without actually
  277.    * installing a new handler, but is this really a problem,
  278.    * only the sysadmin is able to do this.
  279.    */
  280. rand_initialize_irq(irq);
  281. }
  282. save_and_cli(flags);
  283. action = *(bucket->pil + irq_action);
  284. if(action) {
  285. if((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ))
  286. for (tmp = action; tmp->next; tmp = tmp->next)
  287. ;
  288. else {
  289. restore_flags(flags);
  290. return -EBUSY;
  291. }
  292. action = NULL; /* Or else! */
  293. }
  294. /* If this is flagged as statically allocated then we use our
  295.  * private struct which is never freed.
  296.  */
  297. if(irqflags & SA_STATIC_ALLOC) {
  298.     if(static_irq_count < MAX_STATIC_ALLOC)
  299. action = &static_irqaction[static_irq_count++];
  300.     else
  301. printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed "
  302.        "using kmallocn", irq, name);
  303. }
  304. if(action == NULL)
  305.     action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
  306.  GFP_KERNEL);
  307. if(!action) { 
  308. restore_flags(flags);
  309. return -ENOMEM;
  310. }
  311. if (bucket == &pil0_dummy_bucket) {
  312. bucket->irq_info = action;
  313. bucket->flags |= IBF_ACTIVE;
  314. } else {
  315. if((bucket->flags & IBF_ACTIVE) != 0) {
  316. void *orig = bucket->irq_info;
  317. void **vector = NULL;
  318. if((bucket->flags & IBF_PCI) == 0) {
  319. printk("IRQ: Trying to share non-PCI bucket.n");
  320. goto free_and_ebusy;
  321. }
  322. if((bucket->flags & IBF_MULTI) == 0) {
  323. vector = kmalloc(sizeof(void *) * 4, GFP_KERNEL);
  324. if(vector == NULL)
  325. goto free_and_enomem;
  326. /* We might have slept. */
  327. if ((bucket->flags & IBF_MULTI) != 0) {
  328. int ent;
  329. kfree(vector);
  330. vector = (void **)bucket->irq_info;
  331. for(ent = 0; ent < 4; ent++) {
  332. if (vector[ent] == NULL) {
  333. vector[ent] = action;
  334. break;
  335. }
  336. }
  337. if (ent == 4)
  338. goto free_and_ebusy;
  339. } else {
  340. vector[0] = orig;
  341. vector[1] = action;
  342. vector[2] = NULL;
  343. vector[3] = NULL;
  344. bucket->irq_info = vector;
  345. bucket->flags |= IBF_MULTI;
  346. }
  347. } else {
  348. int ent;
  349. vector = (void **)orig;
  350. for(ent = 0; ent < 4; ent++) {
  351. if(vector[ent] == NULL) {
  352. vector[ent] = action;
  353. break;
  354. }
  355. }
  356. if (ent == 4)
  357. goto free_and_ebusy;
  358. }
  359. } else {
  360. bucket->irq_info = action;
  361. bucket->flags |= IBF_ACTIVE;
  362. }
  363. pending = bucket->pending;
  364. if(pending)
  365. bucket->pending = 0;
  366. }
  367. action->handler = handler;
  368. action->flags = irqflags;
  369. action->name = name;
  370. action->next = NULL;
  371. action->dev_id = dev_id;
  372. put_ino_in_irqaction(action, irq);
  373. put_smpaff_in_irqaction(action, 0);
  374. if(tmp)
  375. tmp->next = action;
  376. else
  377. *(bucket->pil + irq_action) = action;
  378. enable_irq(irq);
  379. /* We ate the IVEC already, this makes sure it does not get lost. */
  380. if(pending) {
  381. atomic_bucket_insert(bucket);
  382. set_softint(1 << bucket->pil);
  383. }
  384. restore_flags(flags);
  385. if ((bucket != &pil0_dummy_bucket) && (!(irqflags & SA_STATIC_ALLOC)))
  386. register_irq_proc(__irq_ino(irq));
  387. #ifdef CONFIG_SMP
  388. distribute_irqs();
  389. #endif
  390. return 0;
  391. free_and_ebusy:
  392. kfree(action);
  393. restore_flags(flags);
  394. return -EBUSY;
  395. free_and_enomem:
  396. kfree(action);
  397. restore_flags(flags);
  398. return -ENOMEM;
  399. }
  400. void free_irq(unsigned int irq, void *dev_id)
  401. {
  402. struct irqaction *action;
  403. struct irqaction *tmp = NULL;
  404. unsigned long flags;
  405. struct ino_bucket *bucket = __bucket(irq), *bp;
  406. if ((bucket != &pil0_dummy_bucket) &&
  407.     (bucket < &ivector_table[0] ||
  408.      bucket >= &ivector_table[NUM_IVECS])) {
  409. unsigned int *caller;
  410. __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
  411. printk(KERN_CRIT "free_irq: Old style IRQ removal attempt "
  412.        "from %p, irq %08x.n", caller, irq);
  413. return;
  414. }
  415. action = *(bucket->pil + irq_action);
  416. if(!action->handler) {
  417. printk("Freeing free IRQ %dn", bucket->pil);
  418. return;
  419. }
  420. if(dev_id) {
  421. for( ; action; action = action->next) {
  422. if(action->dev_id == dev_id)
  423. break;
  424. tmp = action;
  425. }
  426. if(!action) {
  427. printk("Trying to free free shared IRQ %dn", bucket->pil);
  428. return;
  429. }
  430. } else if(action->flags & SA_SHIRQ) {
  431. printk("Trying to free shared IRQ %d with NULL device IDn", bucket->pil);
  432. return;
  433. }
  434. if(action->flags & SA_STATIC_ALLOC) {
  435. printk("Attempt to free statically allocated IRQ %d (%s)n",
  436.        bucket->pil, action->name);
  437. return;
  438. }
  439. save_and_cli(flags);
  440. if(action && tmp)
  441. tmp->next = action->next;
  442. else
  443. *(bucket->pil + irq_action) = action->next;
  444. if (bucket != &pil0_dummy_bucket) {
  445. unsigned long imap = bucket->imap;
  446. void **vector, *orig;
  447. int ent;
  448. orig = bucket->irq_info;
  449. vector = (void **)orig;
  450. if ((bucket->flags & IBF_MULTI) != 0) {
  451. int other = 0;
  452. void *orphan = NULL;
  453. for(ent = 0; ent < 4; ent++) {
  454. if(vector[ent] == action)
  455. vector[ent] = NULL;
  456. else if(vector[ent] != NULL) {
  457. orphan = vector[ent];
  458. other++;
  459. }
  460. }
  461. /* Only free when no other shared irq
  462.  * uses this bucket.
  463.  */
  464. if(other) {
  465. if (other == 1) {
  466. /* Convert back to non-shared bucket. */
  467. bucket->irq_info = orphan;
  468. bucket->flags &= ~(IBF_MULTI);
  469. kfree(vector);
  470. }
  471. goto out;
  472. }
  473. } else {
  474. bucket->irq_info = NULL;
  475. }
  476. /* This unique interrupt source is now inactive. */
  477. bucket->flags &= ~IBF_ACTIVE;
  478. /* See if any other buckets share this bucket's IMAP
  479.  * and are still active.
  480.  */
  481. for(ent = 0; ent < NUM_IVECS; ent++) {
  482. bp = &ivector_table[ent];
  483. if(bp != bucket &&
  484.    bp->imap == imap &&
  485.    (bp->flags & IBF_ACTIVE) != 0)
  486. break;
  487. }
  488. /* Only disable when no other sub-irq levels of
  489.  * the same IMAP are active.
  490.  */
  491. if (ent == NUM_IVECS)
  492. disable_irq(irq);
  493. }
  494. out:
  495. kfree(action);
  496. restore_flags(flags);
  497. }
  498. #ifdef CONFIG_SMP
  499. /* Who has the global irq brlock */
  500. unsigned char global_irq_holder = NO_PROC_ID;
  501. static void show(char * str)
  502. {
  503. int cpu = smp_processor_id();
  504. int i;
  505. printk("n%s, CPU %d:n", str, cpu);
  506. printk("irq:  %d [ ", irqs_running());
  507. for (i = 0; i < smp_num_cpus; i++)
  508. printk("%u ", __brlock_array[i][BR_GLOBALIRQ_LOCK]);
  509. printk("]nbh:   %d [ ",
  510.        (spin_is_locked(&global_bh_lock) ? 1 : 0));
  511. for (i = 0; i < smp_num_cpus; i++)
  512. printk("%u ", local_bh_count(i));
  513. printk("]n");
  514. }
  515. #define MAXCOUNT 100000000
  516. #if 0
  517. #define SYNC_OTHER_ULTRAS(x) udelay(x+1)
  518. #else
  519. #define SYNC_OTHER_ULTRAS(x) membar("#Sync");
  520. #endif
  521. void synchronize_irq(void)
  522. {
  523. if (irqs_running()) {
  524. cli();
  525. sti();
  526. }
  527. }
  528. static inline void get_irqlock(int cpu)
  529. {
  530. int count;
  531. if ((unsigned char)cpu == global_irq_holder)
  532. return;
  533. count = MAXCOUNT;
  534. again:
  535. br_write_lock(BR_GLOBALIRQ_LOCK);
  536. for (;;) {
  537. spinlock_t *lock;
  538. if (!irqs_running() &&
  539.     (local_bh_count(smp_processor_id()) || !spin_is_locked(&global_bh_lock)))
  540. break;
  541. br_write_unlock(BR_GLOBALIRQ_LOCK);
  542. lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock;
  543. while (irqs_running() ||
  544.        spin_is_locked(lock) ||
  545.        (!local_bh_count(smp_processor_id()) && spin_is_locked(&global_bh_lock))) {
  546. if (!--count) {
  547. show("get_irqlock");
  548. count = (~0 >> 1);
  549. }
  550. __sti();
  551. SYNC_OTHER_ULTRAS(cpu);
  552. __cli();
  553. }
  554. goto again;
  555. }
  556. global_irq_holder = cpu;
  557. }
  558. void __global_cli(void)
  559. {
  560. unsigned long flags;
  561. __save_flags(flags);
  562. if(flags == 0) {
  563. int cpu = smp_processor_id();
  564. __cli();
  565. if (! local_irq_count(cpu))
  566. get_irqlock(cpu);
  567. }
  568. }
  569. void __global_sti(void)
  570. {
  571. int cpu = smp_processor_id();
  572. if (! local_irq_count(cpu))
  573. release_irqlock(cpu);
  574. __sti();
  575. }
  576. unsigned long __global_save_flags(void)
  577. {
  578. unsigned long flags, local_enabled, retval;
  579. __save_flags(flags);
  580. local_enabled = ((flags == 0) ? 1 : 0);
  581. retval = 2 + local_enabled;
  582. if (! local_irq_count(smp_processor_id())) {
  583. if (local_enabled)
  584. retval = 1;
  585. if (global_irq_holder == (unsigned char) smp_processor_id())
  586. retval = 0;
  587. }
  588. return retval;
  589. }
  590. void __global_restore_flags(unsigned long flags)
  591. {
  592. switch (flags) {
  593. case 0:
  594. __global_cli();
  595. break;
  596. case 1:
  597. __global_sti();
  598. break;
  599. case 2:
  600. __cli();
  601. break;
  602. case 3:
  603. __sti();
  604. break;
  605. default:
  606. {
  607. unsigned long pc;
  608. __asm__ __volatile__("mov %%i7, %0" : "=r" (pc));
  609. printk("global_restore_flags: Bogon flags(%016lx) caller %016lxn",
  610.        flags, pc);
  611. }
  612. }
  613. }
  614. #endif /* CONFIG_SMP */
  615. void catch_disabled_ivec(struct pt_regs *regs)
  616. {
  617. int cpu = smp_processor_id();
  618. struct ino_bucket *bucket = __bucket(*irq_work(cpu, 0));
  619. /* We can actually see this on Ultra/PCI PCI cards, which are bridges
  620.  * to other devices.  Here a single IMAP enabled potentially multiple
  621.  * unique interrupt sources (which each do have a unique ICLR register.
  622.  *
  623.  * So what we do is just register that the IVEC arrived, when registered
  624.  * for real the request_irq() code will check the bit and signal
  625.  * a local CPU interrupt for it.
  626.  */
  627. #if 0
  628. printk("IVEC: Spurious interrupt vector (%x) received at (%016lx)n",
  629.        bucket - &ivector_table[0], regs->tpc);
  630. #endif
  631. *irq_work(cpu, 0) = 0;
  632. bucket->pending = 1;
  633. }
  634. /* Tune this... */
  635. #define FORWARD_VOLUME 12
  636. #ifdef CONFIG_SMP
  637. static inline void redirect_intr(int cpu, struct ino_bucket *bp)
  638. {
  639. /* Ok, here is what is going on:
  640.  * 1) Retargeting IRQs on Starfire is very
  641.  *    expensive so just forget about it on them.
  642.  * 2) Moving around very high priority interrupts
  643.  *    is a losing game.
  644.  * 3) If the current cpu is idle, interrupts are
  645.  *    useful work, so keep them here.  But do not
  646.  *    pass to our neighbour if he is not very idle.
  647.  * 4) If sysadmin explicitly asks for directed intrs,
  648.  *    Just Do It.
  649.  */
  650. struct irqaction *ap = bp->irq_info;
  651. unsigned long cpu_mask = get_smpaff_in_irqaction(ap);
  652. unsigned int buddy, ticks;
  653. if (cpu_mask == 0)
  654. cpu_mask = ~0UL;
  655. if (this_is_starfire != 0 ||
  656.     bp->pil >= 10 || current->pid == 0)
  657. goto out;
  658. /* 'cpu' is the MID (ie. UPAID), calculate the MID
  659.  * of our buddy.
  660.  */
  661. buddy = cpu_number_map(cpu) + 1;
  662. if (buddy >= NR_CPUS ||
  663.     cpu_logical_map(buddy) == -1)
  664. buddy = 0;
  665. ticks = 0;
  666. while ((cpu_mask & (1UL << buddy)) == 0) {
  667. buddy++;
  668. if (buddy >= NR_CPUS ||
  669.     cpu_logical_map(buddy) == -1)
  670. buddy = cpu_logical_map(0);
  671. if (++ticks > NR_CPUS) {
  672. put_smpaff_in_irqaction(ap, 0);
  673. goto out;
  674. }
  675. }
  676. if (buddy == cpu_number_map(cpu))
  677. goto out;
  678. buddy = cpu_logical_map(buddy);
  679. /* Voo-doo programming. */
  680. if (cpu_data[buddy].idle_volume < FORWARD_VOLUME)
  681. goto out;
  682. /* This just so happens to be correct on Cheetah
  683.  * at the moment.
  684.  */
  685. buddy <<= 26;
  686. /* Push it to our buddy. */
  687. upa_writel(buddy | IMAP_VALID, bp->imap);
  688. out:
  689. return;
  690. }
  691. #endif
  692. void handler_irq(int irq, struct pt_regs *regs)
  693. {
  694. struct ino_bucket *bp, *nbp;
  695. int cpu = smp_processor_id();
  696. #ifndef CONFIG_SMP
  697. /*
  698.  * Check for TICK_INT on level 14 softint.
  699.  */
  700. {
  701. unsigned long clr_mask = 1 << irq;
  702. unsigned long tick_mask;
  703. if (SPARC64_USE_STICK)
  704. tick_mask = (1UL << 16);
  705. else
  706. tick_mask = (1UL << 0);
  707. if ((irq == 14) && (get_softint() & tick_mask)) {
  708. irq = 0;
  709. clr_mask = tick_mask;
  710. }
  711. clear_softint(clr_mask);
  712. }
  713. #else
  714. int should_forward = 1;
  715. clear_softint(1 << irq);
  716. #endif
  717. irq_enter(cpu, irq);
  718. kstat.irqs[cpu][irq]++;
  719. #ifdef CONFIG_PCI
  720. if (irq == 9)
  721. kbd_pt_regs = regs;
  722. #endif
  723. /* Sliiiick... */
  724. #ifndef CONFIG_SMP
  725. bp = ((irq != 0) ?
  726.       __bucket(xchg32(irq_work(cpu, irq), 0)) :
  727.       &pil0_dummy_bucket);
  728. #else
  729. bp = __bucket(xchg32(irq_work(cpu, irq), 0));
  730. #endif
  731. for ( ; bp != NULL; bp = nbp) {
  732. unsigned char flags = bp->flags;
  733. unsigned char random = 0;
  734. nbp = __bucket(bp->irq_chain);
  735. bp->irq_chain = 0;
  736. if ((flags & IBF_ACTIVE) != 0) {
  737. #ifdef CONFIG_PCI
  738. if ((flags & IBF_DMA_SYNC) != 0) {
  739. upa_readl(dma_sync_reg_table[bp->synctab_ent]);
  740. upa_readq(pci_dma_wsync);
  741. }
  742. #endif
  743. if ((flags & IBF_MULTI) == 0) {
  744. struct irqaction *ap = bp->irq_info;
  745. ap->handler(__irq(bp), ap->dev_id, regs);
  746. random |= ap->flags & SA_SAMPLE_RANDOM;
  747. } else {
  748. void **vector = (void **)bp->irq_info;
  749. int ent;
  750. for (ent = 0; ent < 4; ent++) {
  751. struct irqaction *ap = vector[ent];
  752. if (ap != NULL) {
  753. ap->handler(__irq(bp), ap->dev_id, regs);
  754. random |= ap->flags & SA_SAMPLE_RANDOM;
  755. }
  756. }
  757. }
  758. /* Only the dummy bucket lacks IMAP/ICLR. */
  759. if (bp->pil != 0) {
  760. #ifdef CONFIG_SMP
  761. if (should_forward) {
  762. redirect_intr(cpu, bp);
  763. should_forward = 0;
  764. }
  765. #endif
  766. upa_writel(ICLR_IDLE, bp->iclr);
  767. /* Test and add entropy */
  768. if (random)
  769. add_interrupt_randomness(irq);
  770. }
  771. } else
  772. bp->pending = 1;
  773. }
  774. irq_exit(cpu, irq);
  775. }
  776. #ifdef CONFIG_BLK_DEV_FD
  777. extern void floppy_interrupt(int irq, void *dev_cookie, struct pt_regs *regs);
  778. void sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
  779. {
  780. struct irqaction *action = *(irq + irq_action);
  781. struct ino_bucket *bucket;
  782. int cpu = smp_processor_id();
  783. irq_enter(cpu, irq);
  784. kstat.irqs[cpu][irq]++;
  785. *(irq_work(cpu, irq)) = 0;
  786. bucket = get_ino_in_irqaction(action) + ivector_table;
  787. floppy_interrupt(irq, dev_cookie, regs);
  788. upa_writel(ICLR_IDLE, bucket->iclr);
  789. irq_exit(cpu, irq);
  790. }
  791. #endif
  792. /* The following assumes that the branch lies before the place we
  793.  * are branching to.  This is the case for a trap vector...
  794.  * You have been warned.
  795.  */
  796. #define SPARC_BRANCH(dest_addr, inst_addr) 
  797.           (0x10800000 | ((((dest_addr)-(inst_addr))>>2)&0x3fffff))
  798. #define SPARC_NOP (0x01000000)
  799. static void install_fast_irq(unsigned int cpu_irq,
  800.      void (*handler)(int, void *, struct pt_regs *))
  801. {
  802. extern unsigned long sparc64_ttable_tl0;
  803. unsigned long ttent = (unsigned long) &sparc64_ttable_tl0;
  804. unsigned int *insns;
  805. ttent += 0x820;
  806. ttent += (cpu_irq - 1) << 5;
  807. insns = (unsigned int *) ttent;
  808. insns[0] = SPARC_BRANCH(((unsigned long) handler),
  809. ((unsigned long)&insns[0]));
  810. insns[1] = SPARC_NOP;
  811. __asm__ __volatile__("membar #StoreStore; flush %0" : : "r" (ttent));
  812. }
  813. int request_fast_irq(unsigned int irq,
  814.      void (*handler)(int, void *, struct pt_regs *),
  815.      unsigned long irqflags, const char *name, void *dev_id)
  816. {
  817. struct irqaction *action;
  818. struct ino_bucket *bucket = __bucket(irq);
  819. unsigned long flags;
  820. /* No pil0 dummy buckets allowed here. */
  821. if (bucket < &ivector_table[0] ||
  822.     bucket >= &ivector_table[NUM_IVECS]) {
  823. unsigned int *caller;
  824. __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
  825. printk(KERN_CRIT "request_fast_irq: Old style IRQ registry attempt "
  826.        "from %p, irq %08x.n", caller, irq);
  827. return -EINVAL;
  828. }
  829. if(!handler)
  830. return -EINVAL;
  831. if ((bucket->pil == 0) || (bucket->pil == 14)) {
  832. printk("request_fast_irq: Trying to register shared IRQ 0 or 14.n");
  833. return -EBUSY;
  834. }
  835. action = *(bucket->pil + irq_action);
  836. if(action) {
  837. if(action->flags & SA_SHIRQ)
  838. panic("Trying to register fast irq when already shared.n");
  839. if(irqflags & SA_SHIRQ)
  840. panic("Trying to register fast irq as shared.n");
  841. printk("request_fast_irq: Trying to register yet already owned.n");
  842. return -EBUSY;
  843. }
  844. /*
  845.  * We do not check for SA_SAMPLE_RANDOM in this path. Neither do we
  846.  * support smp intr affinity in this path.
  847.  */
  848. save_and_cli(flags);
  849. if(irqflags & SA_STATIC_ALLOC) {
  850. if(static_irq_count < MAX_STATIC_ALLOC)
  851. action = &static_irqaction[static_irq_count++];
  852. else
  853. printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed "
  854.        "using kmallocn", bucket->pil, name);
  855. }
  856. if(action == NULL)
  857. action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
  858.      GFP_KERNEL);
  859. if(!action) {
  860. restore_flags(flags);
  861. return -ENOMEM;
  862. }
  863. install_fast_irq(bucket->pil, handler);
  864. bucket->irq_info = action;
  865. bucket->flags |= IBF_ACTIVE;
  866. action->handler = handler;
  867. action->flags = irqflags;
  868. action->dev_id = NULL;
  869. action->name = name;
  870. action->next = NULL;
  871. put_ino_in_irqaction(action, irq);
  872. put_smpaff_in_irqaction(action, 0);
  873. *(bucket->pil + irq_action) = action;
  874. enable_irq(irq);
  875. restore_flags(flags);
  876. #ifdef CONFIG_SMP
  877. distribute_irqs();
  878. #endif
  879. return 0;
  880. }
  881. /* We really don't need these at all on the Sparc.  We only have
  882.  * stubs here because they are exported to modules.
  883.  */
  884. unsigned long probe_irq_on(void)
  885. {
  886. return 0;
  887. }
  888. int probe_irq_off(unsigned long mask)
  889. {
  890. return 0;
  891. }
  892. /* This is gets the master TICK_INT timer going. */
  893. void init_timers(void (*cfunc)(int, void *, struct pt_regs *),
  894.  unsigned long *clock)
  895. {
  896. unsigned long pstate;
  897. extern unsigned long timer_tick_offset;
  898. int node, err;
  899. #ifdef CONFIG_SMP
  900. extern void smp_tick_init(void);
  901. #endif
  902. if (!SPARC64_USE_STICK) {
  903. node = linux_cpus[0].prom_node;
  904. *clock = prom_getint(node, "clock-frequency");
  905. } else {
  906. node = prom_root_node;
  907. *clock = prom_getint(node, "stick-frequency");
  908. }
  909. timer_tick_offset = *clock / HZ;
  910. #ifdef CONFIG_SMP
  911. smp_tick_init();
  912. #endif
  913. /* Register IRQ handler. */
  914. err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, SA_STATIC_ALLOC,
  915.   "timer", NULL);
  916. if(err) {
  917. prom_printf("Serious problem, cannot register TICK_INTn");
  918. prom_halt();
  919. }
  920. /* Guarentee that the following sequences execute
  921.  * uninterrupted.
  922.  */
  923. __asm__ __volatile__("rdpr %%pstate, %0nt"
  924.      "wrpr %0, %1, %%pstate"
  925.      : "=r" (pstate)
  926.      : "i" (PSTATE_IE));
  927. /* Set things up so user can access tick register for profiling
  928.  * purposes.  Also workaround BB_ERRATA_1 by doing a dummy
  929.  * read back of %tick after writing it.
  930.  */
  931. __asm__ __volatile__(
  932. " sethi %%hi(0x80000000), %%g1n"
  933. " ba,pt %%xcc, 1fn"
  934. "  sllx %%g1, 32, %%g1n"
  935. " .align 64n"
  936. "1: rd %%tick, %%g2n"
  937. " add %%g2, 6, %%g2n"
  938. " andn %%g2, %%g1, %%g2n"
  939. " wrpr %%g2, 0, %%tickn"
  940. " rdpr %%tick, %%g0"
  941. : /* no outputs */
  942. : /* no inputs */
  943. : "g1", "g2");
  944. /* Workaround for Spitfire Errata (#54 I think??), I discovered
  945.  * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch
  946.  * number 103640.
  947.  *
  948.  * On Blackbird writes to %tick_cmpr can fail, the
  949.  * workaround seems to be to execute the wr instruction
  950.  * at the start of an I-cache line, and perform a dummy
  951.  * read back from %tick_cmpr right after writing to it. -DaveM
  952.  */
  953. if (!SPARC64_USE_STICK) {
  954. __asm__ __volatile__(
  955. " rd %%tick, %%g1n"
  956. " ba,pt %%xcc, 1fn"
  957. "  add %%g1, %0, %%g1n"
  958. " .align 64n"
  959. "1: wr %%g1, 0x0, %%tick_cmprn"
  960. " rd %%tick_cmpr, %%g0"
  961. : /* no outputs */
  962. : "r" (timer_tick_offset)
  963. : "g1");
  964. } else {
  965. /* Let the user get at STICK too. */
  966. __asm__ __volatile__(
  967. " sethi %%hi(0x80000000), %%g1n"
  968. " sllx %%g1, 32, %%g1n"
  969. " rd %%asr24, %%g2n"
  970. " andn %%g2, %%g1, %%g2n"
  971. " wr %%g2, 0, %%asr24"
  972. : /* no outputs */
  973. : /* no inputs */
  974. : "g1", "g2");
  975. __asm__ __volatile__(
  976. " rd %%asr24, %%g1n"
  977. " add %%g1, %0, %%g1n"
  978. " wr %%g1, 0x0, %%asr25"
  979. : /* no outputs */
  980. : "r" (timer_tick_offset)
  981. : "g1");
  982. }
  983. /* Restore PSTATE_IE. */
  984. __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
  985.      : /* no outputs */
  986.      : "r" (pstate));
  987. sti();
  988. }
  989. #ifdef CONFIG_SMP
  990. static int retarget_one_irq(struct irqaction *p, int goal_cpu)
  991. {
  992. struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table;
  993. unsigned long imap = bucket->imap;
  994. unsigned int tid;
  995. if (tlb_type == cheetah || tlb_type == cheetah_plus) {
  996. tid = __cpu_logical_map[goal_cpu] << 26;
  997. tid &= IMAP_AID_SAFARI;
  998. } else if (this_is_starfire == 0) {
  999. tid = __cpu_logical_map[goal_cpu] << 26;
  1000. tid &= IMAP_TID_UPA;
  1001. } else {
  1002. tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26);
  1003. tid &= IMAP_TID_UPA;
  1004. }
  1005. upa_writel(tid | IMAP_VALID, imap);
  1006. goal_cpu++;
  1007. if(goal_cpu >= NR_CPUS ||
  1008.    __cpu_logical_map[goal_cpu] == -1)
  1009. goal_cpu = 0;
  1010. return goal_cpu;
  1011. }
  1012. /* Called from request_irq. */
  1013. static void distribute_irqs(void)
  1014. {
  1015. unsigned long flags;
  1016. int cpu, level;
  1017. save_and_cli(flags);
  1018. cpu = 0;
  1019. /*
  1020.  * Skip the timer at [0], and very rare error/power intrs at [15].
  1021.  * Also level [12], it causes problems on Ex000 systems.
  1022.  */
  1023. for(level = 1; level < NR_IRQS; level++) {
  1024. struct irqaction *p = irq_action[level];
  1025. if (level == 12) continue;
  1026. while(p) {
  1027. cpu = retarget_one_irq(p, cpu);
  1028. p = p->next;
  1029. }
  1030. }
  1031. restore_flags(flags);
  1032. }
  1033. #endif
  1034. struct sun5_timer *prom_timers;
  1035. static u64 prom_limit0, prom_limit1;
  1036. static void map_prom_timers(void)
  1037. {
  1038. unsigned int addr[3];
  1039. int tnode, err;
  1040. /* PROM timer node hangs out in the top level of device siblings... */
  1041. tnode = prom_finddevice("/counter-timer");
  1042. /* Assume if node is not present, PROM uses different tick mechanism
  1043.  * which we should not care about.
  1044.  */
  1045. if(tnode == 0 || tnode == -1) {
  1046. prom_timers = (struct sun5_timer *) 0;
  1047. return;
  1048. }
  1049. /* If PROM is really using this, it must be mapped by him. */
  1050. err = prom_getproperty(tnode, "address", (char *)addr, sizeof(addr));
  1051. if(err == -1) {
  1052. prom_printf("PROM does not have timer mapped, trying to continue.n");
  1053. prom_timers = (struct sun5_timer *) 0;
  1054. return;
  1055. }
  1056. prom_timers = (struct sun5_timer *) ((unsigned long)addr[0]);
  1057. }
  1058. static void kill_prom_timer(void)
  1059. {
  1060. if(!prom_timers)
  1061. return;
  1062. /* Save them away for later. */
  1063. prom_limit0 = prom_timers->limit0;
  1064. prom_limit1 = prom_timers->limit1;
  1065. /* Just as in sun4c/sun4m PROM uses timer which ticks at IRQ 14.
  1066.  * We turn both off here just to be paranoid.
  1067.  */
  1068. prom_timers->limit0 = 0;
  1069. prom_timers->limit1 = 0;
  1070. /* Wheee, eat the interrupt packet too... */
  1071. __asm__ __volatile__(
  1072. " mov 0x40, %%g2n"
  1073. " ldxa [%%g0] %0, %%g1n"
  1074. " ldxa [%%g2] %1, %%g1n"
  1075. " stxa %%g0, [%%g0] %0n"
  1076. " membar #Syncn"
  1077. : /* no outputs */
  1078. : "i" (ASI_INTR_RECEIVE), "i" (ASI_INTR_R)
  1079. : "g1", "g2");
  1080. }
  1081. void enable_prom_timer(void)
  1082. {
  1083. if(!prom_timers)
  1084. return;
  1085. /* Set it to whatever was there before. */
  1086. prom_timers->limit1 = prom_limit1;
  1087. prom_timers->count1 = 0;
  1088. prom_timers->limit0 = prom_limit0;
  1089. prom_timers->count0 = 0;
  1090. }
  1091. void __init init_IRQ(void)
  1092. {
  1093. static int called = 0;
  1094. if (called == 0) {
  1095. called = 1;
  1096. map_prom_timers();
  1097. kill_prom_timer();
  1098. memset(&ivector_table[0], 0, sizeof(ivector_table));
  1099. #ifndef CONFIG_SMP
  1100. memset(&__up_workvec[0], 0, sizeof(__up_workvec));
  1101. #endif
  1102. }
  1103. /* We need to clear any IRQ's pending in the soft interrupt
  1104.  * registers, a spurious one could be left around from the
  1105.  * PROM timer which we just disabled.
  1106.  */
  1107. clear_softint(get_softint());
  1108. /* Now that ivector table is initialized, it is safe
  1109.  * to receive IRQ vector traps.  We will normally take
  1110.  * one or two right now, in case some device PROM used
  1111.  * to boot us wants to speak to us.  We just ignore them.
  1112.  */
  1113. __asm__ __volatile__("rdpr %%pstate, %%g1nt"
  1114.      "or %%g1, %0, %%g1nt"
  1115.      "wrpr %%g1, 0x0, %%pstate"
  1116.      : /* No outputs */
  1117.      : "i" (PSTATE_IE)
  1118.      : "g1");
  1119. }
  1120. static struct proc_dir_entry * root_irq_dir;
  1121. static struct proc_dir_entry * irq_dir [NUM_IVECS];
  1122. #ifdef CONFIG_SMP
  1123. #define HEX_DIGITS 16
  1124. static unsigned int parse_hex_value (const char *buffer,
  1125. unsigned long count, unsigned long *ret)
  1126. {
  1127. unsigned char hexnum [HEX_DIGITS];
  1128. unsigned long value;
  1129. int i;
  1130. if (!count)
  1131. return -EINVAL;
  1132. if (count > HEX_DIGITS)
  1133. count = HEX_DIGITS;
  1134. if (copy_from_user(hexnum, buffer, count))
  1135. return -EFAULT;
  1136. /*
  1137.  * Parse the first 8 characters as a hex string, any non-hex char
  1138.  * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
  1139.  */
  1140. value = 0;
  1141. for (i = 0; i < count; i++) {
  1142. unsigned int c = hexnum[i];
  1143. switch (c) {
  1144. case '0' ... '9': c -= '0'; break;
  1145. case 'a' ... 'f': c -= 'a'-10; break;
  1146. case 'A' ... 'F': c -= 'A'-10; break;
  1147. default:
  1148. goto out;
  1149. }
  1150. value = (value << 4) | c;
  1151. }
  1152. out:
  1153. *ret = value;
  1154. return 0;
  1155. }
  1156. static unsigned long hw_to_logical(unsigned long mask)
  1157. {
  1158. unsigned long new_mask = 0UL;
  1159. int i;
  1160. for (i = 0; i < NR_CPUS; i++) {
  1161. if (mask & (1UL << i)) {
  1162. int logical = cpu_number_map(i);
  1163. new_mask |= (1UL << logical);
  1164. }
  1165. }
  1166. return new_mask;
  1167. }
  1168. static unsigned long logical_to_hw(unsigned long mask)
  1169. {
  1170. unsigned long new_mask = 0UL;
  1171. int i;
  1172. for (i = 0; i < NR_CPUS; i++) {
  1173. if (mask & (1UL << i)) {
  1174. int hw = cpu_logical_map(i);
  1175. new_mask |= (1UL << hw);
  1176. }
  1177. }
  1178. return new_mask;
  1179. }
  1180. static int irq_affinity_read_proc (char *page, char **start, off_t off,
  1181. int count, int *eof, void *data)
  1182. {
  1183. struct ino_bucket *bp = ivector_table + (long)data;
  1184. struct irqaction *ap = bp->irq_info;
  1185. unsigned long mask = get_smpaff_in_irqaction(ap);
  1186. mask = logical_to_hw(mask);
  1187. if (count < HEX_DIGITS+1)
  1188. return -EINVAL;
  1189. return sprintf (page, "%016lxn", mask == 0 ? ~0UL : mask);
  1190. }
  1191. static inline void set_intr_affinity(int irq, unsigned long hw_aff)
  1192. {
  1193. struct ino_bucket *bp = ivector_table + irq;
  1194. unsigned long aff = hw_to_logical(hw_aff);
  1195. /*
  1196.  * Users specify affinity in terms of cpu ids, which is what
  1197.  * is displayed via /proc/cpuinfo. As soon as we do this, 
  1198.  * handler_irq() might see and take action.
  1199.  */
  1200. put_smpaff_in_irqaction((struct irqaction *)bp->irq_info, aff);
  1201. /* Migration is simply done by the next cpu to service this
  1202.  * interrupt.
  1203.  */
  1204. }
  1205. static int irq_affinity_write_proc (struct file *file, const char *buffer,
  1206. unsigned long count, void *data)
  1207. {
  1208. int irq = (long) data, full_count = count, err;
  1209. unsigned long new_value;
  1210. err = parse_hex_value(buffer, count, &new_value);
  1211. /*
  1212.  * Do not allow disabling IRQs completely - it's a too easy
  1213.  * way to make the system unusable accidentally :-) At least
  1214.  * one online CPU still has to be targeted.
  1215.  */
  1216. new_value &= cpu_online_map;
  1217. if (!new_value)
  1218. return -EINVAL;
  1219. set_intr_affinity(irq, new_value);
  1220. return full_count;
  1221. }
  1222. #endif
  1223. #define MAX_NAMELEN 10
  1224. static void register_irq_proc (unsigned int irq)
  1225. {
  1226. char name [MAX_NAMELEN];
  1227. if (!root_irq_dir || irq_dir[irq])
  1228. return;
  1229. memset(name, 0, MAX_NAMELEN);
  1230. sprintf(name, "%x", irq);
  1231. /* create /proc/irq/1234 */
  1232. irq_dir[irq] = proc_mkdir(name, root_irq_dir);
  1233. #ifdef CONFIG_SMP
  1234. /* XXX SMP affinity not supported on starfire yet. */
  1235. if (this_is_starfire == 0) {
  1236. struct proc_dir_entry *entry;
  1237. /* create /proc/irq/1234/smp_affinity */
  1238. entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
  1239. if (entry) {
  1240. entry->nlink = 1;
  1241. entry->data = (void *)(long)irq;
  1242. entry->read_proc = irq_affinity_read_proc;
  1243. entry->write_proc = irq_affinity_write_proc;
  1244. }
  1245. }
  1246. #endif
  1247. }
  1248. void init_irq_proc (void)
  1249. {
  1250. /* create /proc/irq */
  1251. root_irq_dir = proc_mkdir("irq", 0);
  1252. }