Applied to the trunk and the branch (2408, 2411).
Sorry for the delay.

> -----Original Message-----
> From: Sean Hefty [mailto:[email protected]] 
> Sent: Wednesday, September 02, 2009 5:53 PM
> To: [email protected]; Tzachi Dar; Leonid Keller
> Subject: RE: [ofw] [PATCH] mthca/mlx4: allow retrieving CA 
> attributes withpageable memory
> 
> We are in need of a fix for the 2.1 release.  Does this patch 
> look acceptable?
> 
> >Modify the HCA drivers to support querying for attributes using a 
> >pageable buffer.  Since the query calls block, it seems 
> appropriate for 
> >the calls to allow pageable memory, rather than forcing the user to 
> >allocate a non-paged buffer in order to obtain a list of 
> attributes.  
> >The problem stems from the HCA drivers accessing a user's 
> buffer after acquiring a spinlock that raise IRQL.
> >
> >This fixes kernel crashes with both the winmad and winverbs drivers.
> >
> >Signed-off-by: Sean Hefty <[email protected]>
> >---
> >The mthca patch is compile tested only.
> >
> >We need this, or some fix, in winof 2.1.
> >
> >Index: hw/mlx4/kernel/bus/core/cache.c
> >===================================================================
> >--- hw/mlx4/kernel/bus/core/cache.c  (revision 2342)
> >+++ hw/mlx4/kernel/bus/core/cache.c  (working copy)
> >@@ -80,9 +80,9 @@
> >                   int               index,
> >                   union ib_gid     *gid)
> > {
> >+    union ib_gid cgid;
> >     struct ib_gid_cache *cache;
> >     unsigned long flags;
> >-    int ret = 0;
> >
> >     if (mlx4_is_barred(device->dma_device))
> >             return -EFAULT;
> >@@ -94,14 +94,16 @@
> >
> >     cache = device->cache.gid_cache[port_num - start_port(device)];
> >
> >-    if (index < 0 || index >= cache->table_len)
> >-            ret = -EINVAL;
> >-    else
> >-            *gid = cache->table[index];
> >-
> >+    if (index < 0 || index >= cache->table_len) {
> >+            read_unlock_irqrestore(&device->cache.lock, flags);
> >+            return -EINVAL;
> >+    }
> >+
> >+    cgid = cache->table[index];
> >     read_unlock_irqrestore(&device->cache.lock, flags);
> >+    *gid = cgid;
> >
> >-    return ret;
> >+    return 0;
> > }
> > EXPORT_SYMBOL(ib_get_cached_gid);
> >
> >@@ -113,33 +115,34 @@
> >     struct ib_gid_cache *cache;
> >     unsigned long flags;
> >     int p, i;
> >-    int ret = -ENOENT;
> >
> >     if (mlx4_is_barred(device->dma_device))
> >             return -EFAULT;
> >
> >-    *port_num = (u8)-1;
> >-    if (index)
> >-            *index = (u16)-1;
> >-
> >     read_lock_irqsave(&device->cache.lock, &flags);
> >
> >     for (p = 0; p <= end_port(device) - start_port(device); ++p) {
> >             cache = device->cache.gid_cache[p];
> >             for (i = 0; i < cache->table_len; ++i) {
> >                     if (!memcmp(gid, &cache->table[i], 
> sizeof *gid)) {
> >-                            *port_num = (u8)(p + 
> start_port(device));
> >-                            if (index)
> >-                                    *index = (u16)i;
> >-                            ret = 0;
> >                             goto found;
> >                     }
> >             }
> >     }
> >+
> >+    read_unlock_irqrestore(&device->cache.lock, flags);
> >+    *port_num = (u8)-1;
> >+    if (index)
> >+            *index = (u16)-1;
> >+    return -ENOENT;
> >+
> > found:
> >     read_unlock_irqrestore(&device->cache.lock, flags);
> >+    *port_num = (u8)(p + start_port(device));
> >+    if (index)
> >+            *index = (u16)i;
> >
> >-    return ret;
> >+    return 0;
> > }
> > EXPORT_SYMBOL(ib_find_cached_gid);
> >
> >@@ -149,8 +152,8 @@
> >                    __be16           *pkey)
> > {
> >     struct ib_pkey_cache *cache;
> >+    __be16 cpkey;
> >     unsigned long flags;
> >-    int ret = 0;
> >
> >     if (mlx4_is_barred(device->dma_device))
> >             return -EFAULT;
> >@@ -162,14 +165,16 @@
> >
> >     cache = device->cache.pkey_cache[port_num - start_port(device)];
> >
> >-    if (index < 0 || index >= cache->table_len)
> >-            ret = -EINVAL;
> >-    else
> >-            *pkey = cache->table[index];
> >+    if (index < 0 || index >= cache->table_len) {
> >+            read_unlock_irqrestore(&device->cache.lock, flags);
> >+            return -EINVAL;
> >+    }
> >
> >+    cpkey = cache->table[index];
> >     read_unlock_irqrestore(&device->cache.lock, flags);
> >+    *pkey = cpkey;
> >
> >-    return ret;
> >+    return 0;
> > }
> > EXPORT_SYMBOL(ib_get_cached_pkey);
> >
> >@@ -181,7 +186,6 @@
> >     struct ib_pkey_cache *cache;
> >     unsigned long flags;
> >     int i;
> >-    int ret = -ENOENT;
> >
> >     if (mlx4_is_barred(device->dma_device))
> >             return -EFAULT;
> >@@ -197,14 +201,17 @@
> >
> >     for (i = 0; i < cache->table_len; ++i)
> >             if ((cache->table[i] & 0x7fff) == (pkey & 0x7fff)) {
> >-                    *index = (u16)i;
> >-                    ret = 0;
> >-                    break;
> >+                    goto found;
> >             }
> >
> >     read_unlock_irqrestore(&device->cache.lock, flags);
> >+    *index = (u16)-1;
> >+    return -ENOENT;
> >
> >-    return ret;
> >+found:
> >+    read_unlock_irqrestore(&device->cache.lock, flags);
> >+    *index = (u16)i;
> >+    return 0;
> > }
> > EXPORT_SYMBOL(ib_find_cached_pkey);
> >
> >@@ -213,14 +220,16 @@
> >                   u8                *lmc)
> > {
> >     unsigned long flags;
> >+    u8 clmc;
> >     int ret = 0;
> >
> >     if (port_num < start_port(device) || port_num > 
> end_port(device))
> >             return -EINVAL;
> >
> >     read_lock_irqsave(&device->cache.lock, &flags);
> >-    *lmc = device->cache.lmc_cache[port_num - start_port(device)];
> >+    clmc = device->cache.lmc_cache[port_num - start_port(device)];
> >     read_unlock_irqrestore(&device->cache.lock, flags);
> >+    *lmc = clmc;
> >
> >     return ret;
> > }
> >Index: hw/mthca/kernel/mt_cache.c
> >===================================================================
> >--- hw/mthca/kernel/mt_cache.c       (revision 2342)
> >+++ hw/mthca/kernel/mt_cache.c       (working copy)
> >@@ -71,8 +71,8 @@
> >                   int               index,
> >                   union ib_gid     *gid)
> > {
> >+    union ib_gid cgid;
> >     struct ib_gid_cache *cache;
> >-    int ret = 0;
> >     SPIN_LOCK_PREP(lh);
> >
> >     // sanity checks
> >@@ -85,14 +85,16 @@
> >
> >     cache = device->cache.gid_cache[port_num - start_port(device)];
> >
> >-    if (index < 0 || index >= cache->table_len)
> >-            ret = -EINVAL;
> >-    else
> >-            *gid = cache->table[index];
> >+    if (index < 0 || index >= cache->table_len) {
> >+            read_unlock_irqrestore(&lh);
> >+            return -EINVAL;
> >+    }
> >
> >+    cgid = cache->table[index];
> >     read_unlock_irqrestore(&lh);
> >+    *gid = cgid;
> >
> >-    return ret;
> >+    return 0;
> > }
> >
> > int ib_find_cached_gid(struct ib_device *device, @@ -103,31 
> +105,32 @@
> >     struct ib_gid_cache *cache;
> >     int i;
> >     u8 p;
> >-    int ret = -ENOENT;
> >     SPIN_LOCK_PREP(lh);
> >
> >-    *port_num = (u8)-1;
> >-    if (index)
> >-            *index = (u16)-1;
> >-
> >     read_lock_irqsave(&device->cache.lock, &lh);
> >
> >     for (p = 0; p <= end_port(device) - start_port(device); ++p) {
> >             cache = device->cache.gid_cache[p];
> >             for (i = 0; i < cache->table_len; ++i) {
> >                     if (!memcmp(gid, &cache->table[i], 
> sizeof *gid)) {
> >-                            *port_num = p + start_port(device);
> >-                            if (index)
> >-                                    *index = (u16)i;
> >-                            ret = 0;
> >                             goto found;
> >                     }
> >             }
> >     }
> >+
> >+    read_unlock_irqrestore(&lh);
> >+    *port_num = (u8)-1;
> >+    if (index)
> >+            *index = (u16)-1;
> >+    return -ENOENT;
> >+
> > found:
> >     read_unlock_irqrestore(&lh);
> >+    *port_num = p + start_port(device);
> >+    if (index)
> >+            *index = (u16)i;
> >
> >-    return ret;
> >+    return 0;
> > }
> >
> > int ib_get_cached_pkey(struct ib_device *device, @@ -136,7 +139,7 @@
> >                    __be16           *pkey)
> > {
> >     struct ib_pkey_cache *cache;
> >-    int ret = 0;
> >+    __be16 cpkey;
> >     SPIN_LOCK_PREP(lh);
> >
> >     // sanity checks
> >@@ -149,14 +152,16 @@
> >
> >     cache = device->cache.pkey_cache[port_num - start_port(device)];
> >
> >-    if (index < 0 || index >= cache->table_len)
> >-            ret = -EINVAL;
> >-    else
> >-            *pkey = cache->table[index];
> >+    if (index < 0 || index >= cache->table_len) {
> >+            read_unlock_irqrestore(&lh);
> >+            return -EINVAL;
> >+    }
> >
> >+    cpkey = cache->table[index];
> >     read_unlock_irqrestore(&lh);
> >+    *pkey = cpkey;
> >
> >-    return ret;
> >+    return 0;
> > }
> >
> > int ib_find_cached_pkey(struct ib_device *device, @@ -166,7 
> +171,6 @@  
> >{
> >     struct ib_pkey_cache *cache;
> >     int i;
> >-    int ret = -ENOENT;
> >     SPIN_LOCK_PREP(lh);
> >
> >     if (port_num < start_port(device) || port_num > 
> end_port(device)) @@ 
> >-176,18 +180,19 @@
> >
> >     cache = device->cache.pkey_cache[port_num - start_port(device)];
> >
> >-    *index = (u16)-1;
> >-
> >     for (i = 0; i < cache->table_len; ++i)
> >             if ((cache->table[i] & 0x7fff) == (pkey & 0x7fff)) {
> >-                    *index = (u16)i;
> >-                    ret = 0;
> >-                    break;
> >+                    goto found;
> >             }
> >
> >     read_unlock_irqrestore(&lh);
> >+    *index = (u16)-1;
> >+    return -ENOENT;
> >
> >-    return ret;
> >+found:
> >+    read_unlock_irqrestore(&lh);
> >+    *index = (u16)i;
> >+    return 0;
> > }
> >
> > static void ib_cache_update(struct ib_device *device,
> >
> 
> 
> 
_______________________________________________
ofw mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/ofw

Reply via email to