Hello,

I have some questions about the locking techniques used inside
file drivers/staging/most/hdm-usb/hdm_usb.c.

The one and only call to function free_anchored_buffers is locked by a Mutex:

----------------------------------------------------------------------------
        ...
        mutex_lock(&mdev->io_mutex);
        free_anchored_buffers(mdev, channel);
        if (mdev->padding_active[channel])
                mdev->padding_active[channel] = false;

        if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
                del_timer_sync(&mdev->link_stat_timer);
                cancel_work_sync(&mdev->poll_work_obj);
        }
        mutex_unlock(&mdev->io_mutex);
        ...                                             
----------------------------------------------------------------------------

Then, inside function free_anchored_buffers, they use a (from my point of view)
somewhat complex spinlock variant:

----------------------------------------------------------------------------
static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel)
{
        struct mbo *mbo;
        struct buf_anchor *anchor, *tmp;
        unsigned long flags;

        spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
        list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel],
                                 list) {
                struct urb *urb = anchor->urb;

                spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
                if (likely(urb)) {
                        mbo = urb->context;
                        if (!irqs_disabled()) {
                                usb_kill_urb(urb);
                        } else {
                                usb_unlink_urb(urb);
                                wait_for_completion(&anchor->urb_compl);
                        }
                        if ((mbo) && (mbo->complete)) {
                                mbo->status = MBO_E_CLOSE;
                                mbo->processed_length = 0;
                                mbo->complete(mbo);
                        }
                        usb_free_urb(urb);
                }
                spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
                list_del(&anchor->list);
                cancel_work_sync(&anchor->clear_work_obj);
                kfree(anchor);
        }
        spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
}
----------------------------------------------------------------------------

To my questions:

#1: What is the intention of locking a whole function with a Mutex and then
    using spinlocks inside the function? Wouldn't it be sufficient to use
    one locking technique?
#2: Why is the spinlock not just locking the whole list_for_each_entry part or
    just the list_del(&anchor->list)?


Thank you very much in advance.

With best regards

Michael

_______________________________________________
Kernelnewbies mailing list
[email protected]
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

Reply via email to