| .. | .. |
|---|
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
|---|
| 2 | | -/* Copyright(c) 2013 - 2018 Intel Corporation. */ |
|---|
| 2 | +/* Copyright(c) 2013 - 2019 Intel Corporation. */ |
|---|
| 3 | 3 | |
|---|
| 4 | 4 | #include "fm10k.h" |
|---|
| 5 | 5 | #include <linux/vmalloc.h> |
|---|
| .. | .. |
|---|
| 54 | 54 | **/ |
|---|
| 55 | 55 | static int fm10k_setup_all_tx_resources(struct fm10k_intfc *interface) |
|---|
| 56 | 56 | { |
|---|
| 57 | | - int i, err = 0; |
|---|
| 57 | + int i, err; |
|---|
| 58 | 58 | |
|---|
| 59 | 59 | for (i = 0; i < interface->num_tx_queues; i++) { |
|---|
| 60 | 60 | err = fm10k_setup_tx_resources(interface->tx_ring[i]); |
|---|
| .. | .. |
|---|
| 121 | 121 | **/ |
|---|
| 122 | 122 | static int fm10k_setup_all_rx_resources(struct fm10k_intfc *interface) |
|---|
| 123 | 123 | { |
|---|
| 124 | | - int i, err = 0; |
|---|
| 124 | + int i, err; |
|---|
| 125 | 125 | |
|---|
| 126 | 126 | for (i = 0; i < interface->num_rx_queues; i++) { |
|---|
| 127 | 127 | err = fm10k_setup_rx_resources(interface->rx_ring[i]); |
|---|
| .. | .. |
|---|
| 169 | 169 | **/ |
|---|
| 170 | 170 | static void fm10k_clean_tx_ring(struct fm10k_ring *tx_ring) |
|---|
| 171 | 171 | { |
|---|
| 172 | | - struct fm10k_tx_buffer *tx_buffer; |
|---|
| 173 | 172 | unsigned long size; |
|---|
| 174 | 173 | u16 i; |
|---|
| 175 | 174 | |
|---|
| .. | .. |
|---|
| 179 | 178 | |
|---|
| 180 | 179 | /* Free all the Tx ring sk_buffs */ |
|---|
| 181 | 180 | for (i = 0; i < tx_ring->count; i++) { |
|---|
| 182 | | - tx_buffer = &tx_ring->tx_buffer[i]; |
|---|
| 181 | + struct fm10k_tx_buffer *tx_buffer = &tx_ring->tx_buffer[i]; |
|---|
| 182 | + |
|---|
| 183 | 183 | fm10k_unmap_and_free_tx_resource(tx_ring, tx_buffer); |
|---|
| 184 | 184 | } |
|---|
| 185 | 185 | |
|---|
| .. | .. |
|---|
| 253 | 253 | if (!rx_ring->rx_buffer) |
|---|
| 254 | 254 | return; |
|---|
| 255 | 255 | |
|---|
| 256 | | - if (rx_ring->skb) |
|---|
| 257 | | - dev_kfree_skb(rx_ring->skb); |
|---|
| 256 | + dev_kfree_skb(rx_ring->skb); |
|---|
| 258 | 257 | rx_ring->skb = NULL; |
|---|
| 259 | 258 | |
|---|
| 260 | 259 | /* Free all the Rx ring sk_buffs */ |
|---|
| .. | .. |
|---|
| 368 | 367 | } |
|---|
| 369 | 368 | |
|---|
| 370 | 369 | /** |
|---|
| 371 | | - * fm10k_free_udp_port_info |
|---|
| 372 | | - * @interface: board private structure |
|---|
| 373 | | - * |
|---|
| 374 | | - * This function frees both geneve_port and vxlan_port structures |
|---|
| 375 | | - **/ |
|---|
| 376 | | -static void fm10k_free_udp_port_info(struct fm10k_intfc *interface) |
|---|
| 377 | | -{ |
|---|
| 378 | | - struct fm10k_udp_port *port; |
|---|
| 379 | | - |
|---|
| 380 | | - /* flush all entries from vxlan list */ |
|---|
| 381 | | - port = list_first_entry_or_null(&interface->vxlan_port, |
|---|
| 382 | | - struct fm10k_udp_port, list); |
|---|
| 383 | | - while (port) { |
|---|
| 384 | | - list_del(&port->list); |
|---|
| 385 | | - kfree(port); |
|---|
| 386 | | - port = list_first_entry_or_null(&interface->vxlan_port, |
|---|
| 387 | | - struct fm10k_udp_port, |
|---|
| 388 | | - list); |
|---|
| 389 | | - } |
|---|
| 390 | | - |
|---|
| 391 | | - /* flush all entries from geneve list */ |
|---|
| 392 | | - port = list_first_entry_or_null(&interface->geneve_port, |
|---|
| 393 | | - struct fm10k_udp_port, list); |
|---|
| 394 | | - while (port) { |
|---|
| 395 | | - list_del(&port->list); |
|---|
| 396 | | - kfree(port); |
|---|
| 397 | | - port = list_first_entry_or_null(&interface->vxlan_port, |
|---|
| 398 | | - struct fm10k_udp_port, |
|---|
| 399 | | - list); |
|---|
| 400 | | - } |
|---|
| 401 | | -} |
|---|
| 402 | | - |
|---|
| 403 | | -/** |
|---|
| 404 | 370 | * fm10k_restore_udp_port_info |
|---|
| 405 | 371 | * @interface: board private structure |
|---|
| 406 | 372 | * |
|---|
| .. | .. |
|---|
| 409 | 375 | static void fm10k_restore_udp_port_info(struct fm10k_intfc *interface) |
|---|
| 410 | 376 | { |
|---|
| 411 | 377 | struct fm10k_hw *hw = &interface->hw; |
|---|
| 412 | | - struct fm10k_udp_port *port; |
|---|
| 413 | 378 | |
|---|
| 414 | 379 | /* only the PF supports configuring tunnels */ |
|---|
| 415 | 380 | if (hw->mac.type != fm10k_mac_pf) |
|---|
| 416 | 381 | return; |
|---|
| 417 | 382 | |
|---|
| 418 | | - port = list_first_entry_or_null(&interface->vxlan_port, |
|---|
| 419 | | - struct fm10k_udp_port, list); |
|---|
| 420 | | - |
|---|
| 421 | 383 | /* restore tunnel configuration register */ |
|---|
| 422 | 384 | fm10k_write_reg(hw, FM10K_TUNNEL_CFG, |
|---|
| 423 | | - (port ? ntohs(port->port) : 0) | |
|---|
| 385 | + ntohs(interface->vxlan_port) | |
|---|
| 424 | 386 | (ETH_P_TEB << FM10K_TUNNEL_CFG_NVGRE_SHIFT)); |
|---|
| 425 | | - |
|---|
| 426 | | - port = list_first_entry_or_null(&interface->geneve_port, |
|---|
| 427 | | - struct fm10k_udp_port, list); |
|---|
| 428 | 387 | |
|---|
| 429 | 388 | /* restore Geneve tunnel configuration register */ |
|---|
| 430 | 389 | fm10k_write_reg(hw, FM10K_TUNNEL_CFG_GENEVE, |
|---|
| 431 | | - (port ? ntohs(port->port) : 0)); |
|---|
| 432 | | -} |
|---|
| 433 | | - |
|---|
| 434 | | -static struct fm10k_udp_port * |
|---|
| 435 | | -fm10k_remove_tunnel_port(struct list_head *ports, |
|---|
| 436 | | - struct udp_tunnel_info *ti) |
|---|
| 437 | | -{ |
|---|
| 438 | | - struct fm10k_udp_port *port; |
|---|
| 439 | | - |
|---|
| 440 | | - list_for_each_entry(port, ports, list) { |
|---|
| 441 | | - if ((port->port == ti->port) && |
|---|
| 442 | | - (port->sa_family == ti->sa_family)) { |
|---|
| 443 | | - list_del(&port->list); |
|---|
| 444 | | - return port; |
|---|
| 445 | | - } |
|---|
| 446 | | - } |
|---|
| 447 | | - |
|---|
| 448 | | - return NULL; |
|---|
| 449 | | -} |
|---|
| 450 | | - |
|---|
| 451 | | -static void fm10k_insert_tunnel_port(struct list_head *ports, |
|---|
| 452 | | - struct udp_tunnel_info *ti) |
|---|
| 453 | | -{ |
|---|
| 454 | | - struct fm10k_udp_port *port; |
|---|
| 455 | | - |
|---|
| 456 | | - /* remove existing port entry from the list so that the newest items |
|---|
| 457 | | - * are always at the tail of the list. |
|---|
| 458 | | - */ |
|---|
| 459 | | - port = fm10k_remove_tunnel_port(ports, ti); |
|---|
| 460 | | - if (!port) { |
|---|
| 461 | | - port = kmalloc(sizeof(*port), GFP_ATOMIC); |
|---|
| 462 | | - if (!port) |
|---|
| 463 | | - return; |
|---|
| 464 | | - port->port = ti->port; |
|---|
| 465 | | - port->sa_family = ti->sa_family; |
|---|
| 466 | | - } |
|---|
| 467 | | - |
|---|
| 468 | | - list_add_tail(&port->list, ports); |
|---|
| 390 | + ntohs(interface->geneve_port)); |
|---|
| 469 | 391 | } |
|---|
| 470 | 392 | |
|---|
| 471 | 393 | /** |
|---|
| 472 | | - * fm10k_udp_tunnel_add |
|---|
| 394 | + * fm10k_udp_tunnel_sync - Called when UDP tunnel ports change |
|---|
| 473 | 395 | * @dev: network interface device structure |
|---|
| 474 | | - * @ti: Tunnel endpoint information |
|---|
| 396 | + * @table: Tunnel table (according to tables of @fm10k_udp_tunnels) |
|---|
| 475 | 397 | * |
|---|
| 476 | | - * This function is called when a new UDP tunnel port has been added. |
|---|
| 398 | + * This function is called when a new UDP tunnel port is added or deleted. |
|---|
| 477 | 399 | * Due to hardware restrictions, only one port per type can be offloaded at |
|---|
| 478 | | - * once. |
|---|
| 400 | + * once. Core will send to the driver a port of its choice. |
|---|
| 479 | 401 | **/ |
|---|
| 480 | | -static void fm10k_udp_tunnel_add(struct net_device *dev, |
|---|
| 481 | | - struct udp_tunnel_info *ti) |
|---|
| 402 | +static int fm10k_udp_tunnel_sync(struct net_device *dev, unsigned int table) |
|---|
| 482 | 403 | { |
|---|
| 483 | 404 | struct fm10k_intfc *interface = netdev_priv(dev); |
|---|
| 405 | + struct udp_tunnel_info ti; |
|---|
| 484 | 406 | |
|---|
| 485 | | - /* only the PF supports configuring tunnels */ |
|---|
| 486 | | - if (interface->hw.mac.type != fm10k_mac_pf) |
|---|
| 487 | | - return; |
|---|
| 488 | | - |
|---|
| 489 | | - switch (ti->type) { |
|---|
| 490 | | - case UDP_TUNNEL_TYPE_VXLAN: |
|---|
| 491 | | - fm10k_insert_tunnel_port(&interface->vxlan_port, ti); |
|---|
| 492 | | - break; |
|---|
| 493 | | - case UDP_TUNNEL_TYPE_GENEVE: |
|---|
| 494 | | - fm10k_insert_tunnel_port(&interface->geneve_port, ti); |
|---|
| 495 | | - break; |
|---|
| 496 | | - default: |
|---|
| 497 | | - return; |
|---|
| 498 | | - } |
|---|
| 407 | + udp_tunnel_nic_get_port(dev, table, 0, &ti); |
|---|
| 408 | + if (!table) |
|---|
| 409 | + interface->vxlan_port = ti.port; |
|---|
| 410 | + else |
|---|
| 411 | + interface->geneve_port = ti.port; |
|---|
| 499 | 412 | |
|---|
| 500 | 413 | fm10k_restore_udp_port_info(interface); |
|---|
| 414 | + return 0; |
|---|
| 501 | 415 | } |
|---|
| 502 | 416 | |
|---|
| 503 | | -/** |
|---|
| 504 | | - * fm10k_udp_tunnel_del |
|---|
| 505 | | - * @dev: network interface device structure |
|---|
| 506 | | - * @ti: Tunnel end point information |
|---|
| 507 | | - * |
|---|
| 508 | | - * This function is called when a new UDP tunnel port is deleted. The freed |
|---|
| 509 | | - * port will be removed from the list, then we reprogram the offloaded port |
|---|
| 510 | | - * based on the head of the list. |
|---|
| 511 | | - **/ |
|---|
| 512 | | -static void fm10k_udp_tunnel_del(struct net_device *dev, |
|---|
| 513 | | - struct udp_tunnel_info *ti) |
|---|
| 514 | | -{ |
|---|
| 515 | | - struct fm10k_intfc *interface = netdev_priv(dev); |
|---|
| 516 | | - struct fm10k_udp_port *port = NULL; |
|---|
| 517 | | - |
|---|
| 518 | | - if (interface->hw.mac.type != fm10k_mac_pf) |
|---|
| 519 | | - return; |
|---|
| 520 | | - |
|---|
| 521 | | - switch (ti->type) { |
|---|
| 522 | | - case UDP_TUNNEL_TYPE_VXLAN: |
|---|
| 523 | | - port = fm10k_remove_tunnel_port(&interface->vxlan_port, ti); |
|---|
| 524 | | - break; |
|---|
| 525 | | - case UDP_TUNNEL_TYPE_GENEVE: |
|---|
| 526 | | - port = fm10k_remove_tunnel_port(&interface->geneve_port, ti); |
|---|
| 527 | | - break; |
|---|
| 528 | | - default: |
|---|
| 529 | | - return; |
|---|
| 530 | | - } |
|---|
| 531 | | - |
|---|
| 532 | | - /* if we did remove a port we need to free its memory */ |
|---|
| 533 | | - kfree(port); |
|---|
| 534 | | - |
|---|
| 535 | | - fm10k_restore_udp_port_info(interface); |
|---|
| 536 | | -} |
|---|
| 417 | +static const struct udp_tunnel_nic_info fm10k_udp_tunnels = { |
|---|
| 418 | + .sync_table = fm10k_udp_tunnel_sync, |
|---|
| 419 | + .tables = { |
|---|
| 420 | + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, |
|---|
| 421 | + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_GENEVE, }, |
|---|
| 422 | + }, |
|---|
| 423 | +}; |
|---|
| 537 | 424 | |
|---|
| 538 | 425 | /** |
|---|
| 539 | 426 | * fm10k_open - Called when a network interface is made active |
|---|
| .. | .. |
|---|
| 581 | 468 | if (err) |
|---|
| 582 | 469 | goto err_set_queues; |
|---|
| 583 | 470 | |
|---|
| 584 | | - udp_tunnel_get_rx_info(netdev); |
|---|
| 585 | | - |
|---|
| 586 | 471 | fm10k_up(interface); |
|---|
| 587 | 472 | |
|---|
| 588 | 473 | return 0; |
|---|
| .. | .. |
|---|
| 615 | 500 | fm10k_down(interface); |
|---|
| 616 | 501 | |
|---|
| 617 | 502 | fm10k_qv_free_irq(interface); |
|---|
| 618 | | - |
|---|
| 619 | | - fm10k_free_udp_port_info(interface); |
|---|
| 620 | 503 | |
|---|
| 621 | 504 | fm10k_free_all_tx_resources(interface); |
|---|
| 622 | 505 | fm10k_free_all_rx_resources(interface); |
|---|
| .. | .. |
|---|
| 697 | 580 | /** |
|---|
| 698 | 581 | * fm10k_tx_timeout - Respond to a Tx Hang |
|---|
| 699 | 582 | * @netdev: network interface device structure |
|---|
| 583 | + * @txqueue: the index of the Tx queue that timed out |
|---|
| 700 | 584 | **/ |
|---|
| 701 | | -static void fm10k_tx_timeout(struct net_device *netdev) |
|---|
| 585 | +static void fm10k_tx_timeout(struct net_device *netdev, unsigned int txqueue) |
|---|
| 702 | 586 | { |
|---|
| 703 | 587 | struct fm10k_intfc *interface = netdev_priv(netdev); |
|---|
| 588 | + struct fm10k_ring *tx_ring; |
|---|
| 704 | 589 | bool real_tx_hang = false; |
|---|
| 705 | | - int i; |
|---|
| 706 | 590 | |
|---|
| 707 | | -#define TX_TIMEO_LIMIT 16000 |
|---|
| 708 | | - for (i = 0; i < interface->num_tx_queues; i++) { |
|---|
| 709 | | - struct fm10k_ring *tx_ring = interface->tx_ring[i]; |
|---|
| 710 | | - |
|---|
| 711 | | - if (check_for_tx_hang(tx_ring) && fm10k_check_tx_hang(tx_ring)) |
|---|
| 712 | | - real_tx_hang = true; |
|---|
| 591 | + if (txqueue >= interface->num_tx_queues) { |
|---|
| 592 | + WARN(1, "invalid Tx queue index %d", txqueue); |
|---|
| 593 | + return; |
|---|
| 713 | 594 | } |
|---|
| 714 | 595 | |
|---|
| 596 | + tx_ring = interface->tx_ring[txqueue]; |
|---|
| 597 | + if (check_for_tx_hang(tx_ring) && fm10k_check_tx_hang(tx_ring)) |
|---|
| 598 | + real_tx_hang = true; |
|---|
| 599 | + |
|---|
| 600 | +#define TX_TIMEO_LIMIT 16000 |
|---|
| 715 | 601 | if (real_tx_hang) { |
|---|
| 716 | 602 | fm10k_tx_timeout_reset(interface); |
|---|
| 717 | 603 | } else { |
|---|
| .. | .. |
|---|
| 851 | 737 | /* Don't free requests for other interfaces */ |
|---|
| 852 | 738 | if (r->mac.glort != glort) |
|---|
| 853 | 739 | break; |
|---|
| 854 | | - /* fall through */ |
|---|
| 740 | + fallthrough; |
|---|
| 855 | 741 | case FM10K_VLAN_REQUEST: |
|---|
| 856 | 742 | if (vlans) { |
|---|
| 857 | 743 | list_del(&r->list); |
|---|
| .. | .. |
|---|
| 871 | 757 | u16 glort = interface->glort; |
|---|
| 872 | 758 | u16 vid = interface->vid; |
|---|
| 873 | 759 | bool set = !!(vid / VLAN_N_VID); |
|---|
| 874 | | - int err = -EHOSTDOWN; |
|---|
| 760 | + int err; |
|---|
| 875 | 761 | |
|---|
| 876 | 762 | /* drop any leading bits on the VLAN ID */ |
|---|
| 877 | 763 | vid &= VLAN_N_VID - 1; |
|---|
| .. | .. |
|---|
| 891 | 777 | u16 glort = interface->glort; |
|---|
| 892 | 778 | u16 vid = interface->vid; |
|---|
| 893 | 779 | bool set = !!(vid / VLAN_N_VID); |
|---|
| 894 | | - int err = -EHOSTDOWN; |
|---|
| 780 | + int err; |
|---|
| 895 | 781 | |
|---|
| 896 | 782 | /* drop any leading bits on the VLAN ID */ |
|---|
| 897 | 783 | vid &= VLAN_N_VID - 1; |
|---|
| .. | .. |
|---|
| 1444 | 1330 | static void fm10k_assign_l2_accel(struct fm10k_intfc *interface, |
|---|
| 1445 | 1331 | struct fm10k_l2_accel *l2_accel) |
|---|
| 1446 | 1332 | { |
|---|
| 1447 | | - struct fm10k_ring *ring; |
|---|
| 1448 | 1333 | int i; |
|---|
| 1449 | 1334 | |
|---|
| 1450 | 1335 | for (i = 0; i < interface->num_rx_queues; i++) { |
|---|
| 1451 | | - ring = interface->rx_ring[i]; |
|---|
| 1336 | + struct fm10k_ring *ring = interface->rx_ring[i]; |
|---|
| 1337 | + |
|---|
| 1452 | 1338 | rcu_assign_pointer(ring->l2_accel, l2_accel); |
|---|
| 1453 | 1339 | } |
|---|
| 1454 | 1340 | |
|---|
| .. | .. |
|---|
| 1463 | 1349 | struct fm10k_l2_accel *old_l2_accel = NULL; |
|---|
| 1464 | 1350 | struct fm10k_dglort_cfg dglort = { 0 }; |
|---|
| 1465 | 1351 | struct fm10k_hw *hw = &interface->hw; |
|---|
| 1466 | | - int size = 0, i; |
|---|
| 1352 | + int size, i; |
|---|
| 1467 | 1353 | u16 vid, glort; |
|---|
| 1468 | 1354 | |
|---|
| 1469 | 1355 | /* The hardware supported by fm10k only filters on the destination MAC |
|---|
| .. | .. |
|---|
| 1644 | 1530 | .ndo_set_vf_vlan = fm10k_ndo_set_vf_vlan, |
|---|
| 1645 | 1531 | .ndo_set_vf_rate = fm10k_ndo_set_vf_bw, |
|---|
| 1646 | 1532 | .ndo_get_vf_config = fm10k_ndo_get_vf_config, |
|---|
| 1647 | | - .ndo_udp_tunnel_add = fm10k_udp_tunnel_add, |
|---|
| 1648 | | - .ndo_udp_tunnel_del = fm10k_udp_tunnel_del, |
|---|
| 1533 | + .ndo_get_vf_stats = fm10k_ndo_get_vf_stats, |
|---|
| 1534 | + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, |
|---|
| 1535 | + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, |
|---|
| 1649 | 1536 | .ndo_dfwd_add_station = fm10k_dfwd_add_station, |
|---|
| 1650 | 1537 | .ndo_dfwd_del_station = fm10k_dfwd_del_station, |
|---|
| 1651 | 1538 | .ndo_features_check = fm10k_features_check, |
|---|
| .. | .. |
|---|
| 1692 | 1579 | NETIF_F_SG; |
|---|
| 1693 | 1580 | |
|---|
| 1694 | 1581 | dev->features |= NETIF_F_GSO_UDP_TUNNEL; |
|---|
| 1582 | + |
|---|
| 1583 | + dev->udp_tunnel_nic_info = &fm10k_udp_tunnels; |
|---|
| 1695 | 1584 | } |
|---|
| 1696 | 1585 | |
|---|
| 1697 | 1586 | /* all features defined to this point should be changeable */ |
|---|