Pete Zaitcev wrote:

>
> When I saw it, two thoughts crossed my mind
> 1. No need to cover malloc

Right. Fixed in the attached patch.

>
> 2. Time to de-inline that function

I'm not sure it's time yet. I'll leave that up to Dave
Brownell.

I also added locks in the lookup routine dma_to_ed_td().
It's always a fast lookup, and it's possible the list could
change in the middle of the search either by interrupt code
or another processor, although I don't think currently the
add/free routines are called at interrupt time.

Steve

--- drivers/usb/usb-ohci.h.orig Mon May  7 10:12:42 2001
+++ drivers/usb/usb-ohci.h      Mon May  7 11:41:24 2001
@@ -453,16 +453,26 @@
        /* to support non-PCI OHCIs, you need custom bus/mem/... glue */
 #endif
 
+/* Lock for TD/ED hashing */
+static spinlock_t usb_hash_lock = SPIN_LOCK_UNLOCKED;
 
 /* Recover a TD/ED using its collision chain */
 static inline void *
 dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
 {
-       struct hash_t * scan = entry->head;
+       struct hash_t * scan;
+        unsigned long flags;
+
+        spin_lock_irqsave (&usb_hash_lock, flags);
+
+       scan = entry->head;
        while (scan && scan->dma != dma)
                scan = scan->next;
        if (!scan)
                BUG();
+
+       spin_unlock_irqrestore (&usb_hash_lock, flags);
+
        return scan->virt;
 }
 
@@ -480,16 +490,20 @@
                                      td_dma);
 }
 
+
 /* Add a hash entry for a TD/ED; return true on success */
 static inline int
 hash_add_ed_td(struct hash_list_t * entry, void * virt, dma_addr_t dma)
 {
        struct hash_t * scan;
-       
+        unsigned long flags;
+
        scan = (struct hash_t *)kmalloc(sizeof(struct hash_t), ALLOC_FLAGS);
        if (!scan)
                return 0;
        
+        spin_lock_irqsave (&usb_hash_lock, flags);
+
        if (!entry->tail) {
                entry->head = entry->tail = scan;
        } else {
@@ -500,6 +514,7 @@
        scan->virt = virt;
        scan->dma = dma;
        scan->next = NULL;
+        spin_unlock_irqrestore (&usb_hash_lock, flags);
        return 1;
 }
 
@@ -522,6 +537,10 @@
 hash_free_ed_td (struct hash_list_t * entry, void * virt)
 {
        struct hash_t *scan, *prev;
+        unsigned long flags;
+
+        spin_lock_irqsave (&usb_hash_lock, flags);
+
        scan = prev = entry->head;
 
        // Find and unlink hash entry
@@ -542,6 +561,7 @@
                        prev->next = scan->next;
                kfree(scan);
        }
+        spin_unlock_irqrestore (&usb_hash_lock, flags);
 }
 
 static inline void

Reply via email to