use testpmd for example, to show app how to request and use
uevent monitoring to handle the hot removal event and the
hot insertion event.

Signed-off-by: Jeff Guo <jia....@intel.com>
---
v5->v4:
add new callback to process hot insertion 
---
 app/test-pmd/testpmd.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index e097ee0..df2bb48 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -393,6 +393,9 @@ static void check_all_ports_link_status(uint32_t port_mask);
 static int eth_event_callback(uint8_t port_id,
                              enum rte_eth_event_type type,
                              void *param, void *ret_param);
+static int eth_uevent_callback(enum rte_eal_dev_event_type type,
+                             void *param, void *ret_param);
+
 
 /*
  * Check if all the ports are started.
@@ -1413,6 +1416,7 @@ start_port(portid_t pid)
        struct rte_port *port;
        struct ether_addr mac_addr;
        enum rte_eth_event_type event_type;
+       enum rte_eal_dev_event_type dev_event_type;
 
        if (port_id_is_invalid(pid, ENABLED_WARN))
                return 0;
@@ -1547,6 +1551,21 @@ start_port(portid_t pid)
                                return -1;
                        }
                }
+               rte_eal_dev_monitor_enable();
+
+               for (dev_event_type = RTE_EAL_DEV_EVENT_UNKNOWN;
+                    dev_event_type < RTE_EAL_DEV_EVENT_MAX;
+                    dev_event_type++) {
+                       diag = rte_dev_callback_register(dev_event_type,
+                                       eth_uevent_callback,
+                                       &pi);
+                       if (diag) {
+                               printf("Failed to setup uevent callback for"
+                                       " device event %d\n",
+                                       dev_event_type);
+                               return -1;
+                       }
+               }
 
                /* start port */
                if (rte_eth_dev_start(pi) < 0) {
@@ -1883,6 +1902,35 @@ rmv_event_callback(void *arg)
                        dev->device->name);
 }
 
+static void
+rmv_uevent_callback(void *arg)
+{
+       char name[RTE_ETH_NAME_MAX_LEN];
+
+       uint8_t port_id = *(uint8_t *)arg;
+
+       printf("removing device port_id:%u\n", port_id);
+
+       if (rte_eth_dev_detach(port_id, name)) {
+               RTE_LOG(ERR, USER1, "Failed to detach port '%s'\n", name);
+               return;
+       }
+
+       nb_ports = rte_eth_dev_count();
+
+       printf("Port '%s' is detached. Now total ports is %d\n",
+                       name, nb_ports);
+}
+
+static void
+add_uevent_callback(void *arg)
+{
+       char *dev_name = (char *)arg;
+
+       printf("adding device %s\n", dev_name);
+       attach_port(dev_name);
+}
+
 /* This function is used by the interrupt thread */
 static int
 eth_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param,
@@ -1924,6 +1972,48 @@ eth_event_callback(uint8_t port_id, enum 
rte_eth_event_type type, void *param,
        return 0;
 }
 
+/* This function is used by the interrupt thread */
+static int
+eth_uevent_callback(enum rte_eal_dev_event_type type, void *arg,
+                 void *ret_param)
+{
+       static const char * const event_desc[] = {
+               [RTE_EAL_DEV_EVENT_UNKNOWN] = "Unknown",
+               [RTE_EAL_DEV_EVENT_ADD] = "add",
+               [RTE_EAL_DEV_EVENT_REMOVE] = "remove",
+       };
+
+       RTE_SET_USED(ret_param);
+
+       if (type >= RTE_EAL_DEV_EVENT_MAX) {
+               fprintf(stderr, "%s called upon invalid event %d\n",
+                       __func__, type);
+               fflush(stderr);
+       } else if (event_print_mask & (UINT32_C(1) << type)) {
+               printf("%s event\n",
+                       event_desc[type]);
+               fflush(stdout);
+       }
+
+       switch (type) {
+       case RTE_EAL_DEV_EVENT_ADD:
+               if (rte_eal_alarm_set(2000000,
+                       add_uevent_callback, (void *)arg))
+                       fprintf(stderr, "Could not set up deferred "
+                               "device removal\n");
+               break;
+       case RTE_EAL_DEV_EVENT_REMOVE:
+               if (rte_eal_alarm_set(100000,
+                       rmv_uevent_callback, (void *)arg))
+                       fprintf(stderr, "Could not set up deferred "
+                               "device removal\n");
+               break;
+       default:
+               break;
+       }
+       return 0;
+}
+
 static int
 set_tx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port)
 {
-- 
2.7.4

Reply via email to