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

i40e/i40evf: Do not free the dummy packet buffer synchronously

The HW still needs to consume it and freeing it in the function
that created it would mean we will be racing with the HW. The
i40e_clean_tx_ring() routine will free up the buffer attached once
the HW has consumed it. The clean_fdir_tx_irq function had to be fixed
to handle the freeing correctly.

Cases where we program more than one filter per flow (Ipv4), the
code had to be changed to allocate dummy buffer multiple times
since it will be freed by the clean routine. This also fixes an issue
where the filter program routine was not checking if there were
descriptors available for programming a filter.

Change-ID: Idf72028fd873221934e319d021ef65a1e51acaf7
Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com>
Tested-by: Jim Young <jamesx.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

Anjali Singhai Jain and committed by
Jeff Kirsher
49d7d933 bd4578bc

+96 -52
+19 -2
drivers/net/ethernet/intel/i40e/i40e_main.c
··· 3087 3087 /* clear next_to_watch to prevent false hangs */ 3088 3088 tx_buf->next_to_watch = NULL; 3089 3089 3090 + tx_desc->buffer_addr = 0; 3091 + tx_desc->cmd_type_offset_bsz = 0; 3092 + /* move past filter desc */ 3093 + tx_buf++; 3094 + tx_desc++; 3095 + i++; 3096 + if (unlikely(!i)) { 3097 + i -= tx_ring->count; 3098 + tx_buf = tx_ring->tx_bi; 3099 + tx_desc = I40E_TX_DESC(tx_ring, 0); 3100 + } 3090 3101 /* unmap skb header data */ 3091 3102 dma_unmap_single(tx_ring->dev, 3092 3103 dma_unmap_addr(tx_buf, dma), 3093 3104 dma_unmap_len(tx_buf, len), 3094 3105 DMA_TO_DEVICE); 3106 + if (tx_buf->tx_flags & I40E_TX_FLAGS_FD_SB) 3107 + kfree(tx_buf->raw_buf); 3095 3108 3109 + tx_buf->raw_buf = NULL; 3110 + tx_buf->tx_flags = 0; 3111 + tx_buf->next_to_watch = NULL; 3096 3112 dma_unmap_len_set(tx_buf, len, 0); 3113 + tx_desc->buffer_addr = 0; 3114 + tx_desc->cmd_type_offset_bsz = 0; 3097 3115 3098 - 3099 - /* move to the next desc and buffer to clean */ 3116 + /* move us past the eop_desc for start of next FD desc */ 3100 3117 tx_buf++; 3101 3118 tx_desc++; 3102 3119 i++;
+62 -47
drivers/net/ethernet/intel/i40e/i40e_txrx.c
··· 39 39 } 40 40 41 41 #define I40E_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS) 42 + #define I40E_FD_CLEAN_DELAY 10 42 43 /** 43 44 * i40e_program_fdir_filter - Program a Flow Director filter 44 45 * @fdir_data: Packet data that will be filter parameters ··· 51 50 struct i40e_pf *pf, bool add) 52 51 { 53 52 struct i40e_filter_program_desc *fdir_desc; 54 - struct i40e_tx_buffer *tx_buf; 53 + struct i40e_tx_buffer *tx_buf, *first; 55 54 struct i40e_tx_desc *tx_desc; 56 55 struct i40e_ring *tx_ring; 57 56 unsigned int fpt, dcc; ··· 59 58 struct device *dev; 60 59 dma_addr_t dma; 61 60 u32 td_cmd = 0; 61 + u16 delay = 0; 62 62 u16 i; 63 63 64 64 /* find existing FDIR VSI */ ··· 73 71 tx_ring = vsi->tx_rings[0]; 74 72 dev = tx_ring->dev; 75 73 74 + /* we need two descriptors to add/del a filter and we can wait */ 75 + do { 76 + if (I40E_DESC_UNUSED(tx_ring) > 1) 77 + break; 78 + msleep_interruptible(1); 79 + delay++; 80 + } while (delay < I40E_FD_CLEAN_DELAY); 81 + 82 + if (!(I40E_DESC_UNUSED(tx_ring) > 1)) 83 + return -EAGAIN; 84 + 76 85 dma = dma_map_single(dev, raw_packet, 77 86 I40E_FDIR_MAX_RAW_PACKET_SIZE, DMA_TO_DEVICE); 78 87 if (dma_mapping_error(dev, dma)) ··· 92 79 /* grab the next descriptor */ 93 80 i = tx_ring->next_to_use; 94 81 fdir_desc = I40E_TX_FDIRDESC(tx_ring, i); 82 + first = &tx_ring->tx_bi[i]; 83 + memset(first, 0, sizeof(struct i40e_tx_buffer)); 95 84 96 - tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0; 85 + tx_ring->next_to_use = ((i + 1) < tx_ring->count) ? i + 1 : 0; 97 86 98 87 fpt = (fdir_data->q_index << I40E_TXD_FLTR_QW0_QINDEX_SHIFT) & 99 88 I40E_TXD_FLTR_QW0_QINDEX_MASK; ··· 147 132 tx_desc = I40E_TX_DESC(tx_ring, i); 148 133 tx_buf = &tx_ring->tx_bi[i]; 149 134 150 - tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0; 135 + tx_ring->next_to_use = ((i + 1) < tx_ring->count) ? i + 1 : 0; 136 + 137 + memset(tx_buf, 0, sizeof(struct i40e_tx_buffer)); 151 138 152 139 /* record length, and DMA address */ 153 140 dma_unmap_len_set(tx_buf, len, I40E_FDIR_MAX_RAW_PACKET_SIZE); ··· 158 141 tx_desc->buffer_addr = cpu_to_le64(dma); 159 142 td_cmd = I40E_TXD_CMD | I40E_TX_DESC_CMD_DUMMY; 160 143 144 + tx_buf->tx_flags = I40E_TX_FLAGS_FD_SB; 145 + tx_buf->raw_buf = (void *)raw_packet; 146 + 161 147 tx_desc->cmd_type_offset_bsz = 162 148 build_ctob(td_cmd, 0, I40E_FDIR_MAX_RAW_PACKET_SIZE, 0); 163 149 ··· 168 148 tx_buf->time_stamp = jiffies; 169 149 170 150 /* Force memory writes to complete before letting h/w 171 - * know there are new descriptors to fetch. (Only 172 - * applicable for weak-ordered memory model archs, 173 - * such as IA-64). 151 + * know there are new descriptors to fetch. 174 152 */ 175 153 wmb(); 176 154 177 155 /* Mark the data descriptor to be watched */ 178 - tx_buf->next_to_watch = tx_desc; 156 + first->next_to_watch = tx_desc; 179 157 180 158 writel(tx_ring->next_to_use, tx_ring->tail); 181 159 return 0; ··· 188 170 * i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 filters 189 171 * @vsi: pointer to the targeted VSI 190 172 * @fd_data: the flow director data required for the FDir descriptor 191 - * @raw_packet: the pre-allocated packet buffer for FDir 192 173 * @add: true adds a filter, false removes it 193 174 * 194 175 * Returns 0 if the filters were successfully added or removed 195 176 **/ 196 177 static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi, 197 178 struct i40e_fdir_filter *fd_data, 198 - u8 *raw_packet, bool add) 179 + bool add) 199 180 { 200 181 struct i40e_pf *pf = vsi->back; 201 182 struct udphdr *udp; 202 183 struct iphdr *ip; 203 184 bool err = false; 185 + u8 *raw_packet; 204 186 int ret; 205 187 static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0, 206 188 0x45, 0, 0, 0x1c, 0, 0, 0x40, 0, 0x40, 0x11, 0, 0, 0, 0, 0, 0, 207 189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 208 190 191 + raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL); 192 + if (!raw_packet) 193 + return -ENOMEM; 209 194 memcpy(raw_packet, packet, I40E_UDPIP_DUMMY_PACKET_LEN); 210 195 211 196 ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET); ··· 241 220 * i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 filters 242 221 * @vsi: pointer to the targeted VSI 243 222 * @fd_data: the flow director data required for the FDir descriptor 244 - * @raw_packet: the pre-allocated packet buffer for FDir 245 223 * @add: true adds a filter, false removes it 246 224 * 247 225 * Returns 0 if the filters were successfully added or removed 248 226 **/ 249 227 static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, 250 228 struct i40e_fdir_filter *fd_data, 251 - u8 *raw_packet, bool add) 229 + bool add) 252 230 { 253 231 struct i40e_pf *pf = vsi->back; 254 232 struct tcphdr *tcp; 255 233 struct iphdr *ip; 256 234 bool err = false; 235 + u8 *raw_packet; 257 236 int ret; 258 237 /* Dummy packet */ 259 238 static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0, ··· 261 240 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x11, 262 241 0x0, 0x72, 0, 0, 0, 0}; 263 242 243 + raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL); 244 + if (!raw_packet) 245 + return -ENOMEM; 264 246 memcpy(raw_packet, packet, I40E_TCPIP_DUMMY_PACKET_LEN); 265 247 266 248 ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET); ··· 310 286 **/ 311 287 static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi, 312 288 struct i40e_fdir_filter *fd_data, 313 - u8 *raw_packet, bool add) 289 + bool add) 314 290 { 315 291 return -EOPNOTSUPP; 316 292 } ··· 321 297 * a specific flow spec 322 298 * @vsi: pointer to the targeted VSI 323 299 * @fd_data: the flow director data required for the FDir descriptor 324 - * @raw_packet: the pre-allocated packet buffer for FDir 325 300 * @add: true adds a filter, false removes it 326 301 * 327 302 * Returns 0 if the filters were successfully added or removed 328 303 **/ 329 304 static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi, 330 305 struct i40e_fdir_filter *fd_data, 331 - u8 *raw_packet, bool add) 306 + bool add) 332 307 { 333 308 struct i40e_pf *pf = vsi->back; 334 309 struct iphdr *ip; 335 310 bool err = false; 311 + u8 *raw_packet; 336 312 int ret; 337 313 int i; 338 314 static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0, 339 315 0x45, 0, 0, 0x14, 0, 0, 0x40, 0, 0x40, 0x10, 0, 0, 0, 0, 0, 0, 340 316 0, 0, 0, 0}; 341 317 342 - memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN); 343 - ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET); 344 - 345 - ip->saddr = fd_data->src_ip[0]; 346 - ip->daddr = fd_data->dst_ip[0]; 347 - ip->protocol = 0; 348 - 349 318 for (i = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER; 350 319 i <= I40E_FILTER_PCTYPE_FRAG_IPV4; i++) { 320 + raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL); 321 + if (!raw_packet) 322 + return -ENOMEM; 323 + memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN); 324 + ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET); 325 + 326 + ip->saddr = fd_data->src_ip[0]; 327 + ip->daddr = fd_data->dst_ip[0]; 328 + ip->protocol = 0; 329 + 351 330 fd_data->pctype = i; 352 331 ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add); 353 332 ··· 380 353 struct i40e_fdir_filter *input, bool add) 381 354 { 382 355 struct i40e_pf *pf = vsi->back; 383 - u8 *raw_packet; 384 356 int ret; 385 - 386 - /* Populate the Flow Director that we have at the moment 387 - * and allocate the raw packet buffer for the calling functions 388 - */ 389 - raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL); 390 - if (!raw_packet) 391 - return -ENOMEM; 392 357 393 358 switch (input->flow_type & ~FLOW_EXT) { 394 359 case TCP_V4_FLOW: 395 - ret = i40e_add_del_fdir_tcpv4(vsi, input, raw_packet, 396 - add); 360 + ret = i40e_add_del_fdir_tcpv4(vsi, input, add); 397 361 break; 398 362 case UDP_V4_FLOW: 399 - ret = i40e_add_del_fdir_udpv4(vsi, input, raw_packet, 400 - add); 363 + ret = i40e_add_del_fdir_udpv4(vsi, input, add); 401 364 break; 402 365 case SCTP_V4_FLOW: 403 - ret = i40e_add_del_fdir_sctpv4(vsi, input, raw_packet, 404 - add); 366 + ret = i40e_add_del_fdir_sctpv4(vsi, input, add); 405 367 break; 406 368 case IPV4_FLOW: 407 - ret = i40e_add_del_fdir_ipv4(vsi, input, raw_packet, 408 - add); 369 + ret = i40e_add_del_fdir_ipv4(vsi, input, add); 409 370 break; 410 371 case IP_USER_FLOW: 411 372 switch (input->ip4_proto) { 412 373 case IPPROTO_TCP: 413 - ret = i40e_add_del_fdir_tcpv4(vsi, input, 414 - raw_packet, add); 374 + ret = i40e_add_del_fdir_tcpv4(vsi, input, add); 415 375 break; 416 376 case IPPROTO_UDP: 417 - ret = i40e_add_del_fdir_udpv4(vsi, input, 418 - raw_packet, add); 377 + ret = i40e_add_del_fdir_udpv4(vsi, input, add); 419 378 break; 420 379 case IPPROTO_SCTP: 421 - ret = i40e_add_del_fdir_sctpv4(vsi, input, 422 - raw_packet, add); 380 + ret = i40e_add_del_fdir_sctpv4(vsi, input, add); 423 381 break; 424 382 default: 425 - ret = i40e_add_del_fdir_ipv4(vsi, input, 426 - raw_packet, add); 383 + ret = i40e_add_del_fdir_ipv4(vsi, input, add); 427 384 break; 428 385 } 429 386 break; ··· 417 406 ret = -EINVAL; 418 407 } 419 408 420 - kfree(raw_packet); 409 + /* The buffer allocated here is freed by the i40e_clean_tx_ring() */ 421 410 return ret; 422 411 } 423 412 ··· 491 480 struct i40e_tx_buffer *tx_buffer) 492 481 { 493 482 if (tx_buffer->skb) { 494 - dev_kfree_skb_any(tx_buffer->skb); 483 + if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB) 484 + kfree(tx_buffer->raw_buf); 485 + else 486 + dev_kfree_skb_any(tx_buffer->skb); 487 + 495 488 if (dma_unmap_len(tx_buffer, len)) 496 489 dma_unmap_single(ring->dev, 497 490 dma_unmap_addr(tx_buffer, dma),
+5 -1
drivers/net/ethernet/intel/i40e/i40e_txrx.h
··· 131 131 #define I40E_TX_FLAGS_FCCRC (u32)(1 << 6) 132 132 #define I40E_TX_FLAGS_FSO (u32)(1 << 7) 133 133 #define I40E_TX_FLAGS_TSYN (u32)(1 << 8) 134 + #define I40E_TX_FLAGS_FD_SB (u32)(1 << 9) 134 135 #define I40E_TX_FLAGS_VLAN_MASK 0xffff0000 135 136 #define I40E_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000 136 137 #define I40E_TX_FLAGS_VLAN_PRIO_SHIFT 29 ··· 140 139 struct i40e_tx_buffer { 141 140 struct i40e_tx_desc *next_to_watch; 142 141 unsigned long time_stamp; 143 - struct sk_buff *skb; 142 + union { 143 + struct sk_buff *skb; 144 + void *raw_buf; 145 + }; 144 146 unsigned int bytecount; 145 147 unsigned short gso_segs; 146 148 DEFINE_DMA_UNMAP_ADDR(dma);
+5 -1
drivers/net/ethernet/intel/i40evf/i40e_txrx.c
··· 50 50 struct i40e_tx_buffer *tx_buffer) 51 51 { 52 52 if (tx_buffer->skb) { 53 - dev_kfree_skb_any(tx_buffer->skb); 53 + if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB) 54 + kfree(tx_buffer->raw_buf); 55 + else 56 + dev_kfree_skb_any(tx_buffer->skb); 57 + 54 58 if (dma_unmap_len(tx_buffer, len)) 55 59 dma_unmap_single(ring->dev, 56 60 dma_unmap_addr(tx_buffer, dma),
+5 -1
drivers/net/ethernet/intel/i40evf/i40e_txrx.h
··· 130 130 #define I40E_TX_FLAGS_IPV6 (u32)(1 << 5) 131 131 #define I40E_TX_FLAGS_FCCRC (u32)(1 << 6) 132 132 #define I40E_TX_FLAGS_FSO (u32)(1 << 7) 133 + #define I40E_TX_FLAGS_FD_SB (u32)(1 << 9) 133 134 #define I40E_TX_FLAGS_VLAN_MASK 0xffff0000 134 135 #define I40E_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000 135 136 #define I40E_TX_FLAGS_VLAN_PRIO_SHIFT 29 ··· 139 138 struct i40e_tx_buffer { 140 139 struct i40e_tx_desc *next_to_watch; 141 140 unsigned long time_stamp; 142 - struct sk_buff *skb; 141 + union { 142 + struct sk_buff *skb; 143 + void *raw_buf; 144 + }; 143 145 unsigned int bytecount; 144 146 unsigned short gso_segs; 145 147 DEFINE_DMA_UNMAP_ADDR(dma);