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
