[ofw] [PATCH] mthca/mlx4: allow retrieving CA attributes with pageable memory
Sean Hefty
sean.hefty at intel.com
Tue Aug 25 14:08:34 PDT 2009
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,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: hw-pagepool.diff
Type: application/octet-stream
Size: 6658 bytes
Desc: not available
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20090825/a9899d98/attachment.obj>
More information about the ofw
mailing list