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

ixgbe: DCB, misallocated packet buffer size with X540 device

The X540 device has a smaller packet buffer but the DCB configuration
never took this into account. Under stress this can result in the DMA
engine hanging and TX Unit hang occurring to reset the device. This
patch reworks the packet buffer allocation routine used for DCB on
82599 and X540 devices to account for RX packet buffer sizes.

This fixes the immediate hang. We should consolidate the various
hardware specific routines for configuring features into a single
routine. This will make it much harder to miss feature cases like
this.

Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Tested-by: Evan Swanson <evan.swanson@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

John Fastabend and committed by
Jeff Kirsher
e09ad236 b776d104

+52 -27
+3
drivers/net/ixgbe/ixgbe_82598.c
··· 37 37 #define IXGBE_82598_RAR_ENTRIES 16 38 38 #define IXGBE_82598_MC_TBL_SIZE 128 39 39 #define IXGBE_82598_VFT_TBL_SIZE 128 40 + #define IXGBE_82598_RX_PB_SIZE 512 40 41 41 42 static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, 42 43 ixgbe_link_speed speed, ··· 224 223 IXGBE_DCA_RXCTRL_DESC_HSRO_EN); 225 224 IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 226 225 } 226 + 227 + hw->mac.rx_pb_size = IXGBE_82598_RX_PB_SIZE; 227 228 228 229 /* set the completion timeout for interface */ 229 230 if (ret_val == 0)
+2
drivers/net/ixgbe/ixgbe_82599.c
··· 38 38 #define IXGBE_82599_RAR_ENTRIES 128 39 39 #define IXGBE_82599_MC_TBL_SIZE 128 40 40 #define IXGBE_82599_VFT_TBL_SIZE 128 41 + #define IXGBE_82599_RX_PB_SIZE 512 41 42 42 43 static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); 43 44 static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); ··· 1766 1765 1767 1766 /* We need to run link autotry after the driver loads */ 1768 1767 hw->mac.autotry_restart = true; 1768 + hw->mac.rx_pb_size = IXGBE_82599_RX_PB_SIZE; 1769 1769 1770 1770 if (ret_val == 0) 1771 1771 ret_val = ixgbe_verify_fw_version_82599(hw);
+42 -26
drivers/net/ixgbe/ixgbe_dcb_82599.c
··· 39 39 */ 40 40 static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, u8 rx_pba) 41 41 { 42 - s32 ret_val = 0; 43 - u32 value = IXGBE_RXPBSIZE_64KB; 42 + int num_tcs = IXGBE_MAX_PACKET_BUFFERS; 43 + u32 rx_pb_size = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT; 44 + u32 rxpktsize; 45 + u32 txpktsize; 46 + u32 txpbthresh; 44 47 u8 i = 0; 45 48 46 - /* Setup Rx packet buffer sizes */ 47 - switch (rx_pba) { 48 - case pba_80_48: 49 - /* Setup the first four at 80KB */ 50 - value = IXGBE_RXPBSIZE_80KB; 51 - for (; i < 4; i++) 52 - IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value); 53 - /* Setup the last four at 48KB...don't re-init i */ 54 - value = IXGBE_RXPBSIZE_48KB; 55 - /* Fall Through */ 56 - case pba_equal: 57 - default: 58 - for (; i < IXGBE_MAX_PACKET_BUFFERS; i++) 59 - IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value); 60 - 61 - /* Setup Tx packet buffer sizes */ 62 - for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) { 63 - IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 64 - IXGBE_TXPBSIZE_20KB); 65 - IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 66 - IXGBE_TXPBTHRESH_DCB); 67 - } 68 - break; 49 + /* 50 + * This really means configure the first half of the TCs 51 + * (Traffic Classes) to use 5/8 of the Rx packet buffer 52 + * space. To determine the size of the buffer for each TC, 53 + * we are multiplying the average size by 5/4 and applying 54 + * it to half of the traffic classes. 55 + */ 56 + if (rx_pba == pba_80_48) { 57 + rxpktsize = (rx_pb_size * 5) / (num_tcs * 4); 58 + rx_pb_size -= rxpktsize * (num_tcs / 2); 59 + for (; i < (num_tcs / 2); i++) 60 + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 69 61 } 70 62 71 - return ret_val; 63 + /* Divide the remaining Rx packet buffer evenly among the TCs */ 64 + rxpktsize = rx_pb_size / (num_tcs - i); 65 + for (; i < num_tcs; i++) 66 + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 67 + 68 + /* 69 + * Setup Tx packet buffer and threshold equally for all TCs 70 + * TXPBTHRESH register is set in K so divide by 1024 and subtract 71 + * 10 since the largest packet we support is just over 9K. 72 + */ 73 + txpktsize = IXGBE_TXPBSIZE_MAX / num_tcs; 74 + txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; 75 + for (i = 0; i < num_tcs; i++) { 76 + IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); 77 + IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); 78 + } 79 + 80 + /* Clear unused TCs, if any, to zero buffer size*/ 81 + for (; i < MAX_TRAFFIC_CLASS; i++) { 82 + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 83 + IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); 84 + IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); 85 + } 86 + 87 + return 0; 72 88 } 73 89 74 90 /**
+2
drivers/net/ixgbe/ixgbe_dcb_82599.h
··· 92 92 #define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */ 93 93 #define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */ 94 94 #define IXGBE_RXPBSIZE_128KB 0x00020000 /* 128KB Packet Buffer */ 95 + #define IXGBE_TXPBSIZE_MAX 0x00028000 /* 160KB Packet Buffer*/ 95 96 96 97 #define IXGBE_TXPBTHRESH_DCB 0xA /* THRESH value for DCB mode */ 98 + #define IXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */ 97 99 98 100 /* SECTXMINIFG DCB */ 99 101 #define IXGBE_SECTX_DCB 0x00001F00 /* DCB TX Buffer IFG */
+1
drivers/net/ixgbe/ixgbe_type.h
··· 2606 2606 u32 vft_size; 2607 2607 u32 num_rar_entries; 2608 2608 u32 rar_highwater; 2609 + u32 rx_pb_size; 2609 2610 u32 max_tx_queues; 2610 2611 u32 max_rx_queues; 2611 2612 u32 max_msix_vectors;
+2 -1
drivers/net/ixgbe/ixgbe_x540.c
··· 37 37 #define IXGBE_X540_RAR_ENTRIES 128 38 38 #define IXGBE_X540_MC_TBL_SIZE 128 39 39 #define IXGBE_X540_VFT_TBL_SIZE 128 40 + #define IXGBE_X540_RX_PB_SIZE 384 40 41 41 42 static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw); 42 43 static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw); ··· 243 242 goto out; 244 243 245 244 ret_val = ixgbe_start_hw_gen2(hw); 246 - 245 + hw->mac.rx_pb_size = IXGBE_X540_RX_PB_SIZE; 247 246 out: 248 247 return ret_val; 249 248 }