The following code seems to me to be a valid example of a binary semaphore (mutex) in a timer:
//timer called 10 times a second static void status_timer(unsigned long device) { struct etp_device_private *dp = (struct etp_device_private *)device; if (unlikely(dp->status_interface == 0)) dp->status_interface = INTERFACES_PER_DEVICE - 1; else dp->status_interface--; //DBG_PRINT ("%s: In status timer, interface:0x%x.\n",etp_NAME, dp->status_interface); idt_los_interrupt_1(dp, dp->status_interface); if (likely(!dp->reset)) // reset the timer: mod_timer(&dp->status_timer, jiffies + HZ / 10); } static inline void read_idt_register_interrupt(struct etp_device_private *dp, unsigned reg) { DBG_PRINT("read_idt_register_interrupt to mutex_lock.\n"); if (unlikely(down_trylock(&dp->semaphore))) return; /* Do not read because failed to lock. */ if (likely (!dp->status && !(inl((void *)(dp->ioaddr + REG_E1_CTRL)) & E1_ACCESS_ON))) { outl(((reg << E1_REGISTER_SHIFT) & E1_REGISTER_MASK) | E1_DIR_READ | E1_ACCESS_ON, (void *)(dp->ioaddr + REG_E1_CTRL)); dp->status = 1; DBG_PRINT("read_idt_register_interrupt set status read.\n"); } else DBG_PRINT ("read_idt_register_interrupt did not set status %u read.\n", dp->status); DBG_PRINT ("read_idt_register_interrupt do not wait for result here, read in tasklet.\n"); } //for getting los information with interrupt: void idt_los_interrupt_1(struct etp_device_private *dp, unsigned interface) { read_idt_register_if_interrupt(dp, E1_TRNCVR_LINE_STATUS0_REG, interface); } static void e1_access_task(unsigned long data) //called after e1_access_interrupt { struct etp_device_private *dp = (struct etp_device_private *)data; struct etp_interface_private *ip; unsigned int interface, error; bool los; //check if los status was read: if (unlikely(!dp->status)) { DBG_PRINT("e1_access_task wakes up user.\n"); wake_up(&dp->e1_access_q); return; } error = idt_los_interrupt_2(dp->ioaddr, &interface, &los, dp->pci_dev->device); //DBG_PRINT ("%s: In e1 task, error:0x%x, interface:0x%x, los:0x%x.\n", // etp_NAME, error, interface, los); dp->status = 0; up(&dp->semaphore); DBG_PRINT("e1_access_task got error %u.\n", error); if (unlikely(error)) return; //update los status: ip = &dp->interface_privates[interface]; ip->los = los; //update status: if ((ip->if_mode == IF_MODE_CLOSED) || //interface closed or (ip->los)) { //link down set_led(LED_CTRL_OFF, ip); if (netif_carrier_ok(ip->ch_priv.this_netdev)) netif_carrier_off(ip->ch_priv.this_netdev); } else { //link up and interface opened if (!netif_carrier_ok(ip->ch_priv.this_netdev)) netif_carrier_on(ip->ch_priv.this_netdev); if (ip->if_mode == IF_MODE_HDLC) { set_led(LED_CTRL_TRAFFIC, ip); } else { //ip->if_mode == IF_MODE_TIMESLOT set_led(LED_CTRL_ON, ip); } } } int idt_los_interrupt_2(u8 * ioaddr, unsigned *interface, bool * los, unsigned pci_device_id) { //returns 0 in success unsigned int value = inl((void *)(ioaddr + REG_E1_CTRL)); //if access not ended: if (value & E1_ACCESS_ON) { return 1; } //if access not to los status register if ((value & E1_REGISTER_MASK_NO_IF) != (E1_TRNCVR_LINE_STATUS0_REG << E1_REGISTER_SHIFT)) { return 1; } //get interface *interface = idt_if_to_if((value & E1_REGISTER_MASK_IF) >> E1_REGISTER_SHIFT_IF, pci_device_id); *los = value & 0x1; return 0; } int write_idt_register_lock(unsigned device, unsigned reg, u32 value) { struct etp_device_private *etp = get_dev_priv(device); unsigned ctrl; DBG_PRINT("write_idt_register_lock to mutex lock device %u.\n", device); down(&etp->semaphore); if (unlikely(etp->reset)) { up(&etp->semaphore); DBG_PRINT ("write_idt_register_lock device %u unusable.\n", device); return -ENXIO; } DBG_PRINT("write_idt_register_lock mutex locked device %u.\n", device); do { DBG_PRINT ("write_idt_register_lock to wait_event_timeout device %u.\n", device); wait_event_timeout(etp->e1_access_q, !((ctrl = inl((void *)(etp->ioaddr + REG_E1_CTRL))) & E1_ACCESS_ON), HZ / 500); } while (ctrl & E1_ACCESS_ON); DBG_PRINT("write_idt_register_lock to outl device %u.\n", device); outl(((reg << E1_REGISTER_SHIFT) & E1_REGISTER_MASK) | E1_DIR_WRITE | E1_ACCESS_ON | (value & E1_DATA_MASK), (void *)(etp->ioaddr + REG_E1_CTRL)); up(&etp->semaphore); DBG_PRINT("write_idt_register_lock mutex unlocked device %u.\n", device); return 0; } Copyright (C) 2006 Jouni Kujala, Flexibilis Oy. __________________________________ Alles was der Gesundheit und Entspannung dient. BE A BETTER MEDIZINMANN! www.yahoo.de/clever - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/