📄 hal13c1-2.4.25.patch
字号:
++ for (event = 0; event < ADEOS_NR_EVENTS; event++)+ /* Need this to update the monitor count. */+ adeos_catch_event(event,NULL);++#ifdef CONFIG_SMP+ {+ unsigned irq;+ int _cpuid;++ /* In the SMP case, wait for the logged events to drain on other+ processors before eventually removing the domain from the+ pipeline. */++ adeos_unstall_pipeline_from(adp);++ flags = adeos_critical_enter(NULL);++ for (irq = 0; irq < IPIPE_NR_IRQS; irq++)+ {+ clear_bit(IPIPE_HANDLE_FLAG,&adp->irqs[irq].control);+ clear_bit(IPIPE_STICKY_FLAG,&adp->irqs[irq].control);+ set_bit(IPIPE_PASS_FLAG,&adp->irqs[irq].control);+ }++ adeos_critical_exit(flags);++ for (_cpuid = 0; _cpuid < smp_num_cpus; _cpuid++)+ {+ for (irq = 0; irq < IPIPE_NR_IRQS; irq++)+ while (adp->cpudata[_cpuid].irq_hits[irq] > 0)+ cpu_relax();++ while (test_bit(IPIPE_XPEND_FLAG,&adp->cpudata[_cpuid].status))+ cpu_relax();++ while (!test_bit(IPIPE_SLEEP_FLAG,&adp->cpudata[_cpuid].status))+ cpu_relax();+ }+ }+#endif /* CONFIG_SMP */++ /* Simply remove the domain from the pipeline and we are almost+ done. */++ flags = adeos_critical_enter(NULL);+ list_del_init(&adp->p_link);+ adeos_critical_exit(flags);++ __adeos_cleanup_domain(adp);++ printk(KERN_WARNING "Adeos: Domain %s unregistered.\n",adp->name);++ return 0;+}++/* adeos_renice_domain() -- Change the priority of the current+ domain. This affects the position of the domain in the interrupt+ pipeline. The greater the priority value, the earlier the domain is+ informed of incoming events when the pipeline is processed. This+ routine causes a round-robin effect if newpri == oldpri. */++void adeos_renice_domain (int newpri)++{+ adomain_t *adp, *nadp = NULL;+ unsigned long lflags, xflags;+ struct list_head *pos;+ adeos_declare_cpuid;++ /* We do want adeos_critical_exit() to leave the IRQs masked, so+ we first clear the interrupt bit before calling+ adeos_critical_enter(). */+ + adeos_lock_cpu(lflags);++ adp = adp_cpu_current[cpuid];++ xflags = adeos_critical_enter(NULL);++ list_del_init(&adp->p_link);++ list_for_each(pos,&__adeos_pipeline) {+ adomain_t *_adp = list_entry(pos,adomain_t,p_link);++ if (newpri > _adp->priority)+ break;++ /* While scanning the pipeline from its head to the current+ domain's new position, pick the first domain which is+ entitled to preempt us. Such domain must be either:+ o in a preempted state (i.e. !sleeping),+ o or sleeping and unstalled with events to process. */++ if (nadp == NULL &&+ (!test_bit(IPIPE_SLEEP_FLAG,&_adp->cpudata[cpuid].status) ||+ (!test_bit(IPIPE_STALL_FLAG,&_adp->cpudata[cpuid].status) &&+ _adp->cpudata[cpuid].irq_pending_hi != 0) ||+ test_bit(IPIPE_XPEND_FLAG,&_adp->cpudata[cpuid].status)))+ nadp = _adp;+ }++ list_add_tail(&adp->p_link,pos);+ adp->priority = newpri;+ + /* On SMP systems, we release the other CPUs but we still keep the+ local IRQs masked so that we can't jump to a stale domain. */++ adeos_critical_exit(xflags);++ if (nadp == NULL)+ goto release_cpu_and_exit;++ __adeos_switch_to(nadp,cpuid);++ adeos_load_cpuid(); /* Processor might have changed. */++ /* Try sync'ing pending interrupts on return from our preemption+ point. */++ if (!test_bit(IPIPE_STALL_FLAG,&adp_cpu_current[cpuid]->cpudata[cpuid].status) &&+ adp_cpu_current[cpuid]->cpudata[cpuid].irq_pending_hi != 0)+ __adeos_sync_stage(IPIPE_IRQMASK_ANY);++ /* Note that we only need to sync interrupts here, since other+ kind of events (i.e. synchronous ones) cannot flow across the+ domain which triggers them down the pipeline. Since a more+ prioritary domain was running up to now, there is no chance for+ us to have such event pending. */++release_cpu_and_exit:++ adeos_unlock_cpu(lflags);+}++int __adeos_schedule_irq (unsigned irq, struct list_head *head)++{+ struct list_head *ln;+ unsigned long flags;+ adeos_declare_cpuid;++ if (irq >= IPIPE_NR_IRQS ||+ (adeos_virtual_irq_p(irq) && !test_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map)))+ return -EINVAL;++ adeos_lock_cpu(flags);++ ln = head;++ while (ln != &__adeos_pipeline)+ {+ adomain_t *adp = list_entry(ln,adomain_t,p_link);++ if (test_bit(IPIPE_HANDLE_FLAG,&adp->irqs[irq].control))+ {+ adp->cpudata[cpuid].irq_hits[irq]++;+ __adeos_set_irq_bit(adp,cpuid,irq);+ adeos_unlock_cpu(flags);+ return 1;+ }++ ln = adp->p_link.next;+ }++ adeos_unlock_cpu(flags);++ return 0;+}++/* adeos_propagate_irq() -- Force a given IRQ propagation on behalf of+ a running interrupt handler to the next domain down the pipeline.+ Returns non-zero if a domain has received the interrupt+ notification, zero otherwise.+ This call is useful for handling shared interrupts among domains.+ e.g. pipeline = [domain-A]---[domain-B]...+ Both domains share IRQ #X.+ - domain-A handles IRQ #X but does not pass it down (i.e. Terminate+ or Dynamic interrupt control mode)+ - domain-B handles IRQ #X (i.e. Terminate or Accept interrupt+ control modes).+ When IRQ #X is raised, domain-A's handler determines whether it+ should process the interrupt by identifying its source. If not,+ adeos_propagate_irq() is called so that the next domain down the+ pipeline which handles IRQ #X is given a chance to process it. This+ process can be repeated until the end of the pipeline is+ reached. */++int adeos_propagate_irq (unsigned irq) {++ return __adeos_schedule_irq(irq,adp_current->p_link.next);+}++/* adeos_schedule_irq() -- Almost the same as adeos_propagate_irq(),+ but attempts to pend the interrupt for the current domain first. */++int adeos_schedule_irq (unsigned irq) {++ return __adeos_schedule_irq(irq,&adp_current->p_link);+}++unsigned long adeos_set_irq_affinity (unsigned irq, unsigned long cpumask)++{+#ifdef CONFIG_SMP+ if (irq >= IPIPE_NR_XIRQS)+ /* Allow changing affinity of external IRQs only. */+ return 0;++ if (smp_num_cpus > 1)+ /* Allow changing affinity of external IRQs only. */+ return __adeos_set_irq_affinity(irq,cpumask);+#endif /* CONFIG_SMP */++ return 0;+}++/* adeos_free_irq() -- Return a previously allocated virtual/soft+ pipelined interrupt to the pool of allocatable interrupts. */++int adeos_free_irq (unsigned irq)++{+ if (irq >= IPIPE_NR_IRQS)+ return -EINVAL;++ clear_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map);++ return 0;+}++/* adeos_unstall_pipeline_from() -- Unstall the interrupt pipeline and+ synchronize pending events from a given domain. */++void adeos_unstall_pipeline_from (adomain_t *adp)++{+ struct list_head *pos;+ unsigned long flags;+ adeos_declare_cpuid;++ adeos_get_cpu(flags);++ clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);++ if (adp == adp_cpu_current[cpuid])+ {+ if (adp->cpudata[cpuid].irq_pending_hi != 0)+ __adeos_sync_stage(IPIPE_IRQMASK_ANY);++ goto release_cpu_and_exit;+ }++ /* Attempt to flush all events that might be pending at the+ unstalled domain level. This code is roughly lifted from+ drivers/adeos/x86.c:__adeos_walk_pipeline(). */++ list_for_each(pos,&__adeos_pipeline) {++ adomain_t *_adp = list_entry(pos,adomain_t,p_link);++ if (test_bit(IPIPE_STALL_FLAG,&_adp->cpudata[cpuid].status))+ break; /* Stalled stage -- do not go further. */++ if (_adp->cpudata[cpuid].irq_pending_hi != 0)+ {+ /* Since the critical IPI might be triggered by the+ following actions, the current domain might not be+ linked to the pipeline anymore after its handler+ returns on SMP boxen, even if the domain remains valid+ (see adeos_unregister_domain()), so don't make any+ hazardous assumptions here. */++ if (_adp == adp_cpu_current[cpuid])+ __adeos_sync_stage(IPIPE_IRQMASK_ANY);+ else+ {+ __adeos_switch_to(_adp,cpuid);++ adeos_load_cpuid(); /* Processor might have changed. */++ if (!test_bit(IPIPE_STALL_FLAG,&adp_cpu_current[cpuid]->cpudata[cpuid].status) &&+ adp_cpu_current[cpuid]->cpudata[cpuid].irq_pending_hi != 0)+ __adeos_sync_stage(IPIPE_IRQMASK_ANY);+ }+ + break;+ }+ else if (_adp == adp_cpu_current[cpuid])+ break;+ }++release_cpu_and_exit:++ adeos_put_cpu(flags);+}++/* adeos_catch_event_from() -- Interpose an event handler starting+ from a given domain. */++int adeos_catch_event_from (adomain_t *adp, unsigned event, void (*handler)(adevinfo_t *))++{+ if (event >= ADEOS_NR_EVENTS)+ return -EINVAL;++ if (!xchg(&adp->events[event].handler,handler))+ {+ if (handler)+ __adeos_event_monitors[event]++;+ }+ else if (!handler)+ __adeos_event_monitors[event]--;++ return 0;+}++void (*adeos_hook_dswitch(void (*handler)(void))) (void) {++ return (void (*)(void))xchg(&adp_current->dswitch,handler);+}++void adeos_init_attr (adattr_t *attr)++{+ attr->name = "Anonymous";+ attr->domid = 1;+ attr->entry = NULL;+ attr->estacksz = 0; /* Let ADEOS choose a reasonable stack size */+ attr->priority = ADEOS_ROOT_PRI;+ attr->dswitch = NULL;+ attr->nptdkeys = 0;+ attr->ptdset = NULL;+ attr->ptdget = NULL;+}++int adeos_alloc_ptdkey (void)++{+ unsigned long flags;+ int key = -1;++ adeos_spin_lock_irqsave(&__adeos_pipelock,flags);++ if (adp_current->ptd_keycount < adp_current->ptd_keymax)+ {+ key = ffz(adp_current->ptd_keymap);+ set_bit(key,&adp_current->ptd_keymap);+ adp_current->ptd_keycount++;+ }++ adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);++ return key;+}++int adeos_free_ptdkey (int key)++{+ unsigned long flags; ++ if (key < 0 || key >= adp_current->ptd_keymax)+ return -EINVAL;++ adeos_spin_lock_irqsave(&__adeos_pipelock,flags);++ if (test_and_clear_bit(key,&adp_current->ptd_keymap))+ adp_current->ptd_keycount--;++ adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);++ return 0;+}++int adeos_set_ptd (int key, void *value)++{+ if (key < 0 || key >= adp_current->ptd_keymax)+ return -EINVAL;++ if (!adp_current->ptd_setfun)+ {+ printk(KERN_WARNING "Adeos: No ptdset hook for %s\n",adp_current->name);+ return -EINVAL;+ }++ adp_current->ptd_setfun(key,value);++ return 0;+}++void *adeos_get_ptd (int key)++{+ if (key < 0 || key >= adp_current->ptd_keymax)+ return NULL;++ if (!adp_current->ptd_getfun)+ {+ printk(KERN_WARNING "Adeos: No ptdget hook for %s\n",adp_current->name);+ return NULL;+ }++ return adp_current->ptd_getfun(key);+}++int adeos_init_mutex (admutex_t *mutex)++{+ admutex_t initm = ADEOS_MUTEX_UNLOCKED;+ *mutex = initm;+ return 0;+}++int adeos_destroy_mutex (admutex_t *mutex)++{+ if (!adeos_spin_trylock(&mutex->lock) &&+ adp_current != adp_root &&+ mutex->owner != adp_current)+ return -EBUSY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -