📄 adeos-ipipe-2.6.14-i386-1.2-01.patch
字号:
++ if (test_bit(IPIPE_STALL_FLAG,+ &next_domain->cpudata[cpuid].status))+ break;++ if (next_domain->cpudata[cpuid].irq_pending_hi == 0)+ continue;++ ipipe_percpu_domain[cpuid] = next_domain;++sync_stage:++ __ipipe_sync_stage(IPIPE_IRQMASK_ANY);++ ipipe_load_cpuid(); /* Processor might have changed. */++ if (ipipe_percpu_domain[cpuid] != next_domain)+ /*+ * Something has changed the current domain under our+ * feet, recycling the register set; take note.+ */+ this_domain = ipipe_percpu_domain[cpuid];+ }++ ipipe_percpu_domain[cpuid] = this_domain;++ ipipe_unlock_cpu(flags);+}++/* ipipe_alloc_virq() -- Allocate a pipelined virtual/soft interrupt.+ * Virtual interrupts are handled in exactly the same way than their+ * hw-generated counterparts wrt pipelining.+ */+unsigned ipipe_alloc_virq(void)+{+ unsigned long flags, irq = 0;+ int ipos;++ spin_lock_irqsave_hw(&__ipipe_pipelock, flags);++ if (__ipipe_virtual_irq_map != ~0) {+ ipos = ffz(__ipipe_virtual_irq_map);+ set_bit(ipos, &__ipipe_virtual_irq_map);+ irq = ipos + IPIPE_VIRQ_BASE;+ }++ spin_unlock_irqrestore_hw(&__ipipe_pipelock, flags);++ return irq;+}++/* ipipe_virtualize_irq() -- Attach a handler (and optionally a hw+ acknowledge routine) to an interrupt for a given domain. */++int ipipe_virtualize_irq(struct ipipe_domain *ipd,+ unsigned irq,+ ipipe_irq_handler_t handler,+ void *cookie,+ ipipe_irq_ackfn_t acknowledge,+ unsigned modemask)+{+ unsigned long flags;+ int err;++ if (irq >= IPIPE_NR_IRQS)+ return -EINVAL;++ if (ipd->irqs[irq].control & IPIPE_SYSTEM_MASK)+ return -EPERM;++ spin_lock_irqsave_hw(&__ipipe_pipelock, flags);++ if (handler != NULL) {++ if (handler == IPIPE_SAME_HANDLER) {+ handler = ipd->irqs[irq].handler;+ cookie = ipd->irqs[irq].cookie;++ if (handler == NULL) {+ err = -EINVAL;+ goto unlock_and_exit;+ }+ } else if ((modemask & IPIPE_EXCLUSIVE_MASK) != 0 &&+ ipd->irqs[irq].handler != NULL) {+ err = -EBUSY;+ goto unlock_and_exit;+ }++ if ((modemask & (IPIPE_SHARED_MASK | IPIPE_PASS_MASK)) ==+ IPIPE_SHARED_MASK) {+ err = -EINVAL;+ goto unlock_and_exit;+ }++ if ((modemask & IPIPE_STICKY_MASK) != 0)+ modemask |= IPIPE_HANDLE_MASK;+ } else+ modemask &=+ ~(IPIPE_HANDLE_MASK | IPIPE_STICKY_MASK |+ IPIPE_SHARED_MASK);++ if (acknowledge == NULL) {+ if ((modemask & IPIPE_SHARED_MASK) == 0)+ /* Acknowledge handler unspecified -- this is ok in+ non-shared management mode, but we will force the use+ of the Linux-defined handler instead. */+ acknowledge = ipipe_root_domain->irqs[irq].acknowledge;+ else {+ /* A valid acknowledge handler to be called in shared mode+ is required when declaring a shared IRQ. */+ err = -EINVAL;+ goto unlock_and_exit;+ }+ }++ ipd->irqs[irq].handler = handler;+ ipd->irqs[irq].cookie = cookie;+ ipd->irqs[irq].acknowledge = acknowledge;+ ipd->irqs[irq].control = modemask;++ if (irq < NR_IRQS &&+ handler != NULL &&+ !ipipe_virtual_irq_p(irq) && (modemask & IPIPE_ENABLE_MASK) != 0) {+ if (ipd != ipipe_current_domain) {+ /* IRQ enable/disable state is domain-sensitive, so we may+ not change it for another domain. What is allowed+ however is forcing some domain to handle an interrupt+ source, by passing the proper 'ipd' descriptor which+ thus may be different from ipipe_current_domain. */+ err = -EPERM;+ goto unlock_and_exit;+ }++ __ipipe_enable_irq(irq);+ }++ err = 0;++ unlock_and_exit:++ spin_unlock_irqrestore_hw(&__ipipe_pipelock, flags);++ return err;+}++/* ipipe_control_irq() -- Change modes of a pipelined interrupt for+ * the current domain. */++int ipipe_control_irq(unsigned irq, unsigned clrmask, unsigned setmask)+{+ struct ipipe_domain *ipd;+ unsigned long flags;++ if (irq >= IPIPE_NR_IRQS)+ return -EINVAL;++ ipd = ipipe_current_domain;++ if (ipd->irqs[irq].control & IPIPE_SYSTEM_MASK)+ return -EPERM;++ if (((setmask | clrmask) & IPIPE_SHARED_MASK) != 0)+ return -EINVAL;++ if (ipd->irqs[irq].handler == NULL)+ setmask &= ~(IPIPE_HANDLE_MASK | IPIPE_STICKY_MASK);++ if ((setmask & IPIPE_STICKY_MASK) != 0)+ setmask |= IPIPE_HANDLE_MASK;++ if ((clrmask & (IPIPE_HANDLE_MASK | IPIPE_STICKY_MASK)) != 0) /* If one goes, both go. */+ clrmask |= (IPIPE_HANDLE_MASK | IPIPE_STICKY_MASK);++ spin_lock_irqsave_hw(&__ipipe_pipelock, flags);++ ipd->irqs[irq].control &= ~clrmask;+ ipd->irqs[irq].control |= setmask;++ if ((setmask & IPIPE_ENABLE_MASK) != 0)+ __ipipe_enable_irq(irq);+ else if ((clrmask & IPIPE_ENABLE_MASK) != 0)+ __ipipe_disable_irq(irq);++ spin_unlock_irqrestore_hw(&__ipipe_pipelock, flags);++ return 0;+}++/* __ipipe_dispatch_event() -- Low-level event dispatcher. */++int fastcall __ipipe_dispatch_event (unsigned event, void *data)+{+ struct ipipe_domain *start_domain, *this_domain, *next_domain;+ struct list_head *pos, *npos;+ unsigned long flags;+ ipipe_declare_cpuid;+ int propagate = 1;++ ipipe_lock_cpu(flags);++ start_domain = this_domain = ipipe_percpu_domain[cpuid];++ list_for_each_safe(pos,npos,&__ipipe_pipeline) {++ next_domain = list_entry(pos,struct ipipe_domain,p_link);++ /*+ * Note: Domain migration may occur while running+ * event or interrupt handlers, in which case the+ * current register set is going to be recycled for a+ * different domain than the initiating one. We do+ * care for that, always tracking the current domain+ * descriptor upon return from those handlers.+ */+ if (next_domain->evhand[event] != NULL) {+ ipipe_percpu_domain[cpuid] = next_domain;+ ipipe_unlock_cpu(flags);+ propagate = !next_domain->evhand[event](event,start_domain,data);+ ipipe_lock_cpu(flags);+ if (ipipe_percpu_domain[cpuid] != next_domain)+ this_domain = ipipe_percpu_domain[cpuid];+ }++ if (next_domain != ipipe_root_domain && /* NEVER sync the root stage here. */+ next_domain->cpudata[cpuid].irq_pending_hi != 0 &&+ !test_bit(IPIPE_STALL_FLAG,&next_domain->cpudata[cpuid].status)) {+ ipipe_percpu_domain[cpuid] = next_domain;+ __ipipe_sync_stage(IPIPE_IRQMASK_ANY);+ ipipe_load_cpuid();+ if (ipipe_percpu_domain[cpuid] != next_domain)+ this_domain = ipipe_percpu_domain[cpuid];+ }++ ipipe_percpu_domain[cpuid] = this_domain;++ if (next_domain == this_domain || !propagate)+ break;+ }++ ipipe_unlock_cpu(flags);++ return !propagate;+}++#ifdef CONFIG_PROC_FS++#include <linux/proc_fs.h>++struct proc_dir_entry *ipipe_proc_root;++static int __ipipe_version_info_proc(char *page,+ char **start,+ off_t off, int count, int *eof, void *data)+{+ int len = sprintf(page, "%s\n", IPIPE_VERSION_STRING);++ len -= off;++ if (len <= off + count)+ *eof = 1;++ *start = page + off;++ if(len > count)+ len = count;++ if(len < 0)+ len = 0;++ return len;+}++static int __ipipe_common_info_proc(char *page,+ char **start,+ off_t off, int count, int *eof, void *data)+{+ struct ipipe_domain *ipd = (struct ipipe_domain *)data;+ unsigned long ctlbits;+ unsigned irq, _irq;+ char *p = page;+ int len;++ spin_lock(&__ipipe_pipelock);++ p += sprintf(p, "Priority=%d, Id=0x%.8x\n",+ ipd->priority, ipd->domid);+ irq = 0;++ while (irq < IPIPE_NR_IRQS) {+ ctlbits =+ (ipd->irqs[irq].+ control & (IPIPE_HANDLE_MASK | IPIPE_PASS_MASK |+ IPIPE_STICKY_MASK));+ if (irq >= IPIPE_NR_XIRQS && !ipipe_virtual_irq_p(irq)) {+ /*+ * There might be a hole between the last external+ * IRQ and the first virtual one; skip it.+ */+ irq++;+ continue;+ }++ if (ipipe_virtual_irq_p(irq)+ && !test_bit(irq - IPIPE_VIRQ_BASE,+ &__ipipe_virtual_irq_map)) {+ /* Non-allocated virtual IRQ; skip it. */+ irq++;+ continue;+ }++ /*+ * Attempt to group consecutive IRQ numbers having the+ * same virtualization settings in a single line.+ */++ _irq = irq;++ while (++_irq < IPIPE_NR_IRQS) {+ if (ipipe_virtual_irq_p(_irq) !=+ ipipe_virtual_irq_p(irq)+ || (ipipe_virtual_irq_p(_irq)+ && !test_bit(_irq - IPIPE_VIRQ_BASE,+ &__ipipe_virtual_irq_map))+ || ctlbits != (ipd->irqs[_irq].+ control & (IPIPE_HANDLE_MASK |+ IPIPE_PASS_MASK |+ IPIPE_STICKY_MASK)))+ break;+ }++ if (_irq == irq + 1)+ p += sprintf(p, "irq%u: ", irq);+ else+ p += sprintf(p, "irq%u-%u: ", irq, _irq - 1);++ /*+ * Statuses are as follows:+ * o "accepted" means handled _and_ passed down the pipeline.+ * o "grabbed" means handled, but the interrupt might be+ * terminated _or_ passed down the pipeline depending on+ * what the domain handler asks for to the I-pipe.+ * o "passed" means unhandled by the domain but passed+ * down the pipeline.+ * o "discarded" means unhandled and _not_ passed down the+ * pipeline. The interrupt merely disappears from the+ * current domain down to the end of the pipeline.+ */+ if (ctlbits & IPIPE_HANDLE_MASK) {+ if (ctlbits & IPIPE_PASS_MASK)+ p += sprintf(p, "accepted");+ else+ p += sprintf(p, "grabbed");+ } else if (ctlbits & IPIPE_PASS_MASK)+ p += sprintf(p, "passed");+ else+ p += sprintf(p, "discarded");++ if (ctlbits & IPIPE_STICKY_MASK)+ p += sprintf(p, ", sticky");++ if (ipipe_virtual_irq_p(irq))+ p += sprintf(p, ", virtual");++ p += sprintf(p, "\n");++ irq = _irq;+ }++ spin_unlock(&__ipipe_pipelock);++ len = p - page;++ if (len <= off + count)+ *eof = 1;++ *start = page + off;++ len -= off;++ if (len > count)+ len = count;++ if (len < 0)+ len = 0;++ return len;+}++#ifdef CONFIG_IPIPE_STATS++static int __ipipe_stat_info_proc(char *page,+ char **start,+ off_t off, int count, int *eof, void *data)+{+ struct ipipe_domain *ipd = (struct ipipe_domain *)data;+ int len = 0, cpu, irq;+ char *p = page;++ p += sprintf(p,"> STALL TIME:\n");++ for_each_online_cpu(cpu) {+ unsigned long eip = ipd->stats[cpu].max_stall_eip;+ char namebuf[KSYM_NAME_LEN+1];+ unsigned long offset, size, t;+ const char *name;+ char *modname;++ name = kallsyms_lookup(eip, &size, &offset, &modname, namebuf);+ t = ipipe_tsc2ns(ipd->stats[cpu].max_stall_time);++ if (name) {+ if (modname)+ p += sprintf(p,"CPU%d %12lu (%s+%#lx [%s])\n",+ cpu,t,name,offset,modname);+ else+ p += sprintf(p,"CPU%d %12lu (%s+%#lx)\n",+ cpu,t,name,offset);+ }+ else+ p += sprintf(p,"CPU%d %12lu (%lx)\n",+ cpu,t,eip);+ }++ p += sprintf(p,"> PROPAGATION TIME:\nIRQ");++ for_each_online_cpu(cpu) {+ p += sprintf(p," CPU%d",cpu);+ }++ for (irq = 0; irq < IPIPE_NR_IRQS; irq++) {++ unsigned long long t = 0;++ for_each_online_cpu(cpu) {+ t += ipd->stats[cpu].irq_stats[irq].max_delivery_time;+ }++ if (!t)+ continue;++ p += sprintf(p,"\n%3d:",irq);++ for_each_online_cpu(cpu) {+ p += sprintf(p,"%13lu",+ ipipe_tsc2ns(ipd->stats[cpu].irq_stats[irq].max_delivery_time));+ }+ }++ p += sprintf(p,"\n");++ len = p - page - off;+ if (len <= off + count) *eof = 1;+ *start = page + off;+ if (len > count) len = count;+ if (len < 0) len = 0;++ return len;+}++#endif /* CONFIG_IPIPE_STATS */++void __ipipe_add_domain_proc(struct ipipe_domain *ipd)+{++ create_proc_read_entry(ipd->name,0444,ipipe_proc_root,&__ipipe_common_info_proc,ipd);+#ifdef CONFIG_IPIPE_STATS+ {+ char name[64];+ snprintf(name,sizeof(name),"%s_stats",ipd->name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -