[ofw] [PATCH] mthca/mlx4: allow retrieving CA attributes withpageable memory
Leonid Keller
leonid at mellanox.co.il
Wed Sep 2 08:17:45 PDT 2009
Applied to the trunk and the branch (2408, 2411).
Sorry for the delay.
> -----Original Message-----
> From: Sean Hefty [mailto:sean.hefty at intel.com]
> Sent: Wednesday, September 02, 2009 5:53 PM
> To: ofw at lists.openfabrics.org; 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 <sean.hefty at intel.com>
> >---
> >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,
> >
>
>
>
More information about the ofw
mailing list