All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matti Linnanvuori <mattilinnanvuori@yahoo.com>
To: Arjan van de Ven <arjan@infradead.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
	linux-kernel@vger.kernel.org, Alan Cox <alan@lxorguk.ukuu.org.uk>
Subject: Do not deprecate binary semaphore or do allow mutex in software interrupt contexts
Date: Tue, 11 Sep 2007 22:39:21 -0700 (PDT)	[thread overview]
Message-ID: <698652.90161.qm@web52004.mail.re2.yahoo.com> (raw)

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

             reply	other threads:[~2007-09-12  5:39 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-12  5:39 Matti Linnanvuori [this message]
  -- strict thread matches above, loose matches on Subject: below --
2007-09-11 17:29 Do not deprecate binary semaphore or do allow mutex in software interrupt contexts Matti Linnanvuori
2007-09-11 19:22 ` Arjan van de Ven
2007-09-11 16:20 Matti Linnanvuori
2007-09-11 16:50 ` Peter Zijlstra
2007-09-11 18:22 ` Arjan van de Ven
2007-09-11 13:20 Matti Linnanvuori
2007-09-11 14:36 ` Arjan van de Ven
2007-09-11 13:56   ` Alan Cox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=698652.90161.qm@web52004.mail.re2.yahoo.com \
    --to=mattilinnanvuori@yahoo.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=arjan@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.