Skip to content

Commit

Permalink
[PATCH] ibmveth: fix int rollover panic
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Santiago Leon authored and Jeff Garzik committed Oct 5, 2006
1 parent 03a85d0 commit 751ae21
Showing 1 changed file with 6 additions and 1 deletion.
7 changes: 6 additions & 1 deletion drivers/net/ibmveth.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
}

free_index = pool->consumer_index++ % pool->size;
pool->consumer_index = free_index;
index = pool->free_map[free_index];

ibmveth_assert(index != IBM_VETH_INVALID_MAP);
Expand All @@ -238,7 +239,10 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
if(lpar_rc != H_SUCCESS) {
pool->free_map[free_index] = index;
pool->skbuff[index] = NULL;
pool->consumer_index--;
if (pool->consumer_index == 0)
pool->consumer_index = pool->size - 1;
else
pool->consumer_index--;
dma_unmap_single(&adapter->vdev->dev,
pool->dma_addr[index], pool->buff_size,
DMA_FROM_DEVICE);
Expand Down Expand Up @@ -326,6 +330,7 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64
DMA_FROM_DEVICE);

free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size;
adapter->rx_buff_pool[pool].producer_index = free_index;
adapter->rx_buff_pool[pool].free_map[free_index] = index;

mb();
Expand Down

0 comments on commit 751ae21

Please sign in to comment.