[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