@@ -1058,15 +1058,27 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
1058
1058
1059
1059
DEBUG_TRACE (SERVICE_CALLBACK_LINE );
1060
1060
1061
+ rcu_read_lock ();
1061
1062
service = handle_to_service (handle );
1062
- if (WARN_ON (!service ))
1063
+ if (WARN_ON (!service )) {
1064
+ rcu_read_unlock ();
1063
1065
return VCHIQ_SUCCESS ;
1066
+ }
1064
1067
1065
1068
user_service = (struct user_service * )service -> base .userdata ;
1066
1069
instance = user_service -> instance ;
1067
1070
1068
- if (!instance || instance -> closing )
1071
+ if (!instance || instance -> closing ) {
1072
+ rcu_read_unlock ();
1069
1073
return VCHIQ_SUCCESS ;
1074
+ }
1075
+
1076
+ /*
1077
+ * As hopping around different synchronization mechanism,
1078
+ * taking an extra reference results in simpler implementation.
1079
+ */
1080
+ vchiq_service_get (service );
1081
+ rcu_read_unlock ();
1070
1082
1071
1083
vchiq_log_trace (vchiq_arm_log_level ,
1072
1084
"%s - service %lx(%d,%p), reason %d, header %lx, instance %lx, bulk_userdata %lx" ,
@@ -1097,6 +1109,7 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
1097
1109
bulk_userdata );
1098
1110
if (status != VCHIQ_SUCCESS ) {
1099
1111
DEBUG_TRACE (SERVICE_CALLBACK_LINE );
1112
+ vchiq_service_put (service );
1100
1113
return status ;
1101
1114
}
1102
1115
}
@@ -1105,10 +1118,12 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
1105
1118
if (wait_for_completion_interruptible (& user_service -> remove_event )) {
1106
1119
vchiq_log_info (vchiq_arm_log_level , "%s interrupted" , __func__ );
1107
1120
DEBUG_TRACE (SERVICE_CALLBACK_LINE );
1121
+ vchiq_service_put (service );
1108
1122
return VCHIQ_RETRY ;
1109
1123
} else if (instance -> closing ) {
1110
1124
vchiq_log_info (vchiq_arm_log_level , "%s closing" , __func__ );
1111
1125
DEBUG_TRACE (SERVICE_CALLBACK_LINE );
1126
+ vchiq_service_put (service );
1112
1127
return VCHIQ_ERROR ;
1113
1128
}
1114
1129
DEBUG_TRACE (SERVICE_CALLBACK_LINE );
@@ -1137,6 +1152,7 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
1137
1152
header = NULL ;
1138
1153
}
1139
1154
DEBUG_TRACE (SERVICE_CALLBACK_LINE );
1155
+ vchiq_service_put (service );
1140
1156
1141
1157
if (skip_completion )
1142
1158
return VCHIQ_SUCCESS ;
0 commit comments