net/failsafe: add fast burst functions
[dpdk.git] / drivers / net / failsafe / failsafe_private.h
index 62b5e24..aac4754 100644 (file)
@@ -34,6 +34,8 @@
 #ifndef _RTE_ETH_FAILSAFE_PRIVATE_H_
 #define _RTE_ETH_FAILSAFE_PRIVATE_H_
 
+#include <sys/queue.h>
+
 #include <rte_dev.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
 #define FAILSAFE_DRIVER_NAME "Fail-safe PMD"
 
 #define PMD_FAILSAFE_MAC_KVARG "mac"
+#define PMD_FAILSAFE_HOTPLUG_POLL_KVARG "hotplug_poll"
 #define PMD_FAILSAFE_PARAM_STRING      \
        "dev(<ifc>),"                   \
-       "mac=mac_addr"                  \
+       "exec(<shell command>),"        \
+       "mac=mac_addr,"                 \
+       "hotplug_poll=u64"              \
        ""
 
+#define FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS 2000
+
 #define FAILSAFE_MAX_ETHPORTS 2
 #define FAILSAFE_MAX_ETHADDR 128
 
@@ -67,6 +74,14 @@ struct txq {
        struct rte_eth_txq_info info;
 };
 
+struct rte_flow {
+       TAILQ_ENTRY(rte_flow) next;
+       /* sub_flows */
+       struct rte_flow *flows[FAILSAFE_MAX_ETHPORTS];
+       /* flow description for synchronization */
+       struct rte_flow_desc *fd;
+};
+
 enum dev_state {
        DEV_UNDEFINED,
        DEV_PARSED,
@@ -81,8 +96,11 @@ struct sub_device {
        struct rte_bus *bus;
        struct rte_device *dev;
        struct rte_eth_dev *edev;
+       uint8_t sid;
        /* Device state machine */
        enum dev_state state;
+       /* Some device are defined as a command line */
+       char *cmdline;
 };
 
 struct fs_priv {
@@ -97,36 +115,66 @@ struct fs_priv {
        uint8_t subs_tail; /* first invalid */
        uint8_t subs_tx; /* current emitting device */
        uint8_t current_probed;
+       /* flow mapping */
+       TAILQ_HEAD(sub_flows, rte_flow) flow_list;
        /* current number of mac_addr slots allocated. */
        uint32_t nb_mac_addr;
        struct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR];
        uint32_t mac_addr_pool[FAILSAFE_MAX_ETHADDR];
        /* current capabilities */
        struct rte_eth_dev_info infos;
+       /*
+        * Fail-safe state machine.
+        * This level will be tracking state of the EAL and eth
+        * layer at large as defined by the user application.
+        * It will then steer the sub_devices toward the same
+        * synchronized state.
+        */
+       enum dev_state state;
+       unsigned int pending_alarm:1; /* An alarm is pending */
 };
 
+/* MISC */
+
+int failsafe_hotplug_alarm_install(struct rte_eth_dev *dev);
+int failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev);
+
 /* RX / TX */
 
+void set_burst_fn(struct rte_eth_dev *dev, int force_safe);
+
 uint16_t failsafe_rx_burst(void *rxq,
                struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
 uint16_t failsafe_tx_burst(void *txq,
                struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
 
+uint16_t failsafe_rx_burst_fast(void *rxq,
+               struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+uint16_t failsafe_tx_burst_fast(void *txq,
+               struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+
 /* ARGS */
 
 int failsafe_args_parse(struct rte_eth_dev *dev, const char *params);
 void failsafe_args_free(struct rte_eth_dev *dev);
 int failsafe_args_count_subdevice(struct rte_eth_dev *dev, const char *params);
+int failsafe_args_parse_subs(struct rte_eth_dev *dev);
 
 /* EAL */
 
 int failsafe_eal_init(struct rte_eth_dev *dev);
 int failsafe_eal_uninit(struct rte_eth_dev *dev);
 
+/* ETH_DEV */
+
+int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev);
+
 /* GLOBALS */
 
 extern const char pmd_failsafe_driver_name[];
 extern const struct eth_dev_ops failsafe_ops;
+extern const struct rte_flow_ops fs_flow_ops;
+extern uint64_t hotplug_poll;
 extern int mac_from_arg;
 
 /* HELPERS */
@@ -143,6 +191,10 @@ extern int mac_from_arg;
 #define PORT_ID(sdev) \
        (ETH(sdev)->data->port_id)
 
+/* sdev: (struct sub_device *) */
+#define SUB_ID(sdev) \
+       ((sdev)->sid)
+
 /**
  * Stateful iterator construct over fail-safe sub-devices:
  * s:     (struct sub_device *), iterator
@@ -205,4 +257,40 @@ fs_find_next(struct rte_eth_dev *dev, uint8_t sid,
        return sid;
 }
 
+static inline void
+fs_switch_dev(struct rte_eth_dev *dev)
+{
+       enum dev_state req_state;
+
+       req_state = PRIV(dev)->state;
+       if (PREFERRED_SUBDEV(dev)->state >= req_state) {
+               if (TX_SUBDEV(dev) != PREFERRED_SUBDEV(dev) &&
+                   (TX_SUBDEV(dev) == NULL ||
+                    (req_state == DEV_STARTED) ||
+                    (TX_SUBDEV(dev) && TX_SUBDEV(dev)->state < DEV_STARTED))) {
+                       DEBUG("Switching tx_dev to preferred sub_device");
+                       PRIV(dev)->subs_tx = 0;
+               }
+       } else if ((TX_SUBDEV(dev) && TX_SUBDEV(dev)->state < req_state) ||
+                  TX_SUBDEV(dev) == NULL) {
+               struct sub_device *sdev;
+               uint8_t i;
+
+               /* Using acceptable device */
+               FOREACH_SUBDEV_STATE(sdev, i, dev, req_state) {
+                       DEBUG("Switching tx_dev to sub_device %d",
+                             i);
+                       PRIV(dev)->subs_tx = i;
+                       break;
+               }
+       } else if (TX_SUBDEV(dev) && TX_SUBDEV(dev)->state < req_state) {
+               DEBUG("No device ready, deactivating tx_dev");
+               PRIV(dev)->subs_tx = PRIV(dev)->subs_tail;
+       } else {
+               return;
+       }
+       set_burst_fn(dev, 0);
+       rte_wmb();
+}
+
 #endif /* _RTE_ETH_FAILSAFE_PRIVATE_H_ */