@@ -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,96 @@ 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+ link -> role == ENDPOINT_ROLE_ENDPOINT &&
4259+ link -> discovered != DISCOVERY_DISCOVERED ;
4260+ }
4261+
4262+ static void link_attempt_discovery_notify (struct link * link )
4263+ {
4264+ struct mctp_ctrl_resp_discovery_notify * resp = NULL ;
4265+ struct mctp_ctrl_cmd_discovery_notify req = { 0 };
4266+ struct mctp_ctrl_cmd cmd = { 0 };
4267+ struct ctx * ctx = link -> ctx ;
4268+ unsigned int retry ;
4269+ uint8_t iid ;
4270+ int rc ;
4271+
4272+ if (!link_supports_discovery_notify (link ))
4273+ return ;
4274+
4275+ for (retry = 0 ; retry < 4 ; retry ++ ) {
4276+ iid = mctp_next_iid (ctx );
4277+ mctp_ctrl_msg_hdr_init_req (& req .ctrl_hdr , iid ,
4278+ MCTP_CTRL_CMD_DISCOVERY_NOTIFY );
4279+ mctp_ctrl_cmd_init_from_req_type (& cmd , req );
4280+
4281+ rc = endpoint_query_phys (ctx , & link -> bus_owner , & cmd );
4282+ if (rc < 0 ) {
4283+ mctp_ctrl_cmd_free (& cmd );
4284+ break ;
4285+ }
4286+
4287+ rc = mctp_ctrl_validate_response (
4288+ & cmd , sizeof (* resp ), dest_phys_tostr (& link -> bus_owner ),
4289+ iid , MCTP_CTRL_CMD_DISCOVERY_NOTIFY );
4290+ mctp_ctrl_cmd_free (& cmd );
4291+ if (rc == 0 )
4292+ return ;
4293+ /* retry on non-fatal completion code errors */
4294+ if (rc != - EBUSY )
4295+ break ;
4296+ }
4297+
4298+ if (rc < 0 )
4299+ warnx ("Discovery Notify on %s failed: %s" , link -> path ,
4300+ strerror (- rc ));
4301+ }
4302+
4303+ static int method_set_bus_owner (sd_bus_message * call , void * data ,
4304+ sd_bus_error * berr )
4305+ {
4306+ struct link * link = data ;
4307+ struct ctx * ctx = link -> ctx ;
4308+ dest_phys dest = { 0 };
4309+ int rc ;
4310+
4311+ dest .ifindex = link -> ifindex ;
4312+ if (dest .ifindex <= 0 )
4313+ return sd_bus_error_setf (berr , SD_BUS_ERROR_INVALID_ARGS ,
4314+ "Unknown MCTP interface" );
4315+
4316+ rc = message_read_hwaddr (call , & dest );
4317+ if (rc < 0 ) {
4318+ set_berr (ctx , rc , berr );
4319+ return rc ;
4320+ }
4321+
4322+ rc = validate_dest_phys (ctx , & dest );
4323+ if (rc < 0 )
4324+ return sd_bus_error_setf (berr , SD_BUS_ERROR_INVALID_ARGS ,
4325+ "Bad physaddr" );
4326+
4327+ link -> bus_owner = dest ;
4328+ link_attempt_discovery_notify (link );
4329+ return sd_bus_reply_method_return (call , "" );
4330+ }
4331+
4332+ // clang-format off
4333+ static const sd_bus_vtable bus_link_endpoint_vtable [] = {
4334+ SD_BUS_VTABLE_START (0 ),
4335+ SD_BUS_METHOD_WITH_ARGS ("SetBusOwner" ,
4336+ SD_BUS_ARGS ("ay" , physaddr ),
4337+ SD_BUS_NO_RESULT ,
4338+ method_set_bus_owner ,
4339+ 0 ),
4340+ SD_BUS_VTABLE_END ,
4341+ };
4342+ // clang-format on
4343+
42494344// clang-format off
42504345static const sd_bus_vtable bus_link_owner_vtable [] = {
42514346 SD_BUS_VTABLE_START (0 ),
@@ -4458,14 +4553,22 @@ static int link_set_role(sd_event_source *ev, void *userdata)
44584553 sd_event_source_unref (link -> role_defer );
44594554 link -> role_defer = NULL ;
44604555
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 );
4556+ if (link -> role == ENDPOINT_ROLE_BUS_OWNER ) {
4557+ rc = sd_bus_add_object_vtable (link -> ctx -> bus ,
4558+ & link -> slot_busowner , link -> path ,
4559+ CC_MCTP_DBUS_IFACE_BUSOWNER ,
4560+ bus_link_owner_vtable , link );
4561+ if (rc )
4562+ warnx ("adding link owner vtable failed: %d" , rc );
4563+ } else if (link -> role == ENDPOINT_ROLE_ENDPOINT ) {
4564+ rc = sd_bus_add_object_vtable (link -> ctx -> bus ,
4565+ & link -> slot_endpoint , link -> path ,
4566+ CC_MCTP_DBUS_IFACE_ENDPOINT ,
4567+ bus_link_endpoint_vtable , link );
4568+ if (rc )
4569+ warnx ("adding link endpoint vtable failed: %d" , rc );
4570+ link_attempt_discovery_notify (link );
4571+ }
44694572
44704573 return 0 ;
44714574}
@@ -4956,6 +5059,7 @@ static void free_link(struct link *link)
49565059 sd_event_source_disable_unref (link -> role_defer );
49575060 sd_bus_slot_unref (link -> slot_iface );
49585061 sd_bus_slot_unref (link -> slot_busowner );
5062+ sd_bus_slot_unref (link -> slot_endpoint );
49595063 free (link -> path );
49605064 free (link -> sysfs_path );
49615065 free (link );
@@ -5025,6 +5129,8 @@ static int rename_interface(struct ctx *ctx, struct link *link, int ifindex)
50255129 link -> slot_iface = NULL ;
50265130 sd_bus_slot_unref (link -> slot_busowner );
50275131 link -> slot_busowner = NULL ;
5132+ sd_bus_slot_unref (link -> slot_endpoint );
5133+ link -> slot_endpoint = NULL ;
50285134 free (link -> path );
50295135
50305136 /* set new path and re-add */
@@ -5038,6 +5144,11 @@ static int rename_interface(struct ctx *ctx, struct link *link, int ifindex)
50385144 link -> path ,
50395145 CC_MCTP_DBUS_IFACE_BUSOWNER ,
50405146 bus_link_owner_vtable , link );
5147+ } else if (link -> role == ENDPOINT_ROLE_ENDPOINT ) {
5148+ sd_bus_add_object_vtable (link -> ctx -> bus , & link -> slot_endpoint ,
5149+ link -> path ,
5150+ CC_MCTP_DBUS_IFACE_ENDPOINT ,
5151+ bus_link_endpoint_vtable , link );
50415152 }
50425153
50435154 emit_interface_added (link );
@@ -5411,6 +5522,11 @@ static int add_interface(struct ctx *ctx, int ifindex)
54115522 link -> path ,
54125523 CC_MCTP_DBUS_IFACE_BUSOWNER ,
54135524 bus_link_owner_vtable , link );
5525+ } else if (link -> role == ENDPOINT_ROLE_ENDPOINT ) {
5526+ sd_bus_add_object_vtable (link -> ctx -> bus , & link -> slot_endpoint ,
5527+ link -> path ,
5528+ CC_MCTP_DBUS_IFACE_ENDPOINT ,
5529+ bus_link_endpoint_vtable , link );
54145530 }
54155531
54165532 if (link -> phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ) {
@@ -5423,6 +5539,8 @@ static int add_interface(struct ctx *ctx, int ifindex)
54235539 link -> published = false;
54245540 }
54255541
5542+ link_attempt_discovery_notify (link );
5543+
54265544 return rc ;
54275545
54285546err_free :
0 commit comments