1ebea83f8SGaetan Rivet /*- 2ebea83f8SGaetan Rivet * BSD LICENSE 3ebea83f8SGaetan Rivet * 4ebea83f8SGaetan Rivet * Copyright 2017 6WIND S.A. 5ebea83f8SGaetan Rivet * Copyright 2017 Mellanox. 6ebea83f8SGaetan Rivet * 7ebea83f8SGaetan Rivet * Redistribution and use in source and binary forms, with or without 8ebea83f8SGaetan Rivet * modification, are permitted provided that the following conditions 9ebea83f8SGaetan Rivet * are met: 10ebea83f8SGaetan Rivet * 11ebea83f8SGaetan Rivet * * Redistributions of source code must retain the above copyright 12ebea83f8SGaetan Rivet * notice, this list of conditions and the following disclaimer. 13ebea83f8SGaetan Rivet * * Redistributions in binary form must reproduce the above copyright 14ebea83f8SGaetan Rivet * notice, this list of conditions and the following disclaimer in 15ebea83f8SGaetan Rivet * the documentation and/or other materials provided with the 16ebea83f8SGaetan Rivet * distribution. 17ebea83f8SGaetan Rivet * * Neither the name of 6WIND S.A. nor the names of its 18ebea83f8SGaetan Rivet * contributors may be used to endorse or promote products derived 19ebea83f8SGaetan Rivet * from this software without specific prior written permission. 20ebea83f8SGaetan Rivet * 21ebea83f8SGaetan Rivet * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22ebea83f8SGaetan Rivet * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23ebea83f8SGaetan Rivet * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24ebea83f8SGaetan Rivet * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25ebea83f8SGaetan Rivet * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26ebea83f8SGaetan Rivet * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27ebea83f8SGaetan Rivet * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28ebea83f8SGaetan Rivet * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29ebea83f8SGaetan Rivet * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30ebea83f8SGaetan Rivet * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31ebea83f8SGaetan Rivet * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32ebea83f8SGaetan Rivet */ 33ebea83f8SGaetan Rivet 34ebea83f8SGaetan Rivet #include <unistd.h> 35ebea83f8SGaetan Rivet 36ebea83f8SGaetan Rivet #include "failsafe_private.h" 37ebea83f8SGaetan Rivet 38ebea83f8SGaetan Rivet static int 39ebea83f8SGaetan Rivet fs_eth_dev_conf_apply(struct rte_eth_dev *dev, 40ebea83f8SGaetan Rivet struct sub_device *sdev) 41ebea83f8SGaetan Rivet { 42ebea83f8SGaetan Rivet struct rte_eth_dev *edev; 43ebea83f8SGaetan Rivet struct rte_vlan_filter_conf *vfc1; 44ebea83f8SGaetan Rivet struct rte_vlan_filter_conf *vfc2; 45ebea83f8SGaetan Rivet uint32_t i; 46ebea83f8SGaetan Rivet int ret; 47ebea83f8SGaetan Rivet 48ebea83f8SGaetan Rivet edev = ETH(sdev); 49ebea83f8SGaetan Rivet /* RX queue setup */ 50ebea83f8SGaetan Rivet for (i = 0; i < dev->data->nb_rx_queues; i++) { 51ebea83f8SGaetan Rivet struct rxq *rxq; 52ebea83f8SGaetan Rivet 53ebea83f8SGaetan Rivet rxq = dev->data->rx_queues[i]; 54ebea83f8SGaetan Rivet ret = rte_eth_rx_queue_setup(PORT_ID(sdev), i, 55ebea83f8SGaetan Rivet rxq->info.nb_desc, rxq->socket_id, 56ebea83f8SGaetan Rivet &rxq->info.conf, rxq->info.mp); 57ebea83f8SGaetan Rivet if (ret) { 58ebea83f8SGaetan Rivet ERROR("rx_queue_setup failed"); 59ebea83f8SGaetan Rivet return ret; 60ebea83f8SGaetan Rivet } 61ebea83f8SGaetan Rivet } 62ebea83f8SGaetan Rivet /* TX queue setup */ 63ebea83f8SGaetan Rivet for (i = 0; i < dev->data->nb_tx_queues; i++) { 64ebea83f8SGaetan Rivet struct txq *txq; 65ebea83f8SGaetan Rivet 66ebea83f8SGaetan Rivet txq = dev->data->tx_queues[i]; 67ebea83f8SGaetan Rivet ret = rte_eth_tx_queue_setup(PORT_ID(sdev), i, 68ebea83f8SGaetan Rivet txq->info.nb_desc, txq->socket_id, 69ebea83f8SGaetan Rivet &txq->info.conf); 70ebea83f8SGaetan Rivet if (ret) { 71ebea83f8SGaetan Rivet ERROR("tx_queue_setup failed"); 72ebea83f8SGaetan Rivet return ret; 73ebea83f8SGaetan Rivet } 74ebea83f8SGaetan Rivet } 75ebea83f8SGaetan Rivet /* dev_link.link_status */ 76ebea83f8SGaetan Rivet if (dev->data->dev_link.link_status != 77ebea83f8SGaetan Rivet edev->data->dev_link.link_status) { 78ebea83f8SGaetan Rivet DEBUG("Configuring link_status"); 79ebea83f8SGaetan Rivet if (dev->data->dev_link.link_status) 80ebea83f8SGaetan Rivet ret = rte_eth_dev_set_link_up(PORT_ID(sdev)); 81ebea83f8SGaetan Rivet else 82ebea83f8SGaetan Rivet ret = rte_eth_dev_set_link_down(PORT_ID(sdev)); 83ebea83f8SGaetan Rivet if (ret) { 84ebea83f8SGaetan Rivet ERROR("Failed to apply link_status"); 85ebea83f8SGaetan Rivet return ret; 86ebea83f8SGaetan Rivet } 87ebea83f8SGaetan Rivet } else { 88ebea83f8SGaetan Rivet DEBUG("link_status already set"); 89ebea83f8SGaetan Rivet } 90ebea83f8SGaetan Rivet /* promiscuous */ 91ebea83f8SGaetan Rivet if (dev->data->promiscuous != edev->data->promiscuous) { 92ebea83f8SGaetan Rivet DEBUG("Configuring promiscuous"); 93ebea83f8SGaetan Rivet if (dev->data->promiscuous) 94ebea83f8SGaetan Rivet rte_eth_promiscuous_enable(PORT_ID(sdev)); 95ebea83f8SGaetan Rivet else 96ebea83f8SGaetan Rivet rte_eth_promiscuous_disable(PORT_ID(sdev)); 97ebea83f8SGaetan Rivet } else { 98ebea83f8SGaetan Rivet DEBUG("promiscuous already set"); 99ebea83f8SGaetan Rivet } 100ebea83f8SGaetan Rivet /* all_multicast */ 101ebea83f8SGaetan Rivet if (dev->data->all_multicast != edev->data->all_multicast) { 102ebea83f8SGaetan Rivet DEBUG("Configuring all_multicast"); 103ebea83f8SGaetan Rivet if (dev->data->all_multicast) 104ebea83f8SGaetan Rivet rte_eth_allmulticast_enable(PORT_ID(sdev)); 105ebea83f8SGaetan Rivet else 106ebea83f8SGaetan Rivet rte_eth_allmulticast_disable(PORT_ID(sdev)); 107ebea83f8SGaetan Rivet } else { 108ebea83f8SGaetan Rivet DEBUG("all_multicast already set"); 109ebea83f8SGaetan Rivet } 110ebea83f8SGaetan Rivet /* MTU */ 111ebea83f8SGaetan Rivet if (dev->data->mtu != edev->data->mtu) { 112ebea83f8SGaetan Rivet DEBUG("Configuring MTU"); 113ebea83f8SGaetan Rivet ret = rte_eth_dev_set_mtu(PORT_ID(sdev), dev->data->mtu); 114ebea83f8SGaetan Rivet if (ret) { 115ebea83f8SGaetan Rivet ERROR("Failed to apply MTU"); 116ebea83f8SGaetan Rivet return ret; 117ebea83f8SGaetan Rivet } 118ebea83f8SGaetan Rivet } else { 119ebea83f8SGaetan Rivet DEBUG("MTU already set"); 120ebea83f8SGaetan Rivet } 121ebea83f8SGaetan Rivet /* default MAC */ 122ebea83f8SGaetan Rivet DEBUG("Configuring default MAC address"); 123ebea83f8SGaetan Rivet ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), 124ebea83f8SGaetan Rivet &dev->data->mac_addrs[0]); 125ebea83f8SGaetan Rivet if (ret) { 126ebea83f8SGaetan Rivet ERROR("Setting default MAC address failed"); 127ebea83f8SGaetan Rivet return ret; 128ebea83f8SGaetan Rivet } 129ebea83f8SGaetan Rivet /* additional MAC */ 130ebea83f8SGaetan Rivet if (PRIV(dev)->nb_mac_addr > 1) 131ebea83f8SGaetan Rivet DEBUG("Configure additional MAC address%s", 132ebea83f8SGaetan Rivet (PRIV(dev)->nb_mac_addr > 2 ? "es" : "")); 133ebea83f8SGaetan Rivet for (i = 1; i < PRIV(dev)->nb_mac_addr; i++) { 134ebea83f8SGaetan Rivet struct ether_addr *ea; 135ebea83f8SGaetan Rivet 136ebea83f8SGaetan Rivet ea = &dev->data->mac_addrs[i]; 137ebea83f8SGaetan Rivet ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), ea, 138ebea83f8SGaetan Rivet PRIV(dev)->mac_addr_pool[i]); 139ebea83f8SGaetan Rivet if (ret) { 140ebea83f8SGaetan Rivet char ea_fmt[ETHER_ADDR_FMT_SIZE]; 141ebea83f8SGaetan Rivet 142ebea83f8SGaetan Rivet ether_format_addr(ea_fmt, ETHER_ADDR_FMT_SIZE, ea); 143ebea83f8SGaetan Rivet ERROR("Adding MAC address %s failed", ea_fmt); 144ebea83f8SGaetan Rivet } 145ebea83f8SGaetan Rivet } 146ebea83f8SGaetan Rivet /* VLAN filter */ 147ebea83f8SGaetan Rivet vfc1 = &dev->data->vlan_filter_conf; 148ebea83f8SGaetan Rivet vfc2 = &edev->data->vlan_filter_conf; 149ebea83f8SGaetan Rivet if (memcmp(vfc1, vfc2, sizeof(struct rte_vlan_filter_conf))) { 150ebea83f8SGaetan Rivet uint64_t vbit; 151ebea83f8SGaetan Rivet uint64_t ids; 152ebea83f8SGaetan Rivet size_t i; 153ebea83f8SGaetan Rivet uint16_t vlan_id; 154ebea83f8SGaetan Rivet 155ebea83f8SGaetan Rivet DEBUG("Configuring VLAN filter"); 156ebea83f8SGaetan Rivet for (i = 0; i < RTE_DIM(vfc1->ids); i++) { 157ebea83f8SGaetan Rivet if (vfc1->ids[i] == 0) 158ebea83f8SGaetan Rivet continue; 159ebea83f8SGaetan Rivet ids = vfc1->ids[i]; 160ebea83f8SGaetan Rivet while (ids) { 161ebea83f8SGaetan Rivet vlan_id = 64 * i; 162ebea83f8SGaetan Rivet /* count trailing zeroes */ 163ebea83f8SGaetan Rivet vbit = ~ids & (ids - 1); 164ebea83f8SGaetan Rivet /* clear least significant bit set */ 165ebea83f8SGaetan Rivet ids ^= (ids ^ (ids - 1)) ^ vbit; 166ebea83f8SGaetan Rivet for (; vbit; vlan_id++) 167ebea83f8SGaetan Rivet vbit >>= 1; 168ebea83f8SGaetan Rivet ret = rte_eth_dev_vlan_filter( 169ebea83f8SGaetan Rivet PORT_ID(sdev), vlan_id, 1); 170ebea83f8SGaetan Rivet if (ret) { 171ebea83f8SGaetan Rivet ERROR("Failed to apply VLAN filter %hu", 172ebea83f8SGaetan Rivet vlan_id); 173ebea83f8SGaetan Rivet return ret; 174ebea83f8SGaetan Rivet } 175ebea83f8SGaetan Rivet } 176ebea83f8SGaetan Rivet } 177ebea83f8SGaetan Rivet } else { 178ebea83f8SGaetan Rivet DEBUG("VLAN filter already set"); 179ebea83f8SGaetan Rivet } 180ebea83f8SGaetan Rivet return 0; 181ebea83f8SGaetan Rivet } 182ebea83f8SGaetan Rivet 183ebea83f8SGaetan Rivet int 184ebea83f8SGaetan Rivet failsafe_eth_dev_state_sync(struct rte_eth_dev *dev) 185ebea83f8SGaetan Rivet { 186ebea83f8SGaetan Rivet struct sub_device *sdev; 187ebea83f8SGaetan Rivet uint32_t inactive; 188ebea83f8SGaetan Rivet int ret; 189ebea83f8SGaetan Rivet uint8_t i; 190ebea83f8SGaetan Rivet 191*a0194d82SGaetan Rivet if (PRIV(dev)->state < DEV_PARSED) 192*a0194d82SGaetan Rivet return 0; 193*a0194d82SGaetan Rivet 194*a0194d82SGaetan Rivet ret = failsafe_args_parse_subs(dev); 195*a0194d82SGaetan Rivet if (ret) 196*a0194d82SGaetan Rivet return ret; 197*a0194d82SGaetan Rivet 198ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_PROBED) 199ebea83f8SGaetan Rivet return 0; 200ebea83f8SGaetan Rivet ret = failsafe_eal_init(dev); 201ebea83f8SGaetan Rivet if (ret) 202ebea83f8SGaetan Rivet return ret; 203ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_ACTIVE) 204ebea83f8SGaetan Rivet return 0; 205ebea83f8SGaetan Rivet inactive = 0; 206ebea83f8SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) 207ebea83f8SGaetan Rivet if (sdev->state == DEV_PROBED) 208ebea83f8SGaetan Rivet inactive |= UINT32_C(1) << i; 209ebea83f8SGaetan Rivet ret = dev->dev_ops->dev_configure(dev); 210ebea83f8SGaetan Rivet if (ret) 211ebea83f8SGaetan Rivet return ret; 212ebea83f8SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) { 213ebea83f8SGaetan Rivet if (inactive & (UINT32_C(1) << i)) { 214ebea83f8SGaetan Rivet ret = fs_eth_dev_conf_apply(dev, sdev); 215ebea83f8SGaetan Rivet if (ret) { 216ebea83f8SGaetan Rivet ERROR("Could not apply configuration to sub_device %d", 217ebea83f8SGaetan Rivet i); 218ebea83f8SGaetan Rivet /* TODO: disable device */ 219ebea83f8SGaetan Rivet return ret; 220ebea83f8SGaetan Rivet } 221ebea83f8SGaetan Rivet } 222ebea83f8SGaetan Rivet } 223ebea83f8SGaetan Rivet /* 224ebea83f8SGaetan Rivet * If new devices have been configured, check if 225ebea83f8SGaetan Rivet * the link state has changed. 226ebea83f8SGaetan Rivet */ 227ebea83f8SGaetan Rivet if (inactive) 228ebea83f8SGaetan Rivet dev->dev_ops->link_update(dev, 1); 229ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_STARTED) 230ebea83f8SGaetan Rivet return 0; 231ebea83f8SGaetan Rivet ret = dev->dev_ops->dev_start(dev); 232ebea83f8SGaetan Rivet if (ret) 233ebea83f8SGaetan Rivet return ret; 234ebea83f8SGaetan Rivet return 0; 235ebea83f8SGaetan Rivet } 236