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 36b737a1eeSGaetan Rivet #include <rte_flow.h> 37b737a1eeSGaetan Rivet #include <rte_flow_driver.h> 38*9dda3e33SMatan Azrad #include <rte_cycles.h> 39b737a1eeSGaetan Rivet 40ebea83f8SGaetan Rivet #include "failsafe_private.h" 41ebea83f8SGaetan Rivet 42b737a1eeSGaetan Rivet /** Print a message out of a flow error. */ 43b737a1eeSGaetan Rivet static int 44b737a1eeSGaetan Rivet fs_flow_complain(struct rte_flow_error *error) 45b737a1eeSGaetan Rivet { 46b737a1eeSGaetan Rivet static const char *const errstrlist[] = { 47b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_NONE] = "no error", 48b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified", 49b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)", 50b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field", 51b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field", 52b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field", 53b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field", 54b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure", 55b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length", 56b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item", 57b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions", 58b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action", 59b737a1eeSGaetan Rivet }; 60b737a1eeSGaetan Rivet const char *errstr; 61b737a1eeSGaetan Rivet char buf[32]; 62b737a1eeSGaetan Rivet int err = rte_errno; 63b737a1eeSGaetan Rivet 64b737a1eeSGaetan Rivet if ((unsigned int)error->type >= RTE_DIM(errstrlist) || 65b737a1eeSGaetan Rivet !errstrlist[error->type]) 66b737a1eeSGaetan Rivet errstr = "unknown type"; 67b737a1eeSGaetan Rivet else 68b737a1eeSGaetan Rivet errstr = errstrlist[error->type]; 69b737a1eeSGaetan Rivet ERROR("Caught error type %d (%s): %s%s\n", 70b737a1eeSGaetan Rivet error->type, errstr, 71b737a1eeSGaetan Rivet error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ", 72b737a1eeSGaetan Rivet error->cause), buf) : "", 73b737a1eeSGaetan Rivet error->message ? error->message : "(no stated reason)"); 74b737a1eeSGaetan Rivet return -err; 75b737a1eeSGaetan Rivet } 76b737a1eeSGaetan Rivet 77ebea83f8SGaetan Rivet static int 782cc52cd7SGaetan Rivet eth_dev_flow_isolate_set(struct rte_eth_dev *dev, 792cc52cd7SGaetan Rivet struct sub_device *sdev) 802cc52cd7SGaetan Rivet { 812cc52cd7SGaetan Rivet struct rte_flow_error ferror; 822cc52cd7SGaetan Rivet int ret; 832cc52cd7SGaetan Rivet 842cc52cd7SGaetan Rivet if (!PRIV(dev)->flow_isolated) { 852cc52cd7SGaetan Rivet DEBUG("Flow isolation already disabled"); 862cc52cd7SGaetan Rivet } else { 872cc52cd7SGaetan Rivet DEBUG("Enabling flow isolation"); 882cc52cd7SGaetan Rivet ret = rte_flow_isolate(PORT_ID(sdev), 892cc52cd7SGaetan Rivet PRIV(dev)->flow_isolated, 902cc52cd7SGaetan Rivet &ferror); 912cc52cd7SGaetan Rivet if (ret) { 922cc52cd7SGaetan Rivet fs_flow_complain(&ferror); 932cc52cd7SGaetan Rivet return ret; 942cc52cd7SGaetan Rivet } 952cc52cd7SGaetan Rivet } 962cc52cd7SGaetan Rivet return 0; 972cc52cd7SGaetan Rivet } 982cc52cd7SGaetan Rivet 992cc52cd7SGaetan Rivet static int 100ebea83f8SGaetan Rivet fs_eth_dev_conf_apply(struct rte_eth_dev *dev, 101ebea83f8SGaetan Rivet struct sub_device *sdev) 102ebea83f8SGaetan Rivet { 103ebea83f8SGaetan Rivet struct rte_eth_dev *edev; 104ebea83f8SGaetan Rivet struct rte_vlan_filter_conf *vfc1; 105ebea83f8SGaetan Rivet struct rte_vlan_filter_conf *vfc2; 106b737a1eeSGaetan Rivet struct rte_flow *flow; 107b737a1eeSGaetan Rivet struct rte_flow_error ferror; 108ebea83f8SGaetan Rivet uint32_t i; 109ebea83f8SGaetan Rivet int ret; 110ebea83f8SGaetan Rivet 111ebea83f8SGaetan Rivet edev = ETH(sdev); 112ebea83f8SGaetan Rivet /* RX queue setup */ 113ebea83f8SGaetan Rivet for (i = 0; i < dev->data->nb_rx_queues; i++) { 114ebea83f8SGaetan Rivet struct rxq *rxq; 115ebea83f8SGaetan Rivet 116ebea83f8SGaetan Rivet rxq = dev->data->rx_queues[i]; 117ebea83f8SGaetan Rivet ret = rte_eth_rx_queue_setup(PORT_ID(sdev), i, 118ebea83f8SGaetan Rivet rxq->info.nb_desc, rxq->socket_id, 119ebea83f8SGaetan Rivet &rxq->info.conf, rxq->info.mp); 120ebea83f8SGaetan Rivet if (ret) { 121ebea83f8SGaetan Rivet ERROR("rx_queue_setup failed"); 122ebea83f8SGaetan Rivet return ret; 123ebea83f8SGaetan Rivet } 124ebea83f8SGaetan Rivet } 125ebea83f8SGaetan Rivet /* TX queue setup */ 126ebea83f8SGaetan Rivet for (i = 0; i < dev->data->nb_tx_queues; i++) { 127ebea83f8SGaetan Rivet struct txq *txq; 128ebea83f8SGaetan Rivet 129ebea83f8SGaetan Rivet txq = dev->data->tx_queues[i]; 130ebea83f8SGaetan Rivet ret = rte_eth_tx_queue_setup(PORT_ID(sdev), i, 131ebea83f8SGaetan Rivet txq->info.nb_desc, txq->socket_id, 132ebea83f8SGaetan Rivet &txq->info.conf); 133ebea83f8SGaetan Rivet if (ret) { 134ebea83f8SGaetan Rivet ERROR("tx_queue_setup failed"); 135ebea83f8SGaetan Rivet return ret; 136ebea83f8SGaetan Rivet } 137ebea83f8SGaetan Rivet } 138ebea83f8SGaetan Rivet /* dev_link.link_status */ 139ebea83f8SGaetan Rivet if (dev->data->dev_link.link_status != 140ebea83f8SGaetan Rivet edev->data->dev_link.link_status) { 141ebea83f8SGaetan Rivet DEBUG("Configuring link_status"); 142ebea83f8SGaetan Rivet if (dev->data->dev_link.link_status) 143ebea83f8SGaetan Rivet ret = rte_eth_dev_set_link_up(PORT_ID(sdev)); 144ebea83f8SGaetan Rivet else 145ebea83f8SGaetan Rivet ret = rte_eth_dev_set_link_down(PORT_ID(sdev)); 146ebea83f8SGaetan Rivet if (ret) { 147ebea83f8SGaetan Rivet ERROR("Failed to apply link_status"); 148ebea83f8SGaetan Rivet return ret; 149ebea83f8SGaetan Rivet } 150ebea83f8SGaetan Rivet } else { 151ebea83f8SGaetan Rivet DEBUG("link_status already set"); 152ebea83f8SGaetan Rivet } 153ebea83f8SGaetan Rivet /* promiscuous */ 154ebea83f8SGaetan Rivet if (dev->data->promiscuous != edev->data->promiscuous) { 155ebea83f8SGaetan Rivet DEBUG("Configuring promiscuous"); 156ebea83f8SGaetan Rivet if (dev->data->promiscuous) 157ebea83f8SGaetan Rivet rte_eth_promiscuous_enable(PORT_ID(sdev)); 158ebea83f8SGaetan Rivet else 159ebea83f8SGaetan Rivet rte_eth_promiscuous_disable(PORT_ID(sdev)); 160ebea83f8SGaetan Rivet } else { 161ebea83f8SGaetan Rivet DEBUG("promiscuous already set"); 162ebea83f8SGaetan Rivet } 163ebea83f8SGaetan Rivet /* all_multicast */ 164ebea83f8SGaetan Rivet if (dev->data->all_multicast != edev->data->all_multicast) { 165ebea83f8SGaetan Rivet DEBUG("Configuring all_multicast"); 166ebea83f8SGaetan Rivet if (dev->data->all_multicast) 167ebea83f8SGaetan Rivet rte_eth_allmulticast_enable(PORT_ID(sdev)); 168ebea83f8SGaetan Rivet else 169ebea83f8SGaetan Rivet rte_eth_allmulticast_disable(PORT_ID(sdev)); 170ebea83f8SGaetan Rivet } else { 171ebea83f8SGaetan Rivet DEBUG("all_multicast already set"); 172ebea83f8SGaetan Rivet } 173ebea83f8SGaetan Rivet /* MTU */ 174ebea83f8SGaetan Rivet if (dev->data->mtu != edev->data->mtu) { 175ebea83f8SGaetan Rivet DEBUG("Configuring MTU"); 176ebea83f8SGaetan Rivet ret = rte_eth_dev_set_mtu(PORT_ID(sdev), dev->data->mtu); 177ebea83f8SGaetan Rivet if (ret) { 178ebea83f8SGaetan Rivet ERROR("Failed to apply MTU"); 179ebea83f8SGaetan Rivet return ret; 180ebea83f8SGaetan Rivet } 181ebea83f8SGaetan Rivet } else { 182ebea83f8SGaetan Rivet DEBUG("MTU already set"); 183ebea83f8SGaetan Rivet } 184ebea83f8SGaetan Rivet /* default MAC */ 185ebea83f8SGaetan Rivet DEBUG("Configuring default MAC address"); 186ebea83f8SGaetan Rivet ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), 187ebea83f8SGaetan Rivet &dev->data->mac_addrs[0]); 188ebea83f8SGaetan Rivet if (ret) { 189ebea83f8SGaetan Rivet ERROR("Setting default MAC address failed"); 190ebea83f8SGaetan Rivet return ret; 191ebea83f8SGaetan Rivet } 192ebea83f8SGaetan Rivet /* additional MAC */ 193ebea83f8SGaetan Rivet if (PRIV(dev)->nb_mac_addr > 1) 194ebea83f8SGaetan Rivet DEBUG("Configure additional MAC address%s", 195ebea83f8SGaetan Rivet (PRIV(dev)->nb_mac_addr > 2 ? "es" : "")); 196ebea83f8SGaetan Rivet for (i = 1; i < PRIV(dev)->nb_mac_addr; i++) { 197ebea83f8SGaetan Rivet struct ether_addr *ea; 198ebea83f8SGaetan Rivet 199ebea83f8SGaetan Rivet ea = &dev->data->mac_addrs[i]; 200ebea83f8SGaetan Rivet ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), ea, 201ebea83f8SGaetan Rivet PRIV(dev)->mac_addr_pool[i]); 202ebea83f8SGaetan Rivet if (ret) { 203ebea83f8SGaetan Rivet char ea_fmt[ETHER_ADDR_FMT_SIZE]; 204ebea83f8SGaetan Rivet 205ebea83f8SGaetan Rivet ether_format_addr(ea_fmt, ETHER_ADDR_FMT_SIZE, ea); 206ebea83f8SGaetan Rivet ERROR("Adding MAC address %s failed", ea_fmt); 207ae7cb246SMatan Azrad return ret; 208ebea83f8SGaetan Rivet } 209ebea83f8SGaetan Rivet } 210ebea83f8SGaetan Rivet /* VLAN filter */ 211ebea83f8SGaetan Rivet vfc1 = &dev->data->vlan_filter_conf; 212ebea83f8SGaetan Rivet vfc2 = &edev->data->vlan_filter_conf; 213ebea83f8SGaetan Rivet if (memcmp(vfc1, vfc2, sizeof(struct rte_vlan_filter_conf))) { 214ebea83f8SGaetan Rivet uint64_t vbit; 215ebea83f8SGaetan Rivet uint64_t ids; 216ebea83f8SGaetan Rivet size_t i; 217ebea83f8SGaetan Rivet uint16_t vlan_id; 218ebea83f8SGaetan Rivet 219ebea83f8SGaetan Rivet DEBUG("Configuring VLAN filter"); 220ebea83f8SGaetan Rivet for (i = 0; i < RTE_DIM(vfc1->ids); i++) { 221ebea83f8SGaetan Rivet if (vfc1->ids[i] == 0) 222ebea83f8SGaetan Rivet continue; 223ebea83f8SGaetan Rivet ids = vfc1->ids[i]; 224ebea83f8SGaetan Rivet while (ids) { 225ebea83f8SGaetan Rivet vlan_id = 64 * i; 226ebea83f8SGaetan Rivet /* count trailing zeroes */ 227ebea83f8SGaetan Rivet vbit = ~ids & (ids - 1); 228ebea83f8SGaetan Rivet /* clear least significant bit set */ 229ebea83f8SGaetan Rivet ids ^= (ids ^ (ids - 1)) ^ vbit; 230ebea83f8SGaetan Rivet for (; vbit; vlan_id++) 231ebea83f8SGaetan Rivet vbit >>= 1; 232ebea83f8SGaetan Rivet ret = rte_eth_dev_vlan_filter( 233ebea83f8SGaetan Rivet PORT_ID(sdev), vlan_id, 1); 234ebea83f8SGaetan Rivet if (ret) { 235ebea83f8SGaetan Rivet ERROR("Failed to apply VLAN filter %hu", 236ebea83f8SGaetan Rivet vlan_id); 237ebea83f8SGaetan Rivet return ret; 238ebea83f8SGaetan Rivet } 239ebea83f8SGaetan Rivet } 240ebea83f8SGaetan Rivet } 241ebea83f8SGaetan Rivet } else { 242ebea83f8SGaetan Rivet DEBUG("VLAN filter already set"); 243ebea83f8SGaetan Rivet } 244b737a1eeSGaetan Rivet /* rte_flow */ 245b737a1eeSGaetan Rivet if (TAILQ_EMPTY(&PRIV(dev)->flow_list)) { 246b737a1eeSGaetan Rivet DEBUG("rte_flow already set"); 247b737a1eeSGaetan Rivet } else { 248b737a1eeSGaetan Rivet DEBUG("Resetting rte_flow configuration"); 249b737a1eeSGaetan Rivet ret = rte_flow_flush(PORT_ID(sdev), &ferror); 250b737a1eeSGaetan Rivet if (ret) { 251b737a1eeSGaetan Rivet fs_flow_complain(&ferror); 252b737a1eeSGaetan Rivet return ret; 253b737a1eeSGaetan Rivet } 254b737a1eeSGaetan Rivet i = 0; 255b737a1eeSGaetan Rivet rte_errno = 0; 256b737a1eeSGaetan Rivet DEBUG("Configuring rte_flow"); 257b737a1eeSGaetan Rivet TAILQ_FOREACH(flow, &PRIV(dev)->flow_list, next) { 258b737a1eeSGaetan Rivet DEBUG("Creating flow #%" PRIu32, i++); 259b737a1eeSGaetan Rivet flow->flows[SUB_ID(sdev)] = 260b737a1eeSGaetan Rivet rte_flow_create(PORT_ID(sdev), 261b737a1eeSGaetan Rivet &flow->fd->attr, 262b737a1eeSGaetan Rivet flow->fd->items, 263b737a1eeSGaetan Rivet flow->fd->actions, 264b737a1eeSGaetan Rivet &ferror); 265b737a1eeSGaetan Rivet ret = rte_errno; 266b737a1eeSGaetan Rivet if (ret) 267b737a1eeSGaetan Rivet break; 268b737a1eeSGaetan Rivet } 269b737a1eeSGaetan Rivet if (ret) { 270b737a1eeSGaetan Rivet fs_flow_complain(&ferror); 271b737a1eeSGaetan Rivet return ret; 272b737a1eeSGaetan Rivet } 273b737a1eeSGaetan Rivet } 274ebea83f8SGaetan Rivet return 0; 275ebea83f8SGaetan Rivet } 276ebea83f8SGaetan Rivet 277598fb8aeSGaetan Rivet static void 278598fb8aeSGaetan Rivet fs_dev_remove(struct sub_device *sdev) 279598fb8aeSGaetan Rivet { 280598fb8aeSGaetan Rivet int ret; 281598fb8aeSGaetan Rivet 282598fb8aeSGaetan Rivet if (sdev == NULL) 283598fb8aeSGaetan Rivet return; 284598fb8aeSGaetan Rivet switch (sdev->state) { 285598fb8aeSGaetan Rivet case DEV_STARTED: 286598fb8aeSGaetan Rivet rte_eth_dev_stop(PORT_ID(sdev)); 287598fb8aeSGaetan Rivet sdev->state = DEV_ACTIVE; 288598fb8aeSGaetan Rivet /* fallthrough */ 289598fb8aeSGaetan Rivet case DEV_ACTIVE: 290598fb8aeSGaetan Rivet rte_eth_dev_close(PORT_ID(sdev)); 291598fb8aeSGaetan Rivet sdev->state = DEV_PROBED; 292598fb8aeSGaetan Rivet /* fallthrough */ 293598fb8aeSGaetan Rivet case DEV_PROBED: 294598fb8aeSGaetan Rivet ret = rte_eal_hotplug_remove(sdev->bus->name, 295598fb8aeSGaetan Rivet sdev->dev->name); 296598fb8aeSGaetan Rivet if (ret) { 297598fb8aeSGaetan Rivet ERROR("Bus detach failed for sub_device %u", 298598fb8aeSGaetan Rivet SUB_ID(sdev)); 299598fb8aeSGaetan Rivet } else { 300598fb8aeSGaetan Rivet ETH(sdev)->state = RTE_ETH_DEV_UNUSED; 301598fb8aeSGaetan Rivet } 302598fb8aeSGaetan Rivet sdev->state = DEV_PARSED; 303598fb8aeSGaetan Rivet /* fallthrough */ 304598fb8aeSGaetan Rivet case DEV_PARSED: 305598fb8aeSGaetan Rivet case DEV_UNDEFINED: 306598fb8aeSGaetan Rivet sdev->state = DEV_UNDEFINED; 307598fb8aeSGaetan Rivet /* the end */ 308598fb8aeSGaetan Rivet break; 309598fb8aeSGaetan Rivet } 310598fb8aeSGaetan Rivet failsafe_hotplug_alarm_install(sdev->fs_dev); 311598fb8aeSGaetan Rivet } 312598fb8aeSGaetan Rivet 3136265ab51SMatan Azrad static void 3146265ab51SMatan Azrad fs_dev_stats_save(struct sub_device *sdev) 3156265ab51SMatan Azrad { 316321809bbSMatan Azrad struct rte_eth_stats stats; 317321809bbSMatan Azrad int err; 318321809bbSMatan Azrad 319321809bbSMatan Azrad /* Attempt to read current stats. */ 320321809bbSMatan Azrad err = rte_eth_stats_get(PORT_ID(sdev), &stats); 321*9dda3e33SMatan Azrad if (err) { 322*9dda3e33SMatan Azrad uint64_t timestamp = sdev->stats_snapshot.timestamp; 323*9dda3e33SMatan Azrad 324*9dda3e33SMatan Azrad WARN("Could not access latest statistics from sub-device %d.\n", 325*9dda3e33SMatan Azrad SUB_ID(sdev)); 326*9dda3e33SMatan Azrad if (timestamp != 0) 327*9dda3e33SMatan Azrad WARN("Using latest snapshot taken before %"PRIu64" seconds.\n", 328*9dda3e33SMatan Azrad (rte_rdtsc() - timestamp) / rte_get_tsc_hz()); 329*9dda3e33SMatan Azrad } 3306265ab51SMatan Azrad failsafe_stats_increment(&PRIV(sdev->fs_dev)->stats_accumulator, 331*9dda3e33SMatan Azrad err ? &sdev->stats_snapshot.stats : &stats); 332*9dda3e33SMatan Azrad memset(&sdev->stats_snapshot, 0, sizeof(sdev->stats_snapshot)); 3336265ab51SMatan Azrad } 3346265ab51SMatan Azrad 335598fb8aeSGaetan Rivet static inline int 336598fb8aeSGaetan Rivet fs_rxtx_clean(struct sub_device *sdev) 337598fb8aeSGaetan Rivet { 338598fb8aeSGaetan Rivet uint16_t i; 339598fb8aeSGaetan Rivet 340598fb8aeSGaetan Rivet for (i = 0; i < ETH(sdev)->data->nb_rx_queues; i++) 341598fb8aeSGaetan Rivet if (FS_ATOMIC_RX(sdev, i)) 342598fb8aeSGaetan Rivet return 0; 343598fb8aeSGaetan Rivet for (i = 0; i < ETH(sdev)->data->nb_tx_queues; i++) 344598fb8aeSGaetan Rivet if (FS_ATOMIC_TX(sdev, i)) 345598fb8aeSGaetan Rivet return 0; 346598fb8aeSGaetan Rivet return 1; 347598fb8aeSGaetan Rivet } 348598fb8aeSGaetan Rivet 349598fb8aeSGaetan Rivet void 350598fb8aeSGaetan Rivet failsafe_dev_remove(struct rte_eth_dev *dev) 351598fb8aeSGaetan Rivet { 352598fb8aeSGaetan Rivet struct sub_device *sdev; 353598fb8aeSGaetan Rivet uint8_t i; 354598fb8aeSGaetan Rivet 355598fb8aeSGaetan Rivet FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) 3566265ab51SMatan Azrad if (sdev->remove && fs_rxtx_clean(sdev)) { 3576265ab51SMatan Azrad fs_dev_stats_save(sdev); 358598fb8aeSGaetan Rivet fs_dev_remove(sdev); 359598fb8aeSGaetan Rivet } 3606265ab51SMatan Azrad } 361598fb8aeSGaetan Rivet 362ebea83f8SGaetan Rivet int 363ebea83f8SGaetan Rivet failsafe_eth_dev_state_sync(struct rte_eth_dev *dev) 364ebea83f8SGaetan Rivet { 365ebea83f8SGaetan Rivet struct sub_device *sdev; 366ebea83f8SGaetan Rivet uint32_t inactive; 367ebea83f8SGaetan Rivet int ret; 368ebea83f8SGaetan Rivet uint8_t i; 369ebea83f8SGaetan Rivet 370a0194d82SGaetan Rivet if (PRIV(dev)->state < DEV_PARSED) 371a0194d82SGaetan Rivet return 0; 372a0194d82SGaetan Rivet 373a0194d82SGaetan Rivet ret = failsafe_args_parse_subs(dev); 374a0194d82SGaetan Rivet if (ret) 375598fb8aeSGaetan Rivet goto err_remove; 376a0194d82SGaetan Rivet 377ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_PROBED) 378ebea83f8SGaetan Rivet return 0; 379ebea83f8SGaetan Rivet ret = failsafe_eal_init(dev); 380ebea83f8SGaetan Rivet if (ret) 381598fb8aeSGaetan Rivet goto err_remove; 382ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_ACTIVE) 383ebea83f8SGaetan Rivet return 0; 384ebea83f8SGaetan Rivet inactive = 0; 3852cc52cd7SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) { 3862cc52cd7SGaetan Rivet if (sdev->state == DEV_PROBED) { 387ebea83f8SGaetan Rivet inactive |= UINT32_C(1) << i; 3882cc52cd7SGaetan Rivet ret = eth_dev_flow_isolate_set(dev, sdev); 3892cc52cd7SGaetan Rivet if (ret) { 3902cc52cd7SGaetan Rivet ERROR("Could not apply configuration to sub_device %d", 3912cc52cd7SGaetan Rivet i); 3922cc52cd7SGaetan Rivet goto err_remove; 3932cc52cd7SGaetan Rivet } 3942cc52cd7SGaetan Rivet } 3952cc52cd7SGaetan Rivet } 396ebea83f8SGaetan Rivet ret = dev->dev_ops->dev_configure(dev); 397ebea83f8SGaetan Rivet if (ret) 398598fb8aeSGaetan Rivet goto err_remove; 399ebea83f8SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) { 400ebea83f8SGaetan Rivet if (inactive & (UINT32_C(1) << i)) { 401ebea83f8SGaetan Rivet ret = fs_eth_dev_conf_apply(dev, sdev); 402ebea83f8SGaetan Rivet if (ret) { 403ebea83f8SGaetan Rivet ERROR("Could not apply configuration to sub_device %d", 404ebea83f8SGaetan Rivet i); 405598fb8aeSGaetan Rivet goto err_remove; 406ebea83f8SGaetan Rivet } 407ebea83f8SGaetan Rivet } 408ebea83f8SGaetan Rivet } 409ebea83f8SGaetan Rivet /* 410ebea83f8SGaetan Rivet * If new devices have been configured, check if 411ebea83f8SGaetan Rivet * the link state has changed. 412ebea83f8SGaetan Rivet */ 413ebea83f8SGaetan Rivet if (inactive) 414ebea83f8SGaetan Rivet dev->dev_ops->link_update(dev, 1); 415ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_STARTED) 416ebea83f8SGaetan Rivet return 0; 417ebea83f8SGaetan Rivet ret = dev->dev_ops->dev_start(dev); 418ebea83f8SGaetan Rivet if (ret) 419598fb8aeSGaetan Rivet goto err_remove; 420598fb8aeSGaetan Rivet return 0; 421598fb8aeSGaetan Rivet err_remove: 422598fb8aeSGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) 423598fb8aeSGaetan Rivet if (sdev->state != PRIV(dev)->state) 424598fb8aeSGaetan Rivet sdev->remove = 1; 425ebea83f8SGaetan Rivet return ret; 426598fb8aeSGaetan Rivet } 427598fb8aeSGaetan Rivet 4286265ab51SMatan Azrad void 4296265ab51SMatan Azrad failsafe_stats_increment(struct rte_eth_stats *to, struct rte_eth_stats *from) 4306265ab51SMatan Azrad { 4316265ab51SMatan Azrad uint32_t i; 4326265ab51SMatan Azrad 4336265ab51SMatan Azrad RTE_ASSERT(to != NULL && from != NULL); 4346265ab51SMatan Azrad to->ipackets += from->ipackets; 4356265ab51SMatan Azrad to->opackets += from->opackets; 4366265ab51SMatan Azrad to->ibytes += from->ibytes; 4376265ab51SMatan Azrad to->obytes += from->obytes; 4386265ab51SMatan Azrad to->imissed += from->imissed; 4396265ab51SMatan Azrad to->ierrors += from->ierrors; 4406265ab51SMatan Azrad to->oerrors += from->oerrors; 4416265ab51SMatan Azrad to->rx_nombuf += from->rx_nombuf; 4426265ab51SMatan Azrad for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 4436265ab51SMatan Azrad to->q_ipackets[i] += from->q_ipackets[i]; 4446265ab51SMatan Azrad to->q_opackets[i] += from->q_opackets[i]; 4456265ab51SMatan Azrad to->q_ibytes[i] += from->q_ibytes[i]; 4466265ab51SMatan Azrad to->q_obytes[i] += from->q_obytes[i]; 4476265ab51SMatan Azrad to->q_errors[i] += from->q_errors[i]; 4486265ab51SMatan Azrad } 4496265ab51SMatan Azrad } 4506265ab51SMatan Azrad 451598fb8aeSGaetan Rivet int 452f8244c63SZhiyong Yang failsafe_eth_rmv_event_callback(uint16_t port_id __rte_unused, 453598fb8aeSGaetan Rivet enum rte_eth_event_type event __rte_unused, 454598fb8aeSGaetan Rivet void *cb_arg, void *out __rte_unused) 455598fb8aeSGaetan Rivet { 456598fb8aeSGaetan Rivet struct sub_device *sdev = cb_arg; 457598fb8aeSGaetan Rivet 458598fb8aeSGaetan Rivet /* Switch as soon as possible tx_dev. */ 459598fb8aeSGaetan Rivet fs_switch_dev(sdev->fs_dev, sdev); 460598fb8aeSGaetan Rivet /* Use safe bursts in any case. */ 461598fb8aeSGaetan Rivet set_burst_fn(sdev->fs_dev, 1); 462598fb8aeSGaetan Rivet /* 463598fb8aeSGaetan Rivet * Async removal, the sub-PMD will try to unregister 464598fb8aeSGaetan Rivet * the callback at the source of the current thread context. 465598fb8aeSGaetan Rivet */ 466598fb8aeSGaetan Rivet sdev->remove = 1; 467ebea83f8SGaetan Rivet return 0; 468ebea83f8SGaetan Rivet } 469ad7d6a35SGaetan Rivet 470ad7d6a35SGaetan Rivet int 471f8244c63SZhiyong Yang failsafe_eth_lsc_event_callback(uint16_t port_id __rte_unused, 472ad7d6a35SGaetan Rivet enum rte_eth_event_type event __rte_unused, 473ad7d6a35SGaetan Rivet void *cb_arg, void *out __rte_unused) 474ad7d6a35SGaetan Rivet { 475ad7d6a35SGaetan Rivet struct rte_eth_dev *dev = cb_arg; 476ad7d6a35SGaetan Rivet int ret; 477ad7d6a35SGaetan Rivet 478ad7d6a35SGaetan Rivet ret = dev->dev_ops->link_update(dev, 0); 479ad7d6a35SGaetan Rivet /* We must pass on the LSC event */ 480ad7d6a35SGaetan Rivet if (ret) 481ad7d6a35SGaetan Rivet return _rte_eth_dev_callback_process(dev, 482ad7d6a35SGaetan Rivet RTE_ETH_EVENT_INTR_LSC, 483ad7d6a35SGaetan Rivet NULL, NULL); 484ad7d6a35SGaetan Rivet else 485ad7d6a35SGaetan Rivet return 0; 486ad7d6a35SGaetan Rivet } 487