uint64_t db_read_uint64(DB_val *const val) { db_assert(val->size >= 1); size_t const len = varint_size(val->data); db_assert(val->size >= len); uint64_t const x = varint_decode(val->data, val->size); val->data += len; val->size -= len; return x; }
static void vrc5477_irq_disable(unsigned int irq) { db_assert(vrc5477_irq_base != -1); db_assert(irq >= vrc5477_irq_base); db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ); ll_vrc5477_irq_disable(irq - vrc5477_irq_base); }
static void vrc5477_irq_end(unsigned int irq) { db_assert(vrc5477_irq_base != -1); db_assert(irq >= vrc5477_irq_base); db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ); if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) ll_vrc5477_irq_enable( irq - vrc5477_irq_base); }
void ll_emma2rh_sw_irq_disable(int irq) { u32 reg; db_assert(irq >= 0); db_assert(irq < 32); reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); reg &= ~(1 << irq); emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); }
void ll_emma2rh_sw_irq_enable(int irq) { u32 reg; db_assert(irq >= 0); db_assert(irq < NUM_EMMA2RH_IRQ_SW); reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); reg |= 1 << irq; emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); }
void ll_emma2rh_gpio_irq_disable(int irq) { u32 reg; db_assert(irq >= 0); db_assert(irq < NUM_EMMA2RH_IRQ_GPIO); reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); reg &= ~(1 << irq); emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); }
void ll_vrc5477_irq_enable(int vrc5477_irq) { u32 reg_value; u32 reg_bitmask; u32 reg_index; db_assert(vrc5477_irq >= 0); db_assert(vrc5477_irq < NUM_5477_IRQ); reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; reg_value = ddb_in32(reg_index); reg_bitmask = 8 << (vrc5477_irq % 8 * 4); db_assert((reg_value & reg_bitmask) == 0); ddb_out32(reg_index, reg_value | reg_bitmask); }
void db_bind_string_len(DB_val *const val, char const *const str, size_t const len, int const nulterm, DB_txn *const txn) { assert(val); assert(len == strnlen(str, len) && "Embedded nuls"); unsigned char *const out = val->data; if(0 == len) { out[val->size++] = '\0'; out[val->size++] = str ? 0x01 : 0x00; return; } if(len < DB_INLINE_MAX) { memcpy(out+val->size, str, len); val->size += len; out[val->size++] = '\0'; if(DB_INLINE_TRUNC != len+1) return; out[val->size++] = '\0'; return; } memcpy(out+val->size, str, DB_INLINE_TRUNC-1); val->size += DB_INLINE_TRUNC-1; out[val->size++] = '\0'; SHA256_CTX algo[1]; int rc; rc = SHA256_Init(algo); db_assert(rc >= 0); rc = SHA256_Update(algo, str, len); db_assert(rc >= 0); rc = SHA256_Final(out+val->size, algo); db_assert(rc >= 0); if(0x00 == out[val->size]) out[val->size] = 0x01; val->size += SHA256_DIGEST_LENGTH; if(!txn) return; unsigned flags = 0; rc = db_txn_get_flags(txn, &flags); db_assertf(rc >= 0, "Database error %s", db_strerror(rc)); if(flags & DB_RDONLY) return; DB_val key = { DB_INLINE_MAX, out+val->size-DB_INLINE_MAX }; char *str2 = nulterm ? (char *)str : strndup(str, len); DB_val full = { len+1, str2 }; assert('\0' == str2[full.size-1]); rc = db_put(txn, &key, &full, 0); if(!nulterm) free(str2); str2 = NULL; db_assertf(rc >= 0, "Database error %s", db_strerror(rc)); }
static void vrc5477_irq_ack(unsigned int irq) { db_assert(vrc5477_irq_base != -1); db_assert(irq >= vrc5477_irq_base); db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ); /* clear the interrupt bit */ /* some irqs require the driver to clear the sources */ ddb_out32(DDB_INTCLR32, 1 << (irq - vrc5477_irq_base)); /* disable interrupt - some handler will re-enable the irq * and if the interrupt is leveled, we will have infinite loop */ ll_vrc5477_irq_disable(irq - vrc5477_irq_base); }
static int tx4927_pcibios_write_config_word(struct pci_dev *dev, int where, unsigned short val) { int flags; unsigned char bus, func_num; if (where & 1) return PCIBIOS_BAD_REGISTER_NUMBER; /* check if the bus is top-level */ if (dev->bus->parent != NULL) { bus = dev->bus->number; db_assert(bus != 0); } else { bus = 0; } func_num = PCI_FUNC(dev->devfn); if (mkaddr(bus, dev->devfn, where, &flags)) return -1; #ifdef __BIG_ENDIAN *(volatile u16 *) ((ulong) & tx4927_pcicptr-> g2pcfgdata | ((where & 3) ^ 2)) = val; #else *(volatile u16 *) ((ulong) & tx4927_pcicptr-> g2pcfgdata | (where & 3)) = val; #endif return check_abort(flags); }
void rtc_ds1386_init(unsigned long base) { unsigned char byte; /* remember the base */ rtc_base = base; db_assert((rtc_base & 0xe0000000) == KSEG1); /* turn on RTC if it is not on */ byte = READ_RTC(0x9); if (byte & 0x80) { byte &= 0x7f; WRITE_RTC(0x9, byte); } /* enable time transfer */ byte = READ_RTC(0xB); byte |= 0x80; WRITE_RTC(0xB, byte); /* set the function pointers */ rtc_get_time = rtc_ds1386_get_time; rtc_set_time = rtc_ds1386_set_time; }
/* * This should really return information about whether * we should do bottom half handling etc. Right now we * end up _always_ checking the bottom half, which is a * waste of time and is not what some drivers would * prefer. */ int __noinstrument handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { int status; int cpu = smp_processor_id(); db_assert(intr_off()); irq_enter(cpu, irq); status = 1; /* Force the "do bottom halves" bit */ if (!(action->flags & SA_INTERRUPT)) __sti(); do { status |= action->flags; action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); __cli(); irq_exit(cpu, irq); return status; }
void ddb5477_runtime_detection(void) { volatile char *test_offset; char saved_test_byte; /* Determine if this is a DDB5477 board, or a BSB-VR0300 base board. We can tell by checking for the location of the NVRAM. It lives at the beginning of LCS1 on the DDB5477, and the beginning of LCS1 on the BSB-VR0300 is flash memory. The first 2K of the NVRAM are reserved, so don't we'll poke around just after that. */ /* We can only use the PCI bus to distinquish between the Rockhopper and RockhopperII backplanes and this must wait until ddb5477_board_init() in setup.c after the 5477 is initialized. So, until then handle both Rockhopper and RockhopperII backplanes as Rockhopper 1 */ test_offset = (char *)KSEG1ADDR(DEFAULT_LCS1_BASE + 0x800); saved_test_byte = *test_offset; *test_offset = TESTVAL1; if (*test_offset != TESTVAL1) { /* We couldn't set our test value, so it must not be NVRAM, so it's a BSB_VR0300 */ mips_machtype = MACH_NEC_ROCKHOPPER; } else { /* We may have gotten lucky, and the TESTVAL1 was already stored at the test location, so we must check a second test value */ *test_offset = TESTVAL2; if (*test_offset != TESTVAL2) { /* OK, we couldn't set this value either, so it must definately be a BSB_VR0300 */ mips_machtype = MACH_NEC_ROCKHOPPER; } else { /* We could change the value twice, so it must be NVRAM, so it's a DDB_VRC5477 */ mips_machtype = MACH_NEC_DDB5477; } } /* Restore the original byte */ *test_offset = saved_test_byte; /* before we know a better way, we will trust PMON for getting * RAM size */ board_ram_size = 1 << (36 - (ddb_in32(DDB_SDRAM0) & 0xf)); db_run(printk("DDB run-time detection : %s, %d MB RAM\n", mips_machtype == MACH_NEC_DDB5477 ? "DDB5477" : "Rockhopper", board_ram_size >> 20)); /* we can't handle ram size > 128 MB */ db_assert(board_ram_size <= (128 << 20)); }
void ll_vrc5477_irq_disable(int vrc5477_irq) { u32 reg_value; u32 reg_bitmask; u32 reg_index; db_assert(vrc5477_irq >= 0); db_assert(vrc5477_irq < NUM_5477_IRQ); reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; reg_value = ddb_in32(reg_index); reg_bitmask = 8 << (vrc5477_irq % 8 * 4); /* we assert that the interrupt is enabled (perhaps over-zealous) */ db_assert( (reg_value & reg_bitmask) != 0); ddb_out32(reg_index, reg_value & ~reg_bitmask); }
void ll_vrc5477_irq_route(int vrc5477_irq, int ip) { u32 reg_value; u32 reg_bitmask; u32 reg_index; db_assert(vrc5477_irq >= 0); db_assert(vrc5477_irq < NUM_5477_IRQ); db_assert(ip >= 0); db_assert((ip < 5) || (ip == 6)); reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; reg_value = ddb_in32(reg_index); reg_bitmask = 7 << (vrc5477_irq % 8 * 4); reg_value &= ~reg_bitmask; reg_value |= ip << (vrc5477_irq % 8 * 4); ddb_out32(reg_index, reg_value); }
__init void plat_time_init(void) { unsigned int configPR; unsigned int n; unsigned int m; unsigned int p; unsigned int pow2p; pnx8xxx_clockevent.cpumask = cpu_none_mask; clockevents_register_device(&pnx8xxx_clockevent); clocksource_register(&pnx_clocksource); /* Timer 1 start */ configPR = read_c0_config7(); configPR &= ~0x00000008; write_c0_config7(configPR); /* Timer 2 start */ configPR = read_c0_config7(); configPR &= ~0x00000010; write_c0_config7(configPR); /* Timer 3 stop */ configPR = read_c0_config7(); configPR |= 0x00000020; write_c0_config7(configPR); /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */ /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */ n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16; m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8; p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2; pow2p = (1 << p); db_assert(m != 0 && pow2p != 0); /* * Compute the frequency as in the PNX8550 User Manual 1.0, p.186 * (a.k.a. 8-10). Divide by HZ for a timer offset that results in * HZ timer interrupts per second. */ mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p)); cpj = (mips_hpt_frequency + HZ / 2) / HZ; write_c0_count(0); timer_ack(); /* Setup Timer 2 */ write_c0_count2(0); write_c0_compare2(0xffffffff); setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq); setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); }
int SLNSessionGetNextMetaMapURI(SLNSessionRef const session, strarg_t const targetURI, uint64_t *const metaMapID, str_t *out, size_t const max) { // TODO: We should handle URI synonyms. // That might mean accepting a fileID instead of targetURI... assert(metaMapID); assert(out); uint64_t const sessionID = SLNSessionGetID(session); DB_env *db = NULL; DB_txn *txn = NULL; DB_cursor *cursor = NULL; int rc = 0; size_t count = 0; rc = SLNSessionDBOpen(session, SLN_RDONLY, &db); if(rc < 0) goto cleanup; rc = db_txn_begin(db, NULL, DB_RDONLY, &txn); if(rc < 0) goto cleanup; rc = db_cursor_open(txn, &cursor); if(rc < 0) goto cleanup; DB_range range[1]; DB_val key[1]; SLNTargetURISessionIDAndMetaMapIDRange2(range, txn, targetURI, sessionID); SLNTargetURISessionIDAndMetaMapIDKeyPack(key, txn, targetURI, sessionID, *metaMapID); rc = db_cursor_seekr(cursor, range, key, NULL, +1); if(rc < 0) goto cleanup; strarg_t u; uint64_t s; SLNTargetURISessionIDAndMetaMapIDKeyUnpack(key, txn, &u, &s, metaMapID); DB_val row[1], val[1]; SLNSessionIDAndMetaMapIDToMetaURIAndTargetURIKeyPack(row, txn, sessionID, *metaMapID); rc = db_get(txn, row, val); if(rc < 0) goto cleanup; strarg_t metaURI, t; SLNSessionIDAndMetaMapIDToMetaURIAndTargetURIValUnpack(val, txn, &metaURI, &t); db_assert(metaURI); strlcpy(out, metaURI, max); // TODO: Handle err cleanup: db_cursor_close(cursor); cursor = NULL; db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); if(rc < 0) return rc; return count; }
static void vrc5477_irq_dispatch(struct pt_regs *regs) { u32 intStatus; u32 bitmask; u32 i; db_assert(ddb_in32(DDB_INT2STAT) == 0); db_assert(ddb_in32(DDB_INT3STAT) == 0); db_assert(ddb_in32(DDB_INT4STAT) == 0); db_assert(ddb_in32(DDB_NMISTAT) == 0); if (ddb_in32(DDB_INT1STAT) != 0) { #if defined(CONFIG_RUNTIME_DEBUG) vrc5477_show_int_regs(); #endif panic("error interrupt has happened."); } intStatus = ddb_in32(DDB_INT0STAT); if (mips_machtype == MACH_NEC_ROCKHOPPERII) { /* check for i8259 interrupts */ if (intStatus & (1 << VRC5477_I8259_CASCADE)) { int i8259_irq = i8259_interrupt_ack(); do_IRQ(I8259_IRQ_BASE + i8259_irq, regs); return; } } for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) { /* do we need to "and" with the int mask? */ if (intStatus & bitmask) { do_IRQ(VRC5477_IRQ_BASE + i, regs); return; } } }
void ll_emma2rh_irq_disable(int emma2rh_irq) { u32 reg_value; u32 reg_bitmask; u32 reg_index; reg_index = EMMA2RH_BHIF_INT_EN_0 + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (emma2rh_irq / 32); reg_value = emma2rh_in32(reg_index); reg_bitmask = 0x1 << (emma2rh_irq % 32); db_assert((reg_value & reg_bitmask) != 0); emma2rh_out32(reg_index, reg_value & ~reg_bitmask); }
static int tx4927_pcibios_read_config_word(struct pci_dev *dev, int where, unsigned short *val) { int flags, retval; unsigned char bus, func_num; if (where & 1) return PCIBIOS_BAD_REGISTER_NUMBER; db_assert((where & 3) == 0); db_assert(where < (1 << 8)); /* check if the bus is top-level */ if (dev->bus->parent != NULL) { bus = dev->bus->number; db_assert(bus != 0); } else { bus = 0; } func_num = PCI_FUNC(dev->devfn); if (mkaddr(bus, dev->devfn, where, &flags)) return -1; #ifdef __BIG_ENDIAN *val = *(volatile u16 *) ((ulong) & tx4927_pcicptr-> g2pcfgdata | ((where & 3) ^ 2)); #else *val = *(volatile u16 *) ((ulong) & tx4927_pcicptr-> g2pcfgdata | (where & 3)); #endif retval = check_abort(flags); if (retval == PCIBIOS_DEVICE_NOT_FOUND) *val = 0xffff; return retval; }
char const *db_read_string(DB_val *const val, DB_txn *const txn) { assert(txn); assert(val); db_assert(val->size >= 1); char const *const str = val->data; size_t const len = strnlen(str, MIN(val->size, DB_INLINE_MAX)); db_assert('\0' == str[len]); if(0 == len) { db_assert(val->size >= 2); val->data += 2; val->size -= 2; if(0x00 == str[1]) return NULL; if(0x01 == str[1]) return ""; db_assertf(0, "Invalid string type %u\n", str[1]); return NULL; } if(DB_INLINE_TRUNC != len+1) { val->data += len+1; val->size -= len+1; return str; } db_assert(val->size >= len+2); if(0x00 == str[len+1]) { val->data += len+2; val->size -= len+2; return str; } DB_val key = { DB_INLINE_MAX, (char *)str }; DB_val full[1]; int rc = db_get(txn, &key, full); db_assertf(rc >= 0, "Database error %s", db_strerror(rc)); char const *const fstr = full->data; db_assert('\0' == fstr[full->size-1]); return fstr; }
void __init pcibios_fixup_irqs(void) { struct pci_dev *dev; int slot_num; pci_for_each_dev(dev) { slot_num = PCI_SLOT(dev->devfn); /* we don't do IRQ fixup for sub-bus yet */ if (dev->bus->parent != NULL) { db_run(printk("Don't know how to fixup irq for PCI device %d on sub-bus %d\n", slot_num, dev->bus->number)); continue; } db_assert(slot_num < MAX_SLOT_NUM); db_assert(irq_map[slot_num] != 0xff); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq_map[slot_num]); dev->irq = vrc5477_irq_to_irq(irq_map[slot_num]); } }
/* * We can't address 8 and 16 bit words directly. Instead we have to * read/write a 32bit word and mask/modify the data we actually want. */ static int jmr3927_pcibios_read_config_byte (struct pci_dev *dev, int where, unsigned char *val) { int flags; unsigned char bus, func_num; db_assert((where & 3) == 0); db_assert(where < (1 << 8)); /* check if the bus is top-level */ if (dev->bus->parent != NULL) { bus = dev->bus->number; db_assert(bus != 0); } else { bus = 0; } func_num = PCI_FUNC(dev->devfn); if (mkaddr(bus, dev->devfn, where, &flags)) return -1; *val = *(volatile u8 *)((ulong)&tx3927_pcicptr->icd | (where&3)); return check_abort(flags); }
void rtc_ds1742_init(unsigned long base) { u8 cmos_second; /* remember the base */ rtc_base = base; db_assert((rtc_base & 0xe0000000) == KSEG1); /* set the function pointers */ rtc_get_time = rtc_ds1742_get_time; rtc_set_time = rtc_ds1742_set_time; /* clear oscillator stop bit */ CMOS_WRITE(RTC_READ, RTC_CONTROL); cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); CMOS_WRITE(RTC_WRITE, RTC_CONTROL); CMOS_WRITE(cmos_second, RTC_SECONDS); /* clear msb */ CMOS_WRITE(0, RTC_CONTROL); }
static int tx4927_pcibios_write_config_dword(struct pci_dev *dev, int where, unsigned int val) { int flags; unsigned char bus, func_num; if (where & 3) return PCIBIOS_BAD_REGISTER_NUMBER; /* check if the bus is top-level */ if (dev->bus->parent != NULL) { bus = dev->bus->number; db_assert(bus != 0); } else { bus = 0; } func_num = PCI_FUNC(dev->devfn); if (mkaddr(bus, dev->devfn, where, &flags)) return -1; tx4927_pcicptr->g2pcfgdata = val; return check_abort(flags); }
void pnx8550_time_init(void) { unsigned int n; unsigned int m; unsigned int p; unsigned int pow2p; /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */ /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */ n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16; m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8; p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2; pow2p = (1 << p); db_assert(m != 0 && pow2p != 0); /* * Compute the frequency as in the PNX8550 User Manual 1.0, p.186 * (a.k.a. 8-10). Divide by HZ for a timer offset that results in * HZ timer interrupts per second. */ mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p)); }
static int jmr3927_pcibios_write_config_word (struct pci_dev *dev, int where, unsigned short val) { int flags; unsigned char bus, func_num; if (where & 1) return PCIBIOS_BAD_REGISTER_NUMBER; /* check if the bus is top-level */ if (dev->bus->parent != NULL) { bus = dev->bus->number; db_assert(bus != 0); } else { bus = 0; } func_num = PCI_FUNC(dev->devfn); if (mkaddr(bus, dev->devfn, where, &flags)) return -1; *(volatile u16 *)((ulong)&tx3927_pcicptr->icd | (where&3)) = cpu_to_le16(val); return check_abort(flags); }
/* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers). */ asmlinkage unsigned int __noinstrument do_IRQ(int irq, struct pt_regs *regs) { /* * We ack quickly, we don't want the irq controller * thinking we're snobs just because some other CPU has * disabled global interrupts (we have already done the * INT_ACK cycles, it's too late to try to pretend to the * controller that we aren't taking the interrupt). * * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; struct irqaction * action; unsigned int status; #ifdef CONFIG_ILATENCY { extern void interrupt_overhead_start(void); interrupt_overhead_start(); } #endif /* CONFIG_ILATENCY */ preempt_disable(); TRACE_IRQ_ENTRY(irq, !user_mode(regs)); kstat.irqs[cpu][irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); /* REPLAY is when Linux resends an IRQ that was dropped earlier WAITING is used by probe to mark irqs that are being tested */ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); status |= IRQ_PENDING; /* we _want_ to handle it */ /* * If the IRQ is disabled for whatever reason, we cannot * use the action we have. */ action = NULL; if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { action = desc->action; status &= ~IRQ_PENDING; /* we commit to handling */ status |= IRQ_INPROGRESS; /* we are handling it */ } desc->status = status; /* * If there is no IRQ handler or it was disabled, exit early. Since we set PENDING, if another processor is handling a different instance of this same irq, the other processor will take care of it. */ if (!action) goto out; /* * Edge triggered interrupts need to remember * pending events. * This applies to any hw interrupts that allow a second * instance of the same irq to arrive while we are in do_IRQ * or in the handler. But the code here only handles the _second_ * instance of the irq, not the third or fourth. So it is mostly * useful for irq hardware that does not mask cleanly in an * SMP environment. */ #ifdef CONFIG_ILATENCY { extern void interrupt_overhead_stop(void); interrupt_overhead_stop(); } #endif /* CONFIG_ILATENCY */ for (;;) { spin_unlock(&desc->lock); handle_IRQ_event(irq, regs, action); spin_lock(&desc->lock); if (!(desc->status & IRQ_PENDING)) break; desc->status &= ~IRQ_PENDING; } desc->status &= ~IRQ_INPROGRESS; out: /* * The ->end() handler has to deal with interrupts which got * disabled while the handler was running. */ desc->handler->end(irq); spin_unlock(&desc->lock); TRACE_IRQ_EXIT(); if (softirq_pending(cpu)) do_softirq(); #if defined(CONFIG_PREEMPT) for(;;) { preempt_enable_no_resched(); if (preempt_is_disabled() || !need_resched()) break; db_assert(intr_off()); db_assert(!in_interrupt()); preempt_disable(); __sti(); preempt_schedule(); __cli(); } #endif #ifdef CONFIG_ILATENCY intr_ret_from_exception(); #endif return 1; }