Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-ibmveth-make-ibmveth-use-new-reset-function-and-new-kunit-testsg'

Dave Marquardt says:

====================
net: ibmveth: Make ibmveth use new reset function and new KUnit testsg

- Fixed struct ibmveth_adapter indentation
- Made ibmveth driver use WARN_ON with recovery rather than BUG_ON. Some
recovery code schedules a reset through new function ibmveth_reset. Also
removed a conflicting and unneeded forward declaration.
- Added KUnit tests for some areas changed by the WARN_ON changes.
====================

Link: https://patch.msgid.link/20250501194944.283729-1-davemarq@linux.ibm.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+273 -50
+13
drivers/net/ethernet/ibm/Kconfig
··· 27 27 To compile this driver as a module, choose M here. The module will 28 28 be called ibmveth. 29 29 30 + config IBMVETH_KUNIT_TEST 31 + bool "KUnit test for IBM LAN Virtual Ethernet support" if !KUNIT_ALL_TESTS 32 + depends on KUNIT 33 + depends on KUNIT=y && IBMVETH=y 34 + default KUNIT_ALL_TESTS 35 + help 36 + This builds unit tests for the IBM LAN Virtual Ethernet driver. 37 + 38 + For more information on KUnit and unit tests in general, please refer 39 + to the KUnit documentation in Documentation/dev-tools/kunit/. 40 + 41 + If unsure, say N. 42 + 30 43 source "drivers/net/ethernet/ibm/emac/Kconfig" 31 44 32 45 config EHEA
+228 -19
drivers/net/ethernet/ibm/ibmveth.c
··· 39 39 #include "ibmveth.h" 40 40 41 41 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance); 42 - static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter, 43 - bool reuse); 44 42 static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev); 45 43 46 44 static struct kobj_type ktype_veth_pool; ··· 229 231 index = pool->free_map[free_index]; 230 232 skb = NULL; 231 233 232 - BUG_ON(index == IBM_VETH_INVALID_MAP); 234 + if (WARN_ON(index == IBM_VETH_INVALID_MAP)) { 235 + schedule_work(&adapter->work); 236 + goto bad_index_failure; 237 + } 233 238 234 239 /* are we allocating a new buffer or recycling an old one */ 235 240 if (pool->skbuff[index]) ··· 301 300 DMA_FROM_DEVICE); 302 301 dev_kfree_skb_any(pool->skbuff[index]); 303 302 pool->skbuff[index] = NULL; 303 + bad_index_failure: 304 304 adapter->replenish_add_buff_failure++; 305 305 306 306 mb(); ··· 372 370 } 373 371 } 374 372 375 - /* remove a buffer from a pool */ 376 - static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, 377 - u64 correlator, bool reuse) 373 + /** 374 + * ibmveth_remove_buffer_from_pool - remove a buffer from a pool 375 + * @adapter: adapter instance 376 + * @correlator: identifies pool and index 377 + * @reuse: whether to reuse buffer 378 + * 379 + * Return: 380 + * * %0 - success 381 + * * %-EINVAL - correlator maps to pool or index out of range 382 + * * %-EFAULT - pool and index map to null skb 383 + */ 384 + static int ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, 385 + u64 correlator, bool reuse) 378 386 { 379 387 unsigned int pool = correlator >> 32; 380 388 unsigned int index = correlator & 0xffffffffUL; 381 389 unsigned int free_index; 382 390 struct sk_buff *skb; 383 391 384 - BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); 385 - BUG_ON(index >= adapter->rx_buff_pool[pool].size); 392 + if (WARN_ON(pool >= IBMVETH_NUM_BUFF_POOLS) || 393 + WARN_ON(index >= adapter->rx_buff_pool[pool].size)) { 394 + schedule_work(&adapter->work); 395 + return -EINVAL; 396 + } 386 397 387 398 skb = adapter->rx_buff_pool[pool].skbuff[index]; 388 - BUG_ON(skb == NULL); 399 + if (WARN_ON(!skb)) { 400 + schedule_work(&adapter->work); 401 + return -EFAULT; 402 + } 389 403 390 404 /* if we are going to reuse the buffer then keep the pointers around 391 405 * but mark index as available. replenish will see the skb pointer and ··· 429 411 mb(); 430 412 431 413 atomic_dec(&(adapter->rx_buff_pool[pool].available)); 414 + 415 + return 0; 432 416 } 433 417 434 418 /* get the current buffer on the rx queue */ ··· 440 420 unsigned int pool = correlator >> 32; 441 421 unsigned int index = correlator & 0xffffffffUL; 442 422 443 - BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); 444 - BUG_ON(index >= adapter->rx_buff_pool[pool].size); 423 + if (WARN_ON(pool >= IBMVETH_NUM_BUFF_POOLS) || 424 + WARN_ON(index >= adapter->rx_buff_pool[pool].size)) { 425 + schedule_work(&adapter->work); 426 + return NULL; 427 + } 445 428 446 429 return adapter->rx_buff_pool[pool].skbuff[index]; 447 430 } 448 431 449 - static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter, 450 - bool reuse) 432 + /** 433 + * ibmveth_rxq_harvest_buffer - Harvest buffer from pool 434 + * 435 + * @adapter: pointer to adapter 436 + * @reuse: whether to reuse buffer 437 + * 438 + * Context: called from ibmveth_poll 439 + * 440 + * Return: 441 + * * %0 - success 442 + * * other - non-zero return from ibmveth_remove_buffer_from_pool 443 + */ 444 + static int ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter, 445 + bool reuse) 451 446 { 452 447 u64 cor; 448 + int rc; 453 449 454 450 cor = adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator; 455 - ibmveth_remove_buffer_from_pool(adapter, cor, reuse); 451 + rc = ibmveth_remove_buffer_from_pool(adapter, cor, reuse); 452 + if (unlikely(rc)) 453 + return rc; 456 454 457 455 if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { 458 456 adapter->rx_queue.index = 0; 459 457 adapter->rx_queue.toggle = !adapter->rx_queue.toggle; 460 458 } 459 + 460 + return 0; 461 461 } 462 462 463 463 static void ibmveth_free_tx_ltb(struct ibmveth_adapter *adapter, int idx) ··· 747 707 netdev_dbg(netdev, "close complete\n"); 748 708 749 709 return 0; 710 + } 711 + 712 + /** 713 + * ibmveth_reset - Handle scheduled reset work 714 + * 715 + * @w: pointer to work_struct embedded in adapter structure 716 + * 717 + * Context: This routine acquires rtnl_mutex and disables its NAPI through 718 + * ibmveth_close. It can't be called directly in a context that has 719 + * already acquired rtnl_mutex or disabled its NAPI, or directly from 720 + * a poll routine. 721 + * 722 + * Return: void 723 + */ 724 + static void ibmveth_reset(struct work_struct *w) 725 + { 726 + struct ibmveth_adapter *adapter = container_of(w, struct ibmveth_adapter, work); 727 + struct net_device *netdev = adapter->netdev; 728 + 729 + netdev_dbg(netdev, "reset starting\n"); 730 + 731 + rtnl_lock(); 732 + 733 + dev_close(adapter->netdev); 734 + dev_open(adapter->netdev, NULL); 735 + 736 + rtnl_unlock(); 737 + 738 + netdev_dbg(netdev, "reset complete\n"); 750 739 } 751 740 752 741 static int ibmveth_set_link_ksettings(struct net_device *dev, ··· 1393 1324 wmb(); /* suggested by larson1 */ 1394 1325 adapter->rx_invalid_buffer++; 1395 1326 netdev_dbg(netdev, "recycling invalid buffer\n"); 1396 - ibmveth_rxq_harvest_buffer(adapter, true); 1327 + if (unlikely(ibmveth_rxq_harvest_buffer(adapter, true))) 1328 + break; 1397 1329 } else { 1398 1330 struct sk_buff *skb, *new_skb; 1399 1331 int length = ibmveth_rxq_frame_length(adapter); ··· 1404 1334 __sum16 iph_check = 0; 1405 1335 1406 1336 skb = ibmveth_rxq_get_buffer(adapter); 1337 + if (unlikely(!skb)) 1338 + break; 1407 1339 1408 1340 /* if the large packet bit is set in the rx queue 1409 1341 * descriptor, the mss will be written by PHYP eight ··· 1429 1357 if (rx_flush) 1430 1358 ibmveth_flush_buffer(skb->data, 1431 1359 length + offset); 1432 - ibmveth_rxq_harvest_buffer(adapter, true); 1360 + if (unlikely(ibmveth_rxq_harvest_buffer(adapter, true))) 1361 + break; 1433 1362 skb = new_skb; 1434 1363 } else { 1435 - ibmveth_rxq_harvest_buffer(adapter, false); 1364 + if (unlikely(ibmveth_rxq_harvest_buffer(adapter, false))) 1365 + break; 1436 1366 skb_reserve(skb, offset); 1437 1367 } 1438 1368 ··· 1481 1407 * then check once more to make sure we are done. 1482 1408 */ 1483 1409 lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE); 1484 - BUG_ON(lpar_rc != H_SUCCESS); 1410 + if (WARN_ON(lpar_rc != H_SUCCESS)) { 1411 + schedule_work(&adapter->work); 1412 + goto out; 1413 + } 1485 1414 1486 1415 if (ibmveth_rxq_pending_buffer(adapter) && napi_schedule(napi)) { 1487 1416 lpar_rc = h_vio_signal(adapter->vdev->unit_address, ··· 1505 1428 if (napi_schedule_prep(&adapter->napi)) { 1506 1429 lpar_rc = h_vio_signal(adapter->vdev->unit_address, 1507 1430 VIO_IRQ_DISABLE); 1508 - BUG_ON(lpar_rc != H_SUCCESS); 1431 + WARN_ON(lpar_rc != H_SUCCESS); 1509 1432 __napi_schedule(&adapter->napi); 1510 1433 } 1511 1434 return IRQ_HANDLED; ··· 1747 1670 1748 1671 adapter->vdev = dev; 1749 1672 adapter->netdev = netdev; 1673 + INIT_WORK(&adapter->work, ibmveth_reset); 1750 1674 adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p); 1751 1675 ibmveth_init_link_settings(netdev); 1752 1676 ··· 1839 1761 struct net_device *netdev = dev_get_drvdata(&dev->dev); 1840 1762 struct ibmveth_adapter *adapter = netdev_priv(netdev); 1841 1763 int i; 1764 + 1765 + cancel_work_sync(&adapter->work); 1842 1766 1843 1767 for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) 1844 1768 kobject_put(&adapter->rx_buff_pool[i].kobj); ··· 2042 1962 2043 1963 module_init(ibmveth_module_init); 2044 1964 module_exit(ibmveth_module_exit); 1965 + 1966 + #ifdef CONFIG_IBMVETH_KUNIT_TEST 1967 + #include <kunit/test.h> 1968 + 1969 + /** 1970 + * ibmveth_reset_kunit - reset routine for running in KUnit environment 1971 + * 1972 + * @w: pointer to work_struct embedded in adapter structure 1973 + * 1974 + * Context: Called in the KUnit environment. Does nothing. 1975 + * 1976 + * Return: void 1977 + */ 1978 + static void ibmveth_reset_kunit(struct work_struct *w) 1979 + { 1980 + netdev_dbg(NULL, "reset_kunit starting\n"); 1981 + netdev_dbg(NULL, "reset_kunit complete\n"); 1982 + } 1983 + 1984 + /** 1985 + * ibmveth_remove_buffer_from_pool_test - unit test for some of 1986 + * ibmveth_remove_buffer_from_pool 1987 + * @test: pointer to kunit structure 1988 + * 1989 + * Tests the error returns from ibmveth_remove_buffer_from_pool. 1990 + * ibmveth_remove_buffer_from_pool also calls WARN_ON, so dmesg should be 1991 + * checked to see that these warnings happened. 1992 + * 1993 + * Return: void 1994 + */ 1995 + static void ibmveth_remove_buffer_from_pool_test(struct kunit *test) 1996 + { 1997 + struct ibmveth_adapter *adapter = kunit_kzalloc(test, sizeof(*adapter), GFP_KERNEL); 1998 + struct ibmveth_buff_pool *pool; 1999 + u64 correlator; 2000 + 2001 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adapter); 2002 + 2003 + INIT_WORK(&adapter->work, ibmveth_reset_kunit); 2004 + 2005 + /* Set sane values for buffer pools */ 2006 + for (int i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) 2007 + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, 2008 + pool_count[i], pool_size[i], 2009 + pool_active[i]); 2010 + 2011 + pool = &adapter->rx_buff_pool[0]; 2012 + pool->skbuff = kunit_kcalloc(test, pool->size, sizeof(void *), GFP_KERNEL); 2013 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pool->skbuff); 2014 + 2015 + correlator = ((u64)IBMVETH_NUM_BUFF_POOLS << 32) | 0; 2016 + KUNIT_EXPECT_EQ(test, -EINVAL, ibmveth_remove_buffer_from_pool(adapter, correlator, false)); 2017 + KUNIT_EXPECT_EQ(test, -EINVAL, ibmveth_remove_buffer_from_pool(adapter, correlator, true)); 2018 + 2019 + correlator = ((u64)0 << 32) | adapter->rx_buff_pool[0].size; 2020 + KUNIT_EXPECT_EQ(test, -EINVAL, ibmveth_remove_buffer_from_pool(adapter, correlator, false)); 2021 + KUNIT_EXPECT_EQ(test, -EINVAL, ibmveth_remove_buffer_from_pool(adapter, correlator, true)); 2022 + 2023 + correlator = (u64)0 | 0; 2024 + pool->skbuff[0] = NULL; 2025 + KUNIT_EXPECT_EQ(test, -EFAULT, ibmveth_remove_buffer_from_pool(adapter, correlator, false)); 2026 + KUNIT_EXPECT_EQ(test, -EFAULT, ibmveth_remove_buffer_from_pool(adapter, correlator, true)); 2027 + 2028 + flush_work(&adapter->work); 2029 + } 2030 + 2031 + /** 2032 + * ibmveth_rxq_get_buffer_test - unit test for ibmveth_rxq_get_buffer 2033 + * @test: pointer to kunit structure 2034 + * 2035 + * Tests ibmveth_rxq_get_buffer. ibmveth_rxq_get_buffer also calls WARN_ON for 2036 + * the NULL returns, so dmesg should be checked to see that these warnings 2037 + * happened. 2038 + * 2039 + * Return: void 2040 + */ 2041 + static void ibmveth_rxq_get_buffer_test(struct kunit *test) 2042 + { 2043 + struct ibmveth_adapter *adapter = kunit_kzalloc(test, sizeof(*adapter), GFP_KERNEL); 2044 + struct sk_buff *skb = kunit_kzalloc(test, sizeof(*skb), GFP_KERNEL); 2045 + struct ibmveth_buff_pool *pool; 2046 + 2047 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adapter); 2048 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb); 2049 + 2050 + INIT_WORK(&adapter->work, ibmveth_reset_kunit); 2051 + 2052 + adapter->rx_queue.queue_len = 1; 2053 + adapter->rx_queue.index = 0; 2054 + adapter->rx_queue.queue_addr = kunit_kzalloc(test, sizeof(struct ibmveth_rx_q_entry), 2055 + GFP_KERNEL); 2056 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adapter->rx_queue.queue_addr); 2057 + 2058 + /* Set sane values for buffer pools */ 2059 + for (int i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) 2060 + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, 2061 + pool_count[i], pool_size[i], 2062 + pool_active[i]); 2063 + 2064 + pool = &adapter->rx_buff_pool[0]; 2065 + pool->skbuff = kunit_kcalloc(test, pool->size, sizeof(void *), GFP_KERNEL); 2066 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pool->skbuff); 2067 + 2068 + adapter->rx_queue.queue_addr[0].correlator = (u64)IBMVETH_NUM_BUFF_POOLS << 32 | 0; 2069 + KUNIT_EXPECT_PTR_EQ(test, NULL, ibmveth_rxq_get_buffer(adapter)); 2070 + 2071 + adapter->rx_queue.queue_addr[0].correlator = (u64)0 << 32 | adapter->rx_buff_pool[0].size; 2072 + KUNIT_EXPECT_PTR_EQ(test, NULL, ibmveth_rxq_get_buffer(adapter)); 2073 + 2074 + pool->skbuff[0] = skb; 2075 + adapter->rx_queue.queue_addr[0].correlator = (u64)0 << 32 | 0; 2076 + KUNIT_EXPECT_PTR_EQ(test, skb, ibmveth_rxq_get_buffer(adapter)); 2077 + 2078 + flush_work(&adapter->work); 2079 + } 2080 + 2081 + static struct kunit_case ibmveth_test_cases[] = { 2082 + KUNIT_CASE(ibmveth_remove_buffer_from_pool_test), 2083 + KUNIT_CASE(ibmveth_rxq_get_buffer_test), 2084 + {} 2085 + }; 2086 + 2087 + static struct kunit_suite ibmveth_test_suite = { 2088 + .name = "ibmveth-kunit-test", 2089 + .test_cases = ibmveth_test_cases, 2090 + }; 2091 + 2092 + kunit_test_suite(ibmveth_test_suite); 2093 + #endif
+32 -31
drivers/net/ethernet/ibm/ibmveth.h
··· 134 134 }; 135 135 136 136 struct ibmveth_adapter { 137 - struct vio_dev *vdev; 138 - struct net_device *netdev; 139 - struct napi_struct napi; 140 - unsigned int mcastFilterSize; 141 - void * buffer_list_addr; 142 - void * filter_list_addr; 143 - void *tx_ltb_ptr[IBMVETH_MAX_QUEUES]; 144 - unsigned int tx_ltb_size; 145 - dma_addr_t tx_ltb_dma[IBMVETH_MAX_QUEUES]; 146 - dma_addr_t buffer_list_dma; 147 - dma_addr_t filter_list_dma; 148 - struct ibmveth_buff_pool rx_buff_pool[IBMVETH_NUM_BUFF_POOLS]; 149 - struct ibmveth_rx_q rx_queue; 150 - int rx_csum; 151 - int large_send; 152 - bool is_active_trunk; 137 + struct vio_dev *vdev; 138 + struct net_device *netdev; 139 + struct napi_struct napi; 140 + struct work_struct work; 141 + unsigned int mcastFilterSize; 142 + void *buffer_list_addr; 143 + void *filter_list_addr; 144 + void *tx_ltb_ptr[IBMVETH_MAX_QUEUES]; 145 + unsigned int tx_ltb_size; 146 + dma_addr_t tx_ltb_dma[IBMVETH_MAX_QUEUES]; 147 + dma_addr_t buffer_list_dma; 148 + dma_addr_t filter_list_dma; 149 + struct ibmveth_buff_pool rx_buff_pool[IBMVETH_NUM_BUFF_POOLS]; 150 + struct ibmveth_rx_q rx_queue; 151 + int rx_csum; 152 + int large_send; 153 + bool is_active_trunk; 153 154 154 - u64 fw_ipv6_csum_support; 155 - u64 fw_ipv4_csum_support; 156 - u64 fw_large_send_support; 157 - /* adapter specific stats */ 158 - u64 replenish_task_cycles; 159 - u64 replenish_no_mem; 160 - u64 replenish_add_buff_failure; 161 - u64 replenish_add_buff_success; 162 - u64 rx_invalid_buffer; 163 - u64 rx_no_buffer; 164 - u64 tx_map_failed; 165 - u64 tx_send_failed; 166 - u64 tx_large_packets; 167 - u64 rx_large_packets; 168 - /* Ethtool settings */ 155 + u64 fw_ipv6_csum_support; 156 + u64 fw_ipv4_csum_support; 157 + u64 fw_large_send_support; 158 + /* adapter specific stats */ 159 + u64 replenish_task_cycles; 160 + u64 replenish_no_mem; 161 + u64 replenish_add_buff_failure; 162 + u64 replenish_add_buff_success; 163 + u64 rx_invalid_buffer; 164 + u64 rx_no_buffer; 165 + u64 tx_map_failed; 166 + u64 tx_send_failed; 167 + u64 tx_large_packets; 168 + u64 rx_large_packets; 169 + /* Ethtool settings */ 169 170 u8 duplex; 170 171 u32 speed; 171 172 };