@@ -147,8 +147,12 @@ struct link {
147147 char * path ;
148148 sd_bus_slot * slot_iface ;
149149 sd_bus_slot * slot_busowner ;
150+ sd_bus_slot * slot_endpoint ;
150151 sd_event_source * role_defer ;
151152
153+ /* Physical address of the bus owner, set via SetBusOwner. */
154+ dest_phys bus_owner ;
155+
152156 struct ctx * ctx ;
153157};
154158
@@ -385,6 +389,7 @@ static const sd_bus_vtable bus_endpoint_obmc_vtable[];
385389static const sd_bus_vtable bus_endpoint_cc_vtable [];
386390static const sd_bus_vtable bus_endpoint_bridge [];
387391static const sd_bus_vtable bus_endpoint_uuid_vtable [];
392+ static const sd_bus_vtable bus_link_endpoint_vtable [];
388393
389394__attribute__((format (printf , 1 , 2 ))) static void bug_warn (const char * fmt , ...)
390395{
@@ -4246,6 +4251,98 @@ static int method_register_vdm_type_support(sd_bus_message *call, void *data,
42464251 return rc ;
42474252}
42484253
4254+ static bool link_supports_discovery_notify (const struct link * link )
4255+ {
4256+ return link -> phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ||
4257+ link -> phys_binding == MCTP_PHYS_BINDING_I3C ;
4258+ }
4259+
4260+ static void link_attempt_discovery_notify (struct link * link )
4261+ {
4262+ struct mctp_ctrl_resp_discovery_notify * resp = NULL ;
4263+ struct mctp_ctrl_cmd_discovery_notify req = { 0 };
4264+ struct mctp_ctrl_cmd cmd = { 0 };
4265+ struct ctx * ctx = link -> ctx ;
4266+ unsigned int retry ;
4267+ uint8_t iid ;
4268+ int rc ;
4269+
4270+ if (!link_supports_discovery_notify (link ))
4271+ return ;
4272+ if (link -> role != ENDPOINT_ROLE_ENDPOINT )
4273+ return ;
4274+ if (link -> discovered == DISCOVERY_DISCOVERED )
4275+ return ;
4276+
4277+ for (retry = 0 ; retry < 4 ; retry ++ ) {
4278+ iid = mctp_next_iid (ctx );
4279+ mctp_ctrl_msg_hdr_init_req (& req .ctrl_hdr , iid ,
4280+ MCTP_CTRL_CMD_DISCOVERY_NOTIFY );
4281+ mctp_ctrl_cmd_init_from_req_type (& cmd , req );
4282+
4283+ rc = endpoint_query_phys (ctx , & link -> bus_owner , & cmd );
4284+ if (rc < 0 ) {
4285+ mctp_ctrl_cmd_free (& cmd );
4286+ break ;
4287+ }
4288+
4289+ rc = mctp_ctrl_validate_response (
4290+ & cmd , sizeof (* resp ), dest_phys_tostr (& link -> bus_owner ),
4291+ iid , MCTP_CTRL_CMD_DISCOVERY_NOTIFY );
4292+ mctp_ctrl_cmd_free (& cmd );
4293+ if (rc == 0 )
4294+ return ;
4295+ /* retry on non-fatal completion code errors */
4296+ if (rc != - EBUSY )
4297+ break ;
4298+ }
4299+
4300+ if (rc < 0 )
4301+ warnx ("Discovery Notify on %s failed: %s" , link -> path ,
4302+ strerror (- rc ));
4303+ }
4304+
4305+ static int method_set_bus_owner (sd_bus_message * call , void * data ,
4306+ sd_bus_error * berr )
4307+ {
4308+ struct link * link = data ;
4309+ struct ctx * ctx = link -> ctx ;
4310+ dest_phys dest = { 0 };
4311+ int rc ;
4312+
4313+ dest .ifindex = link -> ifindex ;
4314+ if (dest .ifindex <= 0 )
4315+ return sd_bus_error_setf (berr , SD_BUS_ERROR_INVALID_ARGS ,
4316+ "Unknown MCTP interface" );
4317+
4318+ rc = message_read_hwaddr (call , & dest );
4319+ if (rc < 0 ) {
4320+ set_berr (ctx , rc , berr );
4321+ return rc ;
4322+ }
4323+
4324+ rc = validate_dest_phys (ctx , & dest );
4325+ if (rc < 0 )
4326+ return sd_bus_error_setf (berr , SD_BUS_ERROR_INVALID_ARGS ,
4327+ "Bad physaddr" );
4328+
4329+ link -> bus_owner = dest ;
4330+ link_attempt_discovery_notify (link );
4331+ return sd_bus_reply_method_return (call , "" );
4332+ }
4333+
4334+ // clang-format off
4335+ static const sd_bus_vtable bus_link_endpoint_vtable [] = {
4336+ SD_BUS_VTABLE_START (0 ),
4337+ SD_BUS_METHOD_WITH_ARGS ("SetBusOwner" ,
4338+ SD_BUS_ARGS ("ay" , physaddr ),
4339+ SD_BUS_NO_RESULT ,
4340+ method_set_bus_owner ,
4341+ 0 ),
4342+ SD_BUS_VTABLE_END ,
4343+ };
4344+ // clang-format on
4345+
42494346// clang-format off
42504347static const sd_bus_vtable bus_link_owner_vtable [] = {
42514348 SD_BUS_VTABLE_START (0 ),
@@ -4458,14 +4555,22 @@ static int link_set_role(sd_event_source *ev, void *userdata)
44584555 sd_event_source_unref (link -> role_defer );
44594556 link -> role_defer = NULL ;
44604557
4461- if (link -> role != ENDPOINT_ROLE_BUS_OWNER )
4462- return 0 ;
4463-
4464- rc = sd_bus_add_object_vtable (link -> ctx -> bus , & link -> slot_busowner ,
4465- link -> path , CC_MCTP_DBUS_IFACE_BUSOWNER ,
4466- bus_link_owner_vtable , link );
4467- if (rc )
4468- warnx ("adding link owner vtable failed: %d" , rc );
4558+ if (link -> role == ENDPOINT_ROLE_BUS_OWNER ) {
4559+ rc = sd_bus_add_object_vtable (link -> ctx -> bus ,
4560+ & link -> slot_busowner , link -> path ,
4561+ CC_MCTP_DBUS_IFACE_BUSOWNER ,
4562+ bus_link_owner_vtable , link );
4563+ if (rc )
4564+ warnx ("adding link owner vtable failed: %d" , rc );
4565+ } else if (link -> role == ENDPOINT_ROLE_ENDPOINT ) {
4566+ rc = sd_bus_add_object_vtable (link -> ctx -> bus ,
4567+ & link -> slot_endpoint , link -> path ,
4568+ CC_MCTP_DBUS_IFACE_ENDPOINT ,
4569+ bus_link_endpoint_vtable , link );
4570+ if (rc )
4571+ warnx ("adding link endpoint vtable failed: %d" , rc );
4572+ link_attempt_discovery_notify (link );
4573+ }
44694574
44704575 return 0 ;
44714576}
@@ -4956,6 +5061,7 @@ static void free_link(struct link *link)
49565061 sd_event_source_disable_unref (link -> role_defer );
49575062 sd_bus_slot_unref (link -> slot_iface );
49585063 sd_bus_slot_unref (link -> slot_busowner );
5064+ sd_bus_slot_unref (link -> slot_endpoint );
49595065 free (link -> path );
49605066 free (link -> sysfs_path );
49615067 free (link );
@@ -5025,6 +5131,8 @@ static int rename_interface(struct ctx *ctx, struct link *link, int ifindex)
50255131 link -> slot_iface = NULL ;
50265132 sd_bus_slot_unref (link -> slot_busowner );
50275133 link -> slot_busowner = NULL ;
5134+ sd_bus_slot_unref (link -> slot_endpoint );
5135+ link -> slot_endpoint = NULL ;
50285136 free (link -> path );
50295137
50305138 /* set new path and re-add */
@@ -5038,6 +5146,11 @@ static int rename_interface(struct ctx *ctx, struct link *link, int ifindex)
50385146 link -> path ,
50395147 CC_MCTP_DBUS_IFACE_BUSOWNER ,
50405148 bus_link_owner_vtable , link );
5149+ } else if (link -> role == ENDPOINT_ROLE_ENDPOINT ) {
5150+ sd_bus_add_object_vtable (link -> ctx -> bus , & link -> slot_endpoint ,
5151+ link -> path ,
5152+ CC_MCTP_DBUS_IFACE_ENDPOINT ,
5153+ bus_link_endpoint_vtable , link );
50415154 }
50425155
50435156 emit_interface_added (link );
@@ -5411,6 +5524,11 @@ static int add_interface(struct ctx *ctx, int ifindex)
54115524 link -> path ,
54125525 CC_MCTP_DBUS_IFACE_BUSOWNER ,
54135526 bus_link_owner_vtable , link );
5527+ } else if (link -> role == ENDPOINT_ROLE_ENDPOINT ) {
5528+ sd_bus_add_object_vtable (link -> ctx -> bus , & link -> slot_endpoint ,
5529+ link -> path ,
5530+ CC_MCTP_DBUS_IFACE_ENDPOINT ,
5531+ bus_link_endpoint_vtable , link );
54145532 }
54155533
54165534 if (link -> phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ) {
@@ -5423,6 +5541,8 @@ static int add_interface(struct ctx *ctx, int ifindex)
54235541 link -> published = false;
54245542 }
54255543
5544+ link_attempt_discovery_notify (link );
5545+
54265546 return rc ;
54275547
54285548err_free :
0 commit comments