New upstream version 16.11.3
[deb_dpdk.git] / drivers / net / bonding / rte_eth_bond_pmd.c
index b20a272..7811a5a 100644 (file)
@@ -42,7 +42,7 @@
 #include <rte_ip_frag.h>
 #include <rte_devargs.h>
 #include <rte_kvargs.h>
-#include <rte_dev.h>
+#include <rte_vdev.h>
 #include <rte_alarm.h>
 #include <rte_cycles.h>
 
@@ -122,6 +122,15 @@ bond_ethdev_rx_burst_active_backup(void *queue, struct rte_mbuf **bufs,
                        bd_rx_q->queue_id, bufs, nb_pkts);
 }
 
+static inline uint8_t
+is_lacp_packets(uint16_t ethertype, uint8_t subtype, uint16_t vlan_tci)
+{
+       const uint16_t ether_type_slow_be = rte_be_to_cpu_16(ETHER_TYPE_SLOW);
+
+       return !vlan_tci && (ethertype == ether_type_slow_be &&
+               (subtype == SLOW_SUBTYPE_MARKER || subtype == SLOW_SUBTYPE_LACP));
+}
+
 static uint16_t
 bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
                uint16_t nb_pkts)
@@ -141,6 +150,7 @@ bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
        uint8_t collecting;  /* current slave collecting status */
        const uint8_t promisc = internals->promiscuous_en;
        uint8_t i, j, k;
+       uint8_t subtype;
 
        rte_eth_macaddr_get(internals->port_id, &bond_mac);
        /* Copy slave list to protect against slave up/down changes during tx
@@ -166,10 +176,12 @@ bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
                                rte_prefetch0(rte_pktmbuf_mtod(bufs[j + 3], void *));
 
                        hdr = rte_pktmbuf_mtod(bufs[j], struct ether_hdr *);
+                       subtype = ((struct slow_protocol_frame *)hdr)->slow_protocol.subtype;
+
                        /* Remove packet from array if it is slow packet or slave is not
                         * in collecting state or bondign interface is not in promiscus
                         * mode and packet address does not match. */
-                       if (unlikely(hdr->ether_type == ether_type_slow_be ||
+                       if (unlikely(is_lacp_packets(hdr->ether_type, subtype, bufs[j]->vlan_tci) ||
                                !collecting || (!promisc &&
                                        !is_multicast_ether_addr(&hdr->d_addr) &&
                                        !is_same_ether_addr(&bond_mac, &hdr->d_addr)))) {
@@ -631,7 +643,7 @@ bandwidth_left(uint8_t port_id, uint64_t load, uint8_t update_idx,
 {
        struct rte_eth_link link_status;
 
-       rte_eth_link_get(port_id, &link_status);
+       rte_eth_link_get_nowait(port_id, &link_status);
        uint64_t link_bwg = link_status.link_speed * 1000000ULL / 8;
        if (link_bwg == 0)
                return;
@@ -1335,6 +1347,9 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
                                bonded_eth_dev->data->dev_conf.rxmode.mq_mode;
        }
 
+       slave_eth_dev->data->dev_conf.rxmode.hw_vlan_filter =
+                       bonded_eth_dev->data->dev_conf.rxmode.hw_vlan_filter;
+
        /* Configure device */
        errval = rte_eth_dev_configure(slave_eth_dev->data->port_id,
                        bonded_eth_dev->data->nb_rx_queues,
@@ -1415,9 +1430,11 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
        }
 
        /* If lsc interrupt is set, check initial slave's link status */
-       if (slave_eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
+       if (slave_eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) {
+               slave_eth_dev->dev_ops->link_update(slave_eth_dev, 0);
                bond_ethdev_lsc_event_callback(slave_eth_dev->data->port_id,
                        RTE_ETH_EVENT_INTR_LSC, &bonded_eth_dev->data->port_id);
+       }
 
        return 0;
 }
@@ -1637,7 +1654,10 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev)
 void
 bond_ethdev_close(struct rte_eth_dev *dev)
 {
+       struct bond_dev_private *internals = dev->data->dev_private;
+
        bond_ethdev_free_queues(dev);
+       rte_bitmap_reset(internals->vlan_filter_bmp);
 }
 
 /* forward declaration */
@@ -1647,14 +1667,38 @@ static void
 bond_ethdev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
        struct bond_dev_private *internals = dev->data->dev_private;
+       uint16_t max_nb_rx_queues = UINT16_MAX;
+       uint16_t max_nb_tx_queues = UINT16_MAX;
 
        dev_info->max_mac_addrs = 1;
 
-       dev_info->max_rx_pktlen = internals->candidate_max_rx_pktlen ?
-                                 internals->candidate_max_rx_pktlen : 2048;
+       dev_info->max_rx_pktlen = internals->candidate_max_rx_pktlen
+                                 ? internals->candidate_max_rx_pktlen
+                                 : ETHER_MAX_JUMBO_FRAME_LEN;
+
+       if (internals->slave_count > 0) {
+               /* Max number of tx/rx queues that the bonded device can
+                * support is the minimum values of the bonded slaves, as
+                * all slaves must be capable of supporting the same number
+                * of tx/rx queues.
+                */
+               struct rte_eth_dev_info slave_info;
+               uint8_t idx;
+
+               for (idx = 0; idx < internals->slave_count; idx++) {
+                       rte_eth_dev_info_get(internals->slaves[idx].port_id,
+                                       &slave_info);
+
+                       if (slave_info.max_rx_queues < max_nb_rx_queues)
+                               max_nb_rx_queues = slave_info.max_rx_queues;
+
+                       if (slave_info.max_tx_queues < max_nb_tx_queues)
+                               max_nb_tx_queues = slave_info.max_tx_queues;
+               }
+       }
 
-       dev_info->max_rx_queues = (uint16_t)128;
-       dev_info->max_tx_queues = (uint16_t)512;
+       dev_info->max_rx_queues = max_nb_rx_queues;
+       dev_info->max_tx_queues = max_nb_tx_queues;
 
        dev_info->min_rx_bufsize = 0;
        dev_info->pci_dev = NULL;
@@ -1666,6 +1710,35 @@ bond_ethdev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
        dev_info->reta_size = internals->reta_size;
 }
 
+static int
+bond_ethdev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
+{
+       int res;
+       uint8_t i;
+       struct bond_dev_private *internals = dev->data->dev_private;
+
+       /* don't do this while a slave is being added */
+       rte_spinlock_lock(&internals->lock);
+
+       if (on)
+               rte_bitmap_set(internals->vlan_filter_bmp, vlan_id);
+       else
+               rte_bitmap_clear(internals->vlan_filter_bmp, vlan_id);
+
+       for (i = 0; i < internals->slave_count; i++) {
+               uint8_t port_id = internals->slaves[i].port_id;
+
+               res = rte_eth_dev_vlan_filter(port_id, vlan_id, on);
+               if (res == ENOTSUP)
+                       RTE_LOG(WARNING, PMD,
+                               "Setting VLAN filter on slave port %u not supported.\n",
+                               port_id);
+       }
+
+       rte_spinlock_unlock(&internals->lock);
+       return 0;
+}
+
 static int
 bond_ethdev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
                uint16_t nb_rx_desc, unsigned int socket_id __rte_unused,
@@ -1923,7 +1996,7 @@ bond_ethdev_delayed_lsc_propagation(void *arg)
                return;
 
        _rte_eth_dev_callback_process((struct rte_eth_dev *)arg,
-                       RTE_ETH_EVENT_INTR_LSC);
+                       RTE_ETH_EVENT_INTR_LSC, NULL);
 }
 
 void
@@ -1985,6 +2058,16 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
                        /* Inherit eth dev link properties from first active slave */
                        link_properties_set(bonded_eth_dev,
                                        &(slave_eth_dev->data->dev_link));
+               } else {
+                       if (link_properties_valid(
+                               &bonded_eth_dev->data->dev_link, &link) != 0) {
+                               slave_eth_dev->data->dev_flags &=
+                                       (~RTE_ETH_DEV_BONDED_SLAVE);
+                               RTE_LOG(ERR, PMD,
+                                       "port %u invalid speed/duplex\n",
+                                       port_id);
+                               return;
+                       }
                }
 
                activate_slave(bonded_eth_dev, port_id);
@@ -2034,7 +2117,7 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
                                                (void *)bonded_eth_dev);
                        else
                                _rte_eth_dev_callback_process(bonded_eth_dev,
-                                               RTE_ETH_EVENT_INTR_LSC);
+                                               RTE_ETH_EVENT_INTR_LSC, NULL);
 
                } else {
                        if (internals->link_down_delay_ms > 0)
@@ -2043,7 +2126,7 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
                                                (void *)bonded_eth_dev);
                        else
                                _rte_eth_dev_callback_process(bonded_eth_dev,
-                                               RTE_ETH_EVENT_INTR_LSC);
+                                               RTE_ETH_EVENT_INTR_LSC, NULL);
                }
        }
 }
@@ -2161,6 +2244,7 @@ const struct eth_dev_ops default_dev_ops = {
        .dev_close            = bond_ethdev_close,
        .dev_configure        = bond_ethdev_configure,
        .dev_infos_get        = bond_ethdev_info,
+       .vlan_filter_set      = bond_ethdev_vlan_filter_set,
        .rx_queue_setup       = bond_ethdev_rx_queue_setup,
        .tx_queue_setup       = bond_ethdev_tx_queue_setup,
        .rx_queue_release     = bond_ethdev_rx_queue_release,
@@ -2177,7 +2261,7 @@ const struct eth_dev_ops default_dev_ops = {
 };
 
 static int
-bond_init(const char *name, const char *params)
+bond_probe(const char *name, const char *params)
 {
        struct bond_dev_private *internals;
        struct rte_kvargs *kvlist;
@@ -2244,7 +2328,7 @@ parse_error:
 }
 
 static int
-bond_uninit(const char *name)
+bond_remove(const char *name)
 {
        int  ret;
 
@@ -2508,15 +2592,15 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
        return 0;
 }
 
-static struct rte_driver bond_drv = {
-       .type = PMD_VDEV,
-       .init = bond_init,
-       .uninit = bond_uninit,
+static struct rte_vdev_driver bond_drv = {
+       .probe = bond_probe,
+       .remove = bond_remove,
 };
 
-PMD_REGISTER_DRIVER(bond_drv, eth_bond);
+RTE_PMD_REGISTER_VDEV(net_bonding, bond_drv);
+RTE_PMD_REGISTER_ALIAS(net_bonding, eth_bond);
 
-DRIVER_REGISTER_PARAM_STRING(eth_bond,
+RTE_PMD_REGISTER_PARAM_STRING(net_bonding,
        "slave=<ifc> "
        "primary=<ifc> "
        "mode=[0-6] "