From bbedefccc6b0da43cfaf785dac89c88bc59cb6ed Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 3 Oct 2006 12:24:23 -0500 Subject: [PATCH] ibmveth: Harden driver initilisation This patch has been floating around for a while now, Santi originally sent it in March: http://www.spinics.net/lists/netdev/msg00471.html After a kexec the ibmveth driver will fail when trying to register with the Hypervisor because the previous kernel has not unregistered. So if the registration fails, we unregister and then try again. We don't unconditionally unregister, because we don't want to disturb the regular code path for 99% of users. Signed-off-by: Michael Ellerman Acked-by: Anton Blanchard Signed-off-by: Santiago Leon Signed-off-by: Jeff Garzik --- drivers/net/ibmveth.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers/net/ibmveth.c') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 767203d35bc..df3a59efa7a 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -437,6 +437,31 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) &adapter->rx_buff_pool[i]); } +static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter, + union ibmveth_buf_desc rxq_desc, u64 mac_address) +{ + int rc, try_again = 1; + + /* After a kexec the adapter will still be open, so our attempt to + * open it will fail. So if we get a failure we free the adapter and + * try again, but only once. */ +retry: + rc = h_register_logical_lan(adapter->vdev->unit_address, + adapter->buffer_list_dma, rxq_desc.desc, + adapter->filter_list_dma, mac_address); + + if (rc != H_SUCCESS && try_again) { + do { + rc = h_free_logical_lan(adapter->vdev->unit_address); + } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY)); + + try_again = 0; + goto retry; + } + + return rc; +} + static int ibmveth_open(struct net_device *netdev) { struct ibmveth_adapter *adapter = netdev->priv; @@ -502,12 +527,7 @@ static int ibmveth_open(struct net_device *netdev) ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr); ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr); - - lpar_rc = h_register_logical_lan(adapter->vdev->unit_address, - adapter->buffer_list_dma, - rxq_desc.desc, - adapter->filter_list_dma, - mac_address); + lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address); if(lpar_rc != H_SUCCESS) { ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); -- cgit v1.2.3 From 6b4223748895ed5b200c8049231567ea399fc0c2 Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Tue, 3 Oct 2006 12:24:28 -0500 Subject: [PATCH] ibmveth: Add netpoll function This patch adds the net poll controller function to ibmveth to support netconsole and netdump. Signed-off-by: Santiago Leon Signed-off-by: Jeff Garzik --- drivers/net/ibmveth.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net/ibmveth.c') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index df3a59efa7a..bd79d67c0e9 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -925,6 +925,14 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void ibmveth_poll_controller(struct net_device *dev) +{ + ibmveth_replenish_task(dev->priv); + ibmveth_interrupt(dev->irq, dev, NULL); +} +#endif + static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) { int rc, i; @@ -997,6 +1005,9 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ netdev->ethtool_ops = &netdev_ethtool_ops; netdev->change_mtu = ibmveth_change_mtu; SET_NETDEV_DEV(netdev, &dev->dev); +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = ibmveth_poll_controller; +#endif netdev->features |= NETIF_F_LLTX; spin_lock_init(&adapter->stats_lock); -- cgit v1.2.3 From 4347ef15f76dca33ae8da769d6900a468253bda2 Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Tue, 3 Oct 2006 12:24:34 -0500 Subject: [PATCH] ibmveth: kdump interrupt fix This patch fixes a race that panics the kernel when opening the device after a kdump. Without this patch there is a window where the hypervisor can send an interrupt before all the structures for the kdump ibmveth module are ready (because the hypervisor is not aware that the partition crashed and that the virtual driver is reloading). We close this window by disabling the interrupts before registering the adapter to the hypervisor. This patch depends on the "ibmveth: Harden driver initilisation" patch. Signed-off-by: Santiago Leon Signed-off-by: Jeff Garzik --- drivers/net/ibmveth.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/ibmveth.c') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index bd79d67c0e9..2ec49d25453 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -527,6 +527,8 @@ static int ibmveth_open(struct net_device *netdev) ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr); ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr); + h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); + lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address); if(lpar_rc != H_SUCCESS) { -- cgit v1.2.3 From 03a85d0907b2455c772b8fb179b0c07a66b00ddb Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Tue, 3 Oct 2006 12:24:39 -0500 Subject: [PATCH] ibmveth: rename proc entry name This patch changes the name of the proc file for each ibmveth adapter from the network device name to the slot number in the virtual bus. The proc file is created when the device is probed, so a change in the name of the device will not be reflected in the name of the proc file giving problems when identifying and removing the adapter. The slot number is a property that does not change through the life of the adapter so we use that instead. Signed-off-by: Santiago Leon Signed-off-by: Jeff Garzik --- drivers/net/ibmveth.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net/ibmveth.c') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 2ec49d25453..6aff2bc3df5 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1165,7 +1165,9 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) { struct proc_dir_entry *entry; if (ibmveth_proc_dir) { - entry = create_proc_entry(adapter->netdev->name, S_IFREG, ibmveth_proc_dir); + char u_addr[10]; + sprintf(u_addr, "%x", adapter->vdev->unit_address); + entry = create_proc_entry(u_addr, S_IFREG, ibmveth_proc_dir); if (!entry) { ibmveth_error_printk("Cannot create adapter proc entry"); } else { @@ -1180,7 +1182,9 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) { if (ibmveth_proc_dir) { - remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir); + char u_addr[10]; + sprintf(u_addr, "%x", adapter->vdev->unit_address); + remove_proc_entry(u_addr, ibmveth_proc_dir); } } -- cgit v1.2.3 From 751ae21c6cd1493e3d0a4935b08fb298b9d89773 Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Tue, 3 Oct 2006 12:24:45 -0500 Subject: [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 Signed-off-by: Jeff Garzik --- drivers/net/ibmveth.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net/ibmveth.c') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 6aff2bc3df5..16f3faa7ea5 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 } 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); @@ -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); @@ -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(); -- cgit v1.2.3 From 5f77113c01d8a9f8193769d2ca73763047af39ef Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 10 Oct 2006 14:33:30 -0700 Subject: [PATCH] ibmveth irq fix drivers/net/ibmveth.c:939: error: too many arguments to function `ibmveth_interrupt' Cc: Jeff Garzik Cc: Anton Blanchard Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/ibmveth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ibmveth.c') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index bf414a93fac..2802db23d3c 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -936,7 +936,7 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) static void ibmveth_poll_controller(struct net_device *dev) { ibmveth_replenish_task(dev->priv); - ibmveth_interrupt(dev->irq, dev, NULL); + ibmveth_interrupt(dev->irq, dev); } #endif -- cgit v1.2.3 From 047a66d4bb24aaf19f41d620f8f0534c2153cd0b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 21 Oct 2006 10:24:13 -0700 Subject: [PATCH] ibmveth: Fix index increment calculation The recent commit 751ae21c6cd1493e3d0a4935b08fb298b9d89773 introduced a bug in the producer/consumer index calculation in the ibmveth driver - incautious use of the post-increment ++ operator resulted in an increment being immediately reverted. This patch corrects the logic. Without this patch, the driver oopses almost immediately after activation on at least some machines. Signed-off-by: David Gibson Acked-by: Santiago Leon Cc: Jeff Garzik Cc: Martin Schwidefsky Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ibmveth.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/ibmveth.c') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 2802db23d3c..44c9f993dcc 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -212,8 +212,8 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc break; } - free_index = pool->consumer_index++ % pool->size; - pool->consumer_index = free_index; + free_index = pool->consumer_index; + pool->consumer_index = (pool->consumer_index + 1) % pool->size; index = pool->free_map[free_index]; ibmveth_assert(index != IBM_VETH_INVALID_MAP); @@ -329,8 +329,10 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 adapter->rx_buff_pool[pool].buff_size, 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; + free_index = adapter->rx_buff_pool[pool].producer_index; + adapter->rx_buff_pool[pool].producer_index + = (adapter->rx_buff_pool[pool].producer_index + 1) + % adapter->rx_buff_pool[pool].size; adapter->rx_buff_pool[pool].free_map[free_index] = index; mb(); -- cgit v1.2.3