static int wait_for_stat(struct tpm_chip* tpm, uint8_t mask, unsigned long timeout, struct wait_queue_head* queue) { s_time_t stop; uint8_t status; status = tpm_tis_status(tpm); if((status & mask) == mask) { return 0; } if(tpm->irq) { wait_event_deadline(*queue, ((tpm_tis_status(tpm) & mask) == mask), timeout); /* FIXME: Check for timeout and return -ETIME */ return 0; } else { stop = NOW() + timeout; do { msleep(TPM_TIMEOUT); status = tpm_tis_status(tpm); if((status & mask) == mask) return 0; } while( NOW() < stop); } return -ETIME; }
/* Blocks the thread while waiting for the semaphore to be * signaled. If the "timeout" argument is non-zero, the thread should * only be blocked for the specified time (measured in * milliseconds). * * If the timeout argument is non-zero, the return value is the number of * milliseconds spent waiting for the semaphore to be signaled. If the * semaphore wasn't signaled within the specified time, the return value is * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore * (i.e., it was already signaled), the function may return zero. */ u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) { /* Slightly more complicated than the normal minios semaphore: * need to wake on timeout *or* signal */ int flags; int64_t then = NOW(); int64_t deadline; if (timeout == 0) deadline = 0; else deadline = then + MILLISECS(timeout); while(1) { wait_event_deadline(sem->sem.wait, (sem->sem.count > 0), deadline); local_irq_save(flags); /* Atomically check that we can proceed */ if (sem->sem.count > 0 || (deadline && NOW() >= deadline)) break; local_irq_restore(flags); } if (sem->sem.count > 0) { sem->sem.count--; local_irq_restore(flags); return NSEC_TO_MSEC(NOW() - then); } local_irq_restore(flags); return SYS_ARCH_TIMEOUT; }
int tpm_tis_request_locality(struct tpm_chip* tpm, int l) { s_time_t stop; /*Make sure locality is valid */ if(!locality_enabled(tpm, l)) { printk("tpm_tis_change_locality() Tried to change to locality %d, but it is disabled or invalid!\n", l); return -1; } /* Check if we already have the current locality */ if(check_locality(tpm, l) >= 0) { return tpm->locality = l; } /* Set the new locality*/ iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_REQUEST_USE); if(tpm->irq) { /* Wait for interrupt */ wait_event_deadline(tpm->int_queue, (check_locality(tpm, l) >= 0), NOW() + tpm->timeout_a); /* FIXME: Handle timeout event, should return error in that case */ return l; } else { /* Wait for burstcount */ stop = NOW() + tpm->timeout_a; do { if(check_locality(tpm, l) >= 0) { return tpm->locality = l; } msleep(TPM_TIMEOUT); } while(NOW() < stop); } printk("REQ LOCALITY FAILURE\n"); return -1; }
/* Blocks the thread until a message arrives in the mailbox, but does * not block the thread longer than "timeout" milliseconds (similar to * the sys_arch_sem_wait() function). The "msg" argument is a result * parameter that is set by the function (i.e., by doing "*msg = * ptr"). The "msg" parameter maybe NULL to indicate that the message * should be dropped. * * The return values are the same as for the sys_arch_sem_wait() function: * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a * timeout. */ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) { int flags; int64_t then = NOW(); int64_t deadline; if (timeout == 0) deadline = 0; else deadline = then + MILLISECS(timeout); while(1) { wait_event_deadline(mbox->read_sem.wait, (mbox->read_sem.count > 0), deadline); local_irq_save(flags); /* Atomically check that we can proceed */ if (mbox->read_sem.count > 0 || (deadline && NOW() >= deadline)) break; local_irq_restore(flags); } if (mbox->read_sem.count <= 0) { local_irq_restore(flags); return SYS_ARCH_TIMEOUT; } mbox->read_sem.count--; local_irq_restore(flags); do_mbox_fetch(mbox, msg); return 0; }