@@ -126,7 +126,6 @@ enum discovery_state {
126
126
};
127
127
128
128
struct link {
129
- enum discovery_state discovered ;
130
129
bool published ;
131
130
int ifindex ;
132
131
enum endpoint_role role ;
@@ -135,6 +134,14 @@ struct link {
135
134
sd_bus_slot * slot_iface ;
136
135
sd_bus_slot * slot_busowner ;
137
136
137
+ struct {
138
+ enum discovery_state flag ;
139
+ sd_event_source * notify_source ;
140
+ dest_phys notify_dest ;
141
+ uint64_t notify_retry_delay ;
142
+ uint8_t notify_retries_left ;
143
+ } discovery ;
144
+
138
145
struct ctx * ctx ;
139
146
};
140
147
@@ -793,8 +800,8 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
793
800
warnx ("ERR: cannot add bus owner to object lists" );
794
801
}
795
802
796
- if (link_data -> discovered != DISCOVERY_UNSUPPORTED ) {
797
- link_data -> discovered = DISCOVERY_DISCOVERED ;
803
+ if (link_data -> discovery . flag != DISCOVERY_UNSUPPORTED ) {
804
+ link_data -> discovery . flag = DISCOVERY_DISCOVERED ;
798
805
}
799
806
resp -> status =
800
807
SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_ACCEPTED ) |
@@ -805,13 +812,13 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
805
812
return reply_message (ctx , sd , resp , resp_len , addr );
806
813
807
814
case MCTP_SET_EID_DISCOVERED :
808
- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
815
+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
809
816
resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
810
817
resp_len = sizeof (struct mctp_ctrl_resp );
811
818
return reply_message (ctx , sd , resp , resp_len , addr );
812
819
}
813
820
814
- link_data -> discovered = DISCOVERY_DISCOVERED ;
821
+ link_data -> discovery . flag = DISCOVERY_DISCOVERED ;
815
822
resp -> status =
816
823
SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_REJECTED ) |
817
824
SET_MCTP_EID_ALLOCATION_STATUS (MCTP_SET_EID_POOL_NONE );
@@ -1009,16 +1016,16 @@ static int handle_control_prepare_endpoint_discovery(
1009
1016
resp = (void * )resp ;
1010
1017
mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , * req );
1011
1018
1012
- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1019
+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
1013
1020
warnx ("received prepare for discovery request to unsupported interface %d" ,
1014
1021
addr -> smctp_ifindex );
1015
1022
resp -> completion_code = MCTP_CTRL_CC_ERROR_UNSUPPORTED_CMD ;
1016
1023
return reply_message_phys (ctx , sd , resp ,
1017
1024
sizeof (struct mctp_ctrl_resp ), addr );
1018
1025
}
1019
1026
1020
- if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1021
- link_data -> discovered = DISCOVERY_UNDISCOVERED ;
1027
+ if (link_data -> discovery . flag == DISCOVERY_DISCOVERED ) {
1028
+ link_data -> discovery . flag = DISCOVERY_UNDISCOVERED ;
1022
1029
warnx ("clear discovered flag of interface %d" ,
1023
1030
addr -> smctp_ifindex );
1024
1031
}
@@ -1053,13 +1060,13 @@ handle_control_endpoint_discovery(struct ctx *ctx, int sd,
1053
1060
return 0 ;
1054
1061
}
1055
1062
1056
- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1063
+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
1057
1064
resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
1058
1065
return reply_message (ctx , sd , resp ,
1059
1066
sizeof (struct mctp_ctrl_resp ), addr );
1060
1067
}
1061
1068
1062
- if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1069
+ if (link_data -> discovery . flag == DISCOVERY_DISCOVERED ) {
1063
1070
// if we are already discovered (i.e, assigned an EID), then no reply
1064
1071
return 0 ;
1065
1072
}
@@ -3460,6 +3467,81 @@ static int bus_link_get_prop(sd_bus *bus, const char *path,
3460
3467
return rc ;
3461
3468
}
3462
3469
3470
+ static int query_discovery_notify (struct link * link )
3471
+ {
3472
+ struct mctp_ctrl_cmd_discovery_notify req = { 0 };
3473
+ struct mctp_ctrl_resp_discovery_notify * resp ;
3474
+ struct sockaddr_mctp_ext resp_addr ;
3475
+ size_t buf_size ;
3476
+ uint8_t * buf ;
3477
+ int rc ;
3478
+
3479
+ mctp_ctrl_msg_hdr_init_req (& req .ctrl_hdr , mctp_next_iid (link -> ctx ),
3480
+ MCTP_CTRL_CMD_DISCOVERY_NOTIFY );
3481
+
3482
+ rc = endpoint_query_phys (link -> ctx , & link -> discovery .notify_dest ,
3483
+ MCTP_CTRL_HDR_MSG_TYPE , & req , sizeof (req ),
3484
+ & buf , & buf_size , & resp_addr );
3485
+ if (rc < 0 )
3486
+ goto free_buf ;
3487
+
3488
+ if (buf_size != sizeof (* resp )) {
3489
+ warnx ("%s: wrong reply length %zu bytes. dest %s" , __func__ ,
3490
+ buf_size , dest_phys_tostr (& link -> discovery .notify_dest ));
3491
+ rc = - ENOMSG ;
3492
+ goto free_buf ;
3493
+ }
3494
+
3495
+ resp = (void * )buf ;
3496
+ if (resp -> completion_code != 0 ) {
3497
+ warnx ("Failure completion code 0x%02x from %s" ,
3498
+ resp -> completion_code ,
3499
+ dest_phys_tostr (& link -> discovery .notify_dest ));
3500
+ rc = - ECONNREFUSED ;
3501
+ goto free_buf ;
3502
+ }
3503
+
3504
+ free_buf :
3505
+ free (buf );
3506
+ return rc ;
3507
+ }
3508
+
3509
+ static int link_discovery_notify_callback (sd_event_source * source ,
3510
+ uint64_t time , void * userdata )
3511
+ {
3512
+ struct link * link = userdata ;
3513
+ struct ctx * ctx = link -> ctx ;
3514
+ int rc ;
3515
+
3516
+ // sanity check
3517
+ assert (link -> discovery .notify_source == source );
3518
+
3519
+ // Discovery notify succeeded
3520
+ if (link -> discovery .flag == DISCOVERY_DISCOVERED ) {
3521
+ sd_event_source_disable_unref (source );
3522
+ link -> discovery .notify_source = NULL ;
3523
+ return 0 ;
3524
+ }
3525
+
3526
+ rc = query_discovery_notify (link );
3527
+ if (rc < 0 ) {
3528
+ if (ctx -> verbose ) {
3529
+ warnx ("failed to send discovery notify at retry %d: %s" ,
3530
+ link -> discovery .notify_retries_left ,
3531
+ strerror (- rc ));
3532
+ }
3533
+ }
3534
+ link -> discovery .notify_retries_left -= 1 ;
3535
+ if (link -> discovery .notify_retries_left == 0 ) {
3536
+ warnx ("failed to send discovery notify after all retries" );
3537
+ sd_event_source_disable_unref (source );
3538
+ } else {
3539
+ sd_event_source_set_time_relative (
3540
+ source , link -> discovery .notify_retry_delay );
3541
+ }
3542
+ return 0 ;
3543
+ }
3544
+
3463
3545
static int bus_link_set_prop (sd_bus * bus , const char * path ,
3464
3546
const char * interface , const char * property ,
3465
3547
sd_bus_message * value , void * userdata ,
@@ -4279,7 +4361,7 @@ static int add_interface(struct ctx *ctx, int ifindex)
4279
4361
if (!link )
4280
4362
return - ENOMEM ;
4281
4363
4282
- link -> discovered = DISCOVERY_UNSUPPORTED ;
4364
+ link -> discovery . flag = DISCOVERY_UNSUPPORTED ;
4283
4365
link -> published = false;
4284
4366
link -> ifindex = ifindex ;
4285
4367
link -> ctx = ctx ;
@@ -4309,7 +4391,29 @@ static int add_interface(struct ctx *ctx, int ifindex)
4309
4391
}
4310
4392
4311
4393
if (phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ) {
4312
- link -> discovered = DISCOVERY_UNDISCOVERED ;
4394
+ link -> discovery .flag = DISCOVERY_UNDISCOVERED ;
4395
+ // TODO: These numbers are respectively MN1 and MT4, specified in DSP0239
4396
+ // control message timing.
4397
+ //
4398
+ // Might need to extract these to macros like MCTP_I2C_TSYM_* in this file,
4399
+ // or a commit to actually centralize those timing at one place, now that
4400
+ // we have support for detecting link binding type.
4401
+ link -> discovery .notify_retries_left = 2 ;
4402
+ link -> discovery .notify_retry_delay = 5000000 ;
4403
+
4404
+ // For PCIe-VDM, we want an all zeroes address for Route-to-Root-Complex.
4405
+ mctp_nl_hwaddr_len_byindex (
4406
+ ctx -> nl , ifindex ,
4407
+ & link -> discovery .notify_dest .hwaddr_len );
4408
+ memset (link -> discovery .notify_dest .hwaddr , 0 ,
4409
+ link -> discovery .notify_dest .hwaddr_len );
4410
+ link -> discovery .notify_dest .ifindex = ifindex ;
4411
+
4412
+ sd_event_add_time_relative (ctx -> event ,
4413
+ & link -> discovery .notify_source ,
4414
+ CLOCK_MONOTONIC , 0 , 0 ,
4415
+ link_discovery_notify_callback ,
4416
+ link );
4313
4417
}
4314
4418
4315
4419
link -> published = true;
0 commit comments