aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSantiago Leon <santil@us.ibm.com>2006-10-03 13:24:45 -0400
committerJeff Garzik <jeff@garzik.org>2006-10-05 06:43:24 -0400
commit751ae21c6cd1493e3d0a4935b08fb298b9d89773 (patch)
treef0cd58c2c357101b6f6cf610221cceca3f6eef9c
parent03a85d0907b2455c772b8fb179b0c07a66b00ddb (diff)
[PATCH] ibmveth: fix int rollover panic
This patch fixes a nasty bug that has been sitting there since the very first versions of the driver, but is generating a panic because we changed the number of 2K buffers for 2.6.16. The consumer_index and producer_index are u32's that get incremented on every buffer emptied and replenished respectively. We use the {producer,consumer}_index mod'ed with the size of the pool to pick out an entry in the free_map. The problem happens when the u32 rolls over and the number of the buffers in the pool is not a perfect divisor of 2^32. i.e. if the number of 2K buffers is 0x300, before the consumer_index rolls over, our index to the free map = 0xffffffff mod 0x300 = 0xff. The next time a buffer is emptied, we want the index to the free map to be 0x100, but 0x0 mod 0x300 is 0x0. This patch assigns the mod'ed result back to the consumer and producer indexes so that they never roll over. The second chunk of the patch covers the unlikely case where the consumer_index has just been reset to 0x0 and the hypervisor is not able to accept that buffer. Signed-off-by: Santiago Leon <santil@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/ibmveth.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 6aff2bc3df55..16f3faa7ea5b 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -213,6 +213,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
213 } 213 }
214 214
215 free_index = pool->consumer_index++ % pool->size; 215 free_index = pool->consumer_index++ % pool->size;
216 pool->consumer_index = free_index;
216 index = pool->free_map[free_index]; 217 index = pool->free_map[free_index];
217 218
218 ibmveth_assert(index != IBM_VETH_INVALID_MAP); 219 ibmveth_assert(index != IBM_VETH_INVALID_MAP);
@@ -238,7 +239,10 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
238 if(lpar_rc != H_SUCCESS) { 239 if(lpar_rc != H_SUCCESS) {
239 pool->free_map[free_index] = index; 240 pool->free_map[free_index] = index;
240 pool->skbuff[index] = NULL; 241 pool->skbuff[index] = NULL;
241 pool->consumer_index--; 242 if (pool->consumer_index == 0)
243 pool->consumer_index = pool->size - 1;
244 else
245 pool->consumer_index--;
242 dma_unmap_single(&adapter->vdev->dev, 246 dma_unmap_single(&adapter->vdev->dev,
243 pool->dma_addr[index], pool->buff_size, 247 pool->dma_addr[index], pool->buff_size,
244 DMA_FROM_DEVICE); 248 DMA_FROM_DEVICE);
@@ -326,6 +330,7 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64
326 DMA_FROM_DEVICE); 330 DMA_FROM_DEVICE);
327 331
328 free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size; 332 free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size;
333 adapter->rx_buff_pool[pool].producer_index = free_index;
329 adapter->rx_buff_pool[pool].free_map[free_index] = index; 334 adapter->rx_buff_pool[pool].free_map[free_index] = index;
330 335
331 mb(); 336 mb();