LCOV - code coverage report
Current view: top level - lib/eal/common - hotplug_mp.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 9 198 4.5 %
Date: 2025-01-02 22:41:34 Functions: 2 10 20.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 6 110 5.5 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Intel Corporation
       3                 :            :  */
       4                 :            : #include <stdlib.h>
       5                 :            : #include <string.h>
       6                 :            : 
       7                 :            : #include <bus_driver.h>
       8                 :            : #include <rte_eal.h>
       9                 :            : #include <rte_errno.h>
      10                 :            : #include <rte_alarm.h>
      11                 :            : #include <rte_string_fns.h>
      12                 :            : #include <rte_devargs.h>
      13                 :            : 
      14                 :            : #include "hotplug_mp.h"
      15                 :            : #include "eal_private.h"
      16                 :            : 
      17                 :            : #define MP_TIMEOUT_S 5 /**< 5 seconds timeouts */
      18                 :            : 
      19                 :            : struct mp_reply_bundle {
      20                 :            :         struct rte_mp_msg msg;
      21                 :            :         void *peer;
      22                 :            : };
      23                 :            : 
      24                 :          0 : static int cmp_dev_name(const struct rte_device *dev, const void *_name)
      25                 :            : {
      26                 :            :         const char *name = _name;
      27                 :            : 
      28                 :          0 :         return strcmp(dev->name, name);
      29                 :            : }
      30                 :            : 
      31                 :            : /**
      32                 :            :  * Secondary to primary request.
      33                 :            :  * start from function eal_dev_hotplug_request_to_primary.
      34                 :            :  *
      35                 :            :  * device attach on secondary:
      36                 :            :  * a) secondary send sync request to the primary.
      37                 :            :  * b) primary receive the request and attach the new device if
      38                 :            :  *    failed goto i).
      39                 :            :  * c) primary forward attach sync request to all secondary.
      40                 :            :  * d) secondary receive the request and attach the device and send a reply.
      41                 :            :  * e) primary check the reply if all success goes to j).
      42                 :            :  * f) primary send attach rollback sync request to all secondary.
      43                 :            :  * g) secondary receive the request and detach the device and send a reply.
      44                 :            :  * h) primary receive the reply and detach device as rollback action.
      45                 :            :  * i) send attach fail to secondary as a reply of step a), goto k).
      46                 :            :  * j) send attach success to secondary as a reply of step a).
      47                 :            :  * k) secondary receive reply and return.
      48                 :            :  *
      49                 :            :  * device detach on secondary:
      50                 :            :  * a) secondary send sync request to the primary.
      51                 :            :  * b) primary send detach sync request to all secondary.
      52                 :            :  * c) secondary detach the device and send a reply.
      53                 :            :  * d) primary check the reply if all success goes to g).
      54                 :            :  * e) primary send detach rollback sync request to all secondary.
      55                 :            :  * f) secondary receive the request and attach back device. goto h).
      56                 :            :  * g) primary detach the device if success goto i), else goto e).
      57                 :            :  * h) primary send detach fail to secondary as a reply of step a), goto j).
      58                 :            :  * i) primary send detach success to secondary as a reply of step a).
      59                 :            :  * j) secondary receive reply and return.
      60                 :            :  */
      61                 :            : 
      62                 :            : static int
      63                 :          0 : send_response_to_secondary(const struct eal_dev_mp_req *req,
      64                 :            :                         int result,
      65                 :            :                         const void *peer)
      66                 :            : {
      67                 :            :         struct rte_mp_msg mp_resp;
      68                 :            :         struct eal_dev_mp_req *resp =
      69                 :            :                 (struct eal_dev_mp_req *)mp_resp.param;
      70                 :            :         int ret;
      71                 :            : 
      72                 :            :         memset(&mp_resp, 0, sizeof(mp_resp));
      73                 :          0 :         mp_resp.len_param = sizeof(*resp);
      74                 :            :         strlcpy(mp_resp.name, EAL_DEV_MP_ACTION_REQUEST, sizeof(mp_resp.name));
      75                 :            :         memcpy(resp, req, sizeof(*req));
      76                 :          0 :         resp->result = result;
      77                 :            : 
      78                 :          0 :         ret = rte_mp_reply(&mp_resp, peer);
      79         [ #  # ]:          0 :         if (ret != 0)
      80                 :          0 :                 EAL_LOG(ERR, "failed to send response to secondary");
      81                 :            : 
      82                 :          0 :         return ret;
      83                 :            : }
      84                 :            : 
      85                 :            : static void
      86                 :          0 : __handle_secondary_request(void *param)
      87                 :            : {
      88                 :            :         struct mp_reply_bundle *bundle = param;
      89                 :            :                 const struct rte_mp_msg *msg = &bundle->msg;
      90                 :            :         const struct eal_dev_mp_req *req =
      91                 :            :                 (const struct eal_dev_mp_req *)msg->param;
      92                 :            :         struct eal_dev_mp_req tmp_req;
      93                 :            :         struct rte_devargs da;
      94                 :            :         struct rte_device *dev;
      95                 :            :         struct rte_bus *bus;
      96                 :            :         int ret = 0;
      97                 :            : 
      98         [ #  # ]:          0 :         tmp_req = *req;
      99                 :            : 
     100                 :            :         memset(&da, 0, sizeof(da));
     101         [ #  # ]:          0 :         if (req->t == EAL_DEV_REQ_TYPE_ATTACH) {
     102                 :          0 :                 ret = local_dev_probe(req->devargs, &dev);
     103         [ #  # ]:          0 :                 if (ret != 0 && ret != -EEXIST) {
     104                 :          0 :                         EAL_LOG(ERR, "Failed to hotplug add device on primary");
     105                 :          0 :                         goto finish;
     106                 :            :                 }
     107                 :          0 :                 ret = eal_dev_hotplug_request_to_secondary(&tmp_req);
     108         [ #  # ]:          0 :                 if (ret != 0) {
     109                 :          0 :                         EAL_LOG(ERR, "Failed to send hotplug request to secondary");
     110                 :            :                         ret = -ENOMSG;
     111                 :          0 :                         goto rollback;
     112                 :            :                 }
     113         [ #  # ]:          0 :                 if (tmp_req.result != 0) {
     114                 :            :                         ret = tmp_req.result;
     115                 :          0 :                         EAL_LOG(ERR, "Failed to hotplug add device on secondary");
     116         [ #  # ]:          0 :                         if (ret != -EEXIST)
     117                 :          0 :                                 goto rollback;
     118                 :            :                 }
     119         [ #  # ]:          0 :         } else if (req->t == EAL_DEV_REQ_TYPE_DETACH) {
     120                 :          0 :                 ret = rte_devargs_parse(&da, req->devargs);
     121         [ #  # ]:          0 :                 if (ret != 0)
     122                 :          0 :                         goto finish;
     123                 :            : 
     124                 :          0 :                 ret = eal_dev_hotplug_request_to_secondary(&tmp_req);
     125         [ #  # ]:          0 :                 if (ret != 0) {
     126                 :          0 :                         EAL_LOG(ERR, "Failed to send hotplug request to secondary");
     127                 :            :                         ret = -ENOMSG;
     128                 :          0 :                         goto rollback;
     129                 :            :                 }
     130                 :            : 
     131                 :          0 :                 bus = rte_bus_find_by_name(da.bus->name);
     132         [ #  # ]:          0 :                 if (bus == NULL) {
     133                 :          0 :                         EAL_LOG(ERR, "Cannot find bus (%s)", da.bus->name);
     134                 :            :                         ret = -ENOENT;
     135                 :          0 :                         goto finish;
     136                 :            :                 }
     137                 :            : 
     138                 :          0 :                 dev = bus->find_device(NULL, cmp_dev_name, da.name);
     139         [ #  # ]:          0 :                 if (dev == NULL) {
     140                 :          0 :                         EAL_LOG(ERR, "Cannot find plugged device (%s)", da.name);
     141                 :            :                         ret = -ENOENT;
     142                 :          0 :                         goto finish;
     143                 :            :                 }
     144                 :            : 
     145         [ #  # ]:          0 :                 if (tmp_req.result != 0) {
     146                 :          0 :                         EAL_LOG(ERR, "Failed to hotplug remove device on secondary");
     147                 :          0 :                         ret = tmp_req.result;
     148         [ #  # ]:          0 :                         if (ret != -ENOENT)
     149                 :          0 :                                 goto rollback;
     150                 :            :                 }
     151                 :            : 
     152                 :          0 :                 ret = local_dev_remove(dev);
     153         [ #  # ]:          0 :                 if (ret != 0) {
     154                 :          0 :                         EAL_LOG(ERR, "Failed to hotplug remove device on primary");
     155         [ #  # ]:          0 :                         if (ret != -ENOENT)
     156                 :          0 :                                 goto rollback;
     157                 :            :                 }
     158                 :            :         } else {
     159                 :          0 :                 EAL_LOG(ERR, "unsupported secondary to primary request");
     160                 :            :                 ret = -ENOTSUP;
     161                 :            :         }
     162                 :          0 :         goto finish;
     163                 :            : 
     164                 :          0 : rollback:
     165         [ #  # ]:          0 :         if (req->t == EAL_DEV_REQ_TYPE_ATTACH) {
     166                 :          0 :                 tmp_req.t = EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK;
     167                 :          0 :                 eal_dev_hotplug_request_to_secondary(&tmp_req);
     168                 :          0 :                 local_dev_remove(dev);
     169                 :            :         } else {
     170                 :          0 :                 tmp_req.t = EAL_DEV_REQ_TYPE_DETACH_ROLLBACK;
     171                 :          0 :                 eal_dev_hotplug_request_to_secondary(&tmp_req);
     172                 :            :         }
     173                 :            : 
     174                 :          0 : finish:
     175                 :          0 :         ret = send_response_to_secondary(&tmp_req, ret, bundle->peer);
     176         [ #  # ]:          0 :         if (ret)
     177                 :          0 :                 EAL_LOG(ERR, "failed to send response to secondary");
     178                 :            : 
     179                 :          0 :         rte_devargs_reset(&da);
     180                 :          0 :         free(bundle->peer);
     181                 :          0 :         free(bundle);
     182                 :          0 : }
     183                 :            : 
     184                 :            : static int
     185                 :          0 : handle_secondary_request(const struct rte_mp_msg *msg, const void *peer)
     186                 :            : {
     187                 :            :         struct mp_reply_bundle *bundle;
     188                 :          0 :         const struct eal_dev_mp_req *req =
     189                 :            :                 (const struct eal_dev_mp_req *)msg->param;
     190                 :            :         int ret = 0;
     191                 :            : 
     192                 :          0 :         bundle = malloc(sizeof(*bundle));
     193         [ #  # ]:          0 :         if (bundle == NULL) {
     194                 :          0 :                 EAL_LOG(ERR, "not enough memory");
     195                 :          0 :                 return send_response_to_secondary(req, -ENOMEM, peer);
     196                 :            :         }
     197                 :            : 
     198                 :          0 :         bundle->msg = *msg;
     199                 :            :         /**
     200                 :            :          * We need to send reply on interrupt thread, but peer can't be
     201                 :            :          * parsed directly, so this is a temporal hack, need to be fixed
     202                 :            :          * when it is ready.
     203                 :            :          */
     204                 :          0 :         bundle->peer = strdup(peer);
     205         [ #  # ]:          0 :         if (bundle->peer == NULL) {
     206                 :          0 :                 free(bundle);
     207                 :          0 :                 EAL_LOG(ERR, "not enough memory");
     208                 :          0 :                 return send_response_to_secondary(req, -ENOMEM, peer);
     209                 :            :         }
     210                 :            : 
     211                 :            :         /**
     212                 :            :          * We are at IPC callback thread, sync IPC is not allowed due to
     213                 :            :          * dead lock, so we delegate the task to interrupt thread.
     214                 :            :          */
     215                 :          0 :         ret = rte_eal_alarm_set(1, __handle_secondary_request, bundle);
     216         [ #  # ]:          0 :         if (ret != 0) {
     217                 :          0 :                 EAL_LOG(ERR, "failed to add mp task");
     218                 :          0 :                 free(bundle->peer);
     219                 :          0 :                 free(bundle);
     220                 :          0 :                 return send_response_to_secondary(req, ret, peer);
     221                 :            :         }
     222                 :            :         return 0;
     223                 :            : }
     224                 :            : 
     225                 :          0 : static void __handle_primary_request(void *param)
     226                 :            : {
     227                 :            :         struct mp_reply_bundle *bundle = param;
     228                 :            :         struct rte_mp_msg *msg = &bundle->msg;
     229      [ #  #  # ]:          0 :         const struct eal_dev_mp_req *req =
     230                 :            :                 (const struct eal_dev_mp_req *)msg->param;
     231                 :            :         struct rte_mp_msg mp_resp;
     232                 :            :         struct eal_dev_mp_req *resp =
     233                 :            :                 (struct eal_dev_mp_req *)mp_resp.param;
     234                 :            :         struct rte_devargs *da;
     235                 :            :         struct rte_device *dev;
     236                 :            :         struct rte_bus *bus;
     237                 :            :         int ret = 0;
     238                 :            : 
     239                 :            :         memset(&mp_resp, 0, sizeof(mp_resp));
     240                 :            : 
     241      [ #  #  # ]:          0 :         switch (req->t) {
     242                 :          0 :         case EAL_DEV_REQ_TYPE_ATTACH:
     243                 :            :         case EAL_DEV_REQ_TYPE_DETACH_ROLLBACK:
     244                 :          0 :                 ret = local_dev_probe(req->devargs, &dev);
     245                 :          0 :                 break;
     246                 :          0 :         case EAL_DEV_REQ_TYPE_DETACH:
     247                 :            :         case EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK:
     248                 :          0 :                 da = calloc(1, sizeof(*da));
     249         [ #  # ]:          0 :                 if (da == NULL) {
     250                 :            :                         ret = -ENOMEM;
     251                 :            :                         break;
     252                 :            :                 }
     253                 :            : 
     254                 :          0 :                 ret = rte_devargs_parse(da, req->devargs);
     255         [ #  # ]:          0 :                 if (ret != 0)
     256                 :          0 :                         goto quit;
     257                 :            : 
     258                 :          0 :                 bus = rte_bus_find_by_name(da->bus->name);
     259         [ #  # ]:          0 :                 if (bus == NULL) {
     260                 :          0 :                         EAL_LOG(ERR, "Cannot find bus (%s)", da->bus->name);
     261                 :            :                         ret = -ENOENT;
     262                 :          0 :                         goto quit;
     263                 :            :                 }
     264                 :            : 
     265                 :          0 :                 dev = bus->find_device(NULL, cmp_dev_name, da->name);
     266         [ #  # ]:          0 :                 if (dev == NULL) {
     267                 :          0 :                         EAL_LOG(ERR, "Cannot find plugged device (%s)", da->name);
     268                 :            :                         ret = -ENOENT;
     269                 :          0 :                         goto quit;
     270                 :            :                 }
     271                 :            : 
     272         [ #  # ]:          0 :                 if (!rte_dev_is_probed(dev)) {
     273         [ #  # ]:          0 :                         if (req->t == EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK) {
     274                 :            :                                 /**
     275                 :            :                                  * Don't fail the rollback just because there's
     276                 :            :                                  * nothing to do.
     277                 :            :                                  */
     278                 :            :                                 ret = 0;
     279                 :            :                         } else
     280                 :            :                                 ret = -ENODEV;
     281                 :            : 
     282                 :          0 :                         goto quit;
     283                 :            :                 }
     284                 :            : 
     285                 :          0 :                 ret = local_dev_remove(dev);
     286                 :          0 : quit:
     287                 :          0 :                 rte_devargs_reset(da);
     288                 :          0 :                 free(da);
     289                 :          0 :                 break;
     290                 :            :         default:
     291                 :            :                 ret = -EINVAL;
     292                 :            :         }
     293                 :            : 
     294                 :            :         strlcpy(mp_resp.name, EAL_DEV_MP_ACTION_REQUEST, sizeof(mp_resp.name));
     295                 :          0 :         mp_resp.len_param = sizeof(*req);
     296                 :            :         memcpy(resp, req, sizeof(*resp));
     297                 :          0 :         resp->result = ret;
     298         [ #  # ]:          0 :         if (rte_mp_reply(&mp_resp, bundle->peer) < 0)
     299                 :          0 :                 EAL_LOG(ERR, "failed to send reply to primary request");
     300                 :            : 
     301                 :          0 :         free(bundle->peer);
     302                 :          0 :         free(bundle);
     303                 :          0 : }
     304                 :            : 
     305                 :            : static int
     306                 :          0 : handle_primary_request(const struct rte_mp_msg *msg, const void *peer)
     307                 :            : {
     308                 :            :         struct rte_mp_msg mp_resp;
     309         [ #  # ]:          0 :         const struct eal_dev_mp_req *req =
     310                 :            :                 (const struct eal_dev_mp_req *)msg->param;
     311                 :            :         struct eal_dev_mp_req *resp =
     312                 :            :                 (struct eal_dev_mp_req *)mp_resp.param;
     313                 :            :         struct mp_reply_bundle *bundle;
     314                 :            :         int ret = 0;
     315                 :            : 
     316                 :            :         memset(&mp_resp, 0, sizeof(mp_resp));
     317                 :            :         strlcpy(mp_resp.name, EAL_DEV_MP_ACTION_REQUEST, sizeof(mp_resp.name));
     318         [ #  # ]:          0 :         mp_resp.len_param = sizeof(*req);
     319                 :            :         memcpy(resp, req, sizeof(*resp));
     320                 :            : 
     321                 :          0 :         bundle = calloc(1, sizeof(*bundle));
     322         [ #  # ]:          0 :         if (bundle == NULL) {
     323                 :          0 :                 EAL_LOG(ERR, "not enough memory");
     324                 :          0 :                 resp->result = -ENOMEM;
     325                 :          0 :                 ret = rte_mp_reply(&mp_resp, peer);
     326         [ #  # ]:          0 :                 if (ret)
     327                 :          0 :                         EAL_LOG(ERR, "failed to send reply to primary request");
     328                 :          0 :                 return ret;
     329                 :            :         }
     330                 :            : 
     331                 :          0 :         bundle->msg = *msg;
     332                 :            :         /**
     333                 :            :          * We need to send reply on interrupt thread, but peer can't be
     334                 :            :          * parsed directly, so this is a temporal hack, need to be fixed
     335                 :            :          * when it is ready.
     336                 :            :          */
     337                 :          0 :         bundle->peer = (void *)strdup(peer);
     338         [ #  # ]:          0 :         if (bundle->peer == NULL) {
     339                 :          0 :                 EAL_LOG(ERR, "not enough memory");
     340                 :          0 :                 free(bundle);
     341                 :          0 :                 resp->result = -ENOMEM;
     342                 :          0 :                 ret = rte_mp_reply(&mp_resp, peer);
     343         [ #  # ]:          0 :                 if (ret)
     344                 :          0 :                         EAL_LOG(ERR, "failed to send reply to primary request");
     345                 :          0 :                 return ret;
     346                 :            :         }
     347                 :            : 
     348                 :            :         /**
     349                 :            :          * We are at IPC callback thread, sync IPC is not allowed due to
     350                 :            :          * dead lock, so we delegate the task to interrupt thread.
     351                 :            :          */
     352                 :          0 :         ret = rte_eal_alarm_set(1, __handle_primary_request, bundle);
     353         [ #  # ]:          0 :         if (ret != 0) {
     354                 :          0 :                 free(bundle->peer);
     355                 :          0 :                 free(bundle);
     356                 :          0 :                 resp->result = ret;
     357                 :          0 :                 ret = rte_mp_reply(&mp_resp, peer);
     358         [ #  # ]:          0 :                 if  (ret != 0) {
     359                 :          0 :                         EAL_LOG(ERR, "failed to send reply to primary request");
     360                 :          0 :                         return ret;
     361                 :            :                 }
     362                 :            :         }
     363                 :            :         return 0;
     364                 :            : }
     365                 :            : 
     366                 :          0 : int eal_dev_hotplug_request_to_primary(struct eal_dev_mp_req *req)
     367                 :            : {
     368                 :            :         struct rte_mp_msg mp_req;
     369                 :            :         struct rte_mp_reply mp_reply;
     370                 :          0 :         struct timespec ts = {.tv_sec = MP_TIMEOUT_S, .tv_nsec = 0};
     371                 :            :         struct eal_dev_mp_req *resp;
     372                 :            :         int ret;
     373                 :            : 
     374                 :            :         memset(&mp_req, 0, sizeof(mp_req));
     375                 :            :         memcpy(mp_req.param, req, sizeof(*req));
     376                 :          0 :         mp_req.len_param = sizeof(*req);
     377                 :            :         strlcpy(mp_req.name, EAL_DEV_MP_ACTION_REQUEST, sizeof(mp_req.name));
     378                 :            : 
     379                 :          0 :         ret = rte_mp_request_sync(&mp_req, &mp_reply, &ts);
     380   [ #  #  #  # ]:          0 :         if (ret || mp_reply.nb_received != 1) {
     381                 :          0 :                 EAL_LOG(ERR, "Cannot send request to primary");
     382         [ #  # ]:          0 :                 if (!ret)
     383                 :            :                         return -1;
     384                 :          0 :                 return ret;
     385                 :            :         }
     386                 :            : 
     387                 :          0 :         resp = (struct eal_dev_mp_req *)mp_reply.msgs[0].param;
     388                 :          0 :         req->result = resp->result;
     389                 :            : 
     390                 :          0 :         free(mp_reply.msgs);
     391                 :          0 :         return ret;
     392                 :            : }
     393                 :            : 
     394                 :          0 : int eal_dev_hotplug_request_to_secondary(struct eal_dev_mp_req *req)
     395                 :            : {
     396                 :            :         struct rte_mp_msg mp_req;
     397                 :            :         struct rte_mp_reply mp_reply;
     398                 :          0 :         struct timespec ts = {.tv_sec = MP_TIMEOUT_S, .tv_nsec = 0};
     399                 :            :         int ret;
     400                 :            :         int i;
     401                 :            : 
     402                 :            :         memset(&mp_req, 0, sizeof(mp_req));
     403                 :            :         memcpy(mp_req.param, req, sizeof(*req));
     404                 :          0 :         mp_req.len_param = sizeof(*req);
     405                 :            :         strlcpy(mp_req.name, EAL_DEV_MP_ACTION_REQUEST, sizeof(mp_req.name));
     406                 :            : 
     407                 :          0 :         ret = rte_mp_request_sync(&mp_req, &mp_reply, &ts);
     408         [ #  # ]:          0 :         if (ret != 0) {
     409                 :            :                 /* if IPC is not supported, behave as if the call succeeded */
     410         [ #  # ]:          0 :                 if (rte_errno != ENOTSUP)
     411                 :          0 :                         EAL_LOG(ERR, "rte_mp_request_sync failed");
     412                 :            :                 else
     413                 :            :                         ret = 0;
     414                 :          0 :                 return ret;
     415                 :            :         }
     416                 :            : 
     417         [ #  # ]:          0 :         if (mp_reply.nb_sent != mp_reply.nb_received) {
     418                 :          0 :                 EAL_LOG(ERR, "not all secondary reply");
     419                 :          0 :                 free(mp_reply.msgs);
     420                 :          0 :                 return -1;
     421                 :            :         }
     422                 :            : 
     423                 :          0 :         req->result = 0;
     424         [ #  # ]:          0 :         for (i = 0; i < mp_reply.nb_received; i++) {
     425                 :            :                 struct eal_dev_mp_req *resp =
     426                 :          0 :                         (struct eal_dev_mp_req *)mp_reply.msgs[i].param;
     427         [ #  # ]:          0 :                 if (resp->result != 0) {
     428   [ #  #  #  # ]:          0 :                         if (req->t == EAL_DEV_REQ_TYPE_ATTACH &&
     429                 :            :                                 resp->result == -EEXIST)
     430                 :          0 :                                 continue;
     431   [ #  #  #  # ]:          0 :                         if (req->t == EAL_DEV_REQ_TYPE_DETACH &&
     432                 :            :                                 resp->result == -ENOENT)
     433                 :          0 :                                 continue;
     434                 :          0 :                         req->result = resp->result;
     435                 :            :                 }
     436                 :            :         }
     437                 :            : 
     438                 :          0 :         free(mp_reply.msgs);
     439                 :          0 :         return 0;
     440                 :            : }
     441                 :            : 
     442                 :        179 : int eal_mp_dev_hotplug_init(void)
     443                 :            : {
     444                 :            :         int ret;
     445                 :            : 
     446         [ +  + ]:        179 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
     447                 :        154 :                 ret = rte_mp_action_register(EAL_DEV_MP_ACTION_REQUEST,
     448                 :            :                                         handle_secondary_request);
     449                 :            :                 /* primary is allowed to not support IPC */
     450   [ +  +  -  + ]:        154 :                 if (ret != 0 && rte_errno != ENOTSUP) {
     451                 :          0 :                         EAL_LOG(ERR, "Couldn't register '%s' action",
     452                 :            :                                 EAL_DEV_MP_ACTION_REQUEST);
     453                 :          0 :                         return ret;
     454                 :            :                 }
     455                 :            :         } else {
     456                 :         25 :                 ret = rte_mp_action_register(EAL_DEV_MP_ACTION_REQUEST,
     457                 :            :                                         handle_primary_request);
     458         [ -  + ]:         25 :                 if (ret != 0) {
     459                 :          0 :                         EAL_LOG(ERR, "Couldn't register '%s' action",
     460                 :            :                                 EAL_DEV_MP_ACTION_REQUEST);
     461                 :          0 :                         return ret;
     462                 :            :                 }
     463                 :            :         }
     464                 :            : 
     465                 :            :         return 0;
     466                 :            : }
     467                 :            : 
     468                 :        251 : void eal_mp_dev_hotplug_cleanup(void)
     469                 :            : {
     470                 :        251 :         rte_mp_action_unregister(EAL_DEV_MP_ACTION_REQUEST);
     471                 :        251 : }

Generated by: LCOV version 1.14