@@ -274,7 +274,8 @@ struct bmc_device {
274
274
unsigned long dyn_id_expiry ;
275
275
struct mutex dyn_mutex ; /* protects id & dyn* fields */
276
276
u8 guid [16 ];
277
- int guid_set ;
277
+ u8 fetch_guid [16 ];
278
+ int dyn_guid_set ;
278
279
struct kref usecount ;
279
280
};
280
281
#define to_bmc_device (x ) container_of((x), struct bmc_device, pdev.dev)
@@ -538,6 +539,8 @@ struct ipmi_smi {
538
539
};
539
540
#define to_si_intf_from_dev (device ) container_of(device, struct ipmi_smi, dev)
540
541
542
+ static void __get_guid (ipmi_smi_t intf );
543
+
541
544
/**
542
545
* The driver model view of the IPMI messaging driver.
543
546
*/
@@ -2198,7 +2201,7 @@ static int bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc,
2198
2201
bool * guid_set , u8 * guid )
2199
2202
{
2200
2203
int rv = 0 ;
2201
- int prev_dyn_id_set ;
2204
+ int prev_dyn_id_set , prev_guid_set ;
2202
2205
2203
2206
if (!intf ) {
2204
2207
mutex_lock (& bmc -> dyn_mutex );
@@ -2230,8 +2233,19 @@ static int bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc,
2230
2233
if (bmc -> dyn_id_set && time_is_after_jiffies (bmc -> dyn_id_expiry ))
2231
2234
goto out ;
2232
2235
2233
- prev_dyn_id_set = bmc -> dyn_id_set ;
2236
+ prev_guid_set = bmc -> dyn_guid_set ;
2237
+ __get_guid (intf );
2238
+
2239
+ if (bmc -> dyn_guid_set )
2240
+ memcpy (bmc -> guid , bmc -> fetch_guid , 16 );
2241
+ else if (prev_guid_set )
2242
+ /*
2243
+ * The guid used to be valid and it failed to fetch,
2244
+ * just use the cached value.
2245
+ */
2246
+ bmc -> dyn_guid_set = prev_guid_set ;
2234
2247
2248
+ prev_dyn_id_set = bmc -> dyn_id_set ;
2235
2249
rv = __get_device_id (intf , bmc );
2236
2250
if (rv )
2237
2251
goto out ;
@@ -2250,9 +2264,9 @@ static int bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc,
2250
2264
* id = bmc -> id ;
2251
2265
2252
2266
if (guid_set )
2253
- * guid_set = bmc -> guid_set ;
2267
+ * guid_set = bmc -> dyn_guid_set ;
2254
2268
2255
- if (guid && bmc -> guid_set )
2269
+ if (guid && bmc -> dyn_guid_set )
2256
2270
memcpy (guid , bmc -> guid , 16 );
2257
2271
2258
2272
mutex_unlock (& bmc -> dyn_mutex );
@@ -2845,7 +2859,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum)
2845
2859
* representing the interfaced BMC already
2846
2860
*/
2847
2861
mutex_lock (& ipmidriver_mutex );
2848
- if (bmc -> guid_set )
2862
+ if (bmc -> dyn_guid_set )
2849
2863
old_bmc = ipmi_find_bmc_guid (& ipmidriver .driver , bmc -> guid );
2850
2864
else
2851
2865
old_bmc = ipmi_find_bmc_prod_dev_id (& ipmidriver .driver ,
@@ -2997,9 +3011,10 @@ send_guid_cmd(ipmi_smi_t intf, int chan)
2997
3011
-1 , 0 );
2998
3012
}
2999
3013
3000
- static void
3001
- guid_handler (ipmi_smi_t intf , struct ipmi_recv_msg * msg )
3014
+ static void guid_handler (ipmi_smi_t intf , struct ipmi_recv_msg * msg )
3002
3015
{
3016
+ struct bmc_device * bmc = intf -> bmc ;
3017
+
3003
3018
if ((msg -> addr .addr_type != IPMI_SYSTEM_INTERFACE_ADDR_TYPE )
3004
3019
|| (msg -> msg .netfn != IPMI_NETFN_APP_RESPONSE )
3005
3020
|| (msg -> msg .cmd != IPMI_GET_DEVICE_GUID_CMD ))
@@ -3008,12 +3023,12 @@ guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
3008
3023
3009
3024
if (msg -> msg .data [0 ] != 0 ) {
3010
3025
/* Error from getting the GUID, the BMC doesn't have one. */
3011
- intf -> bmc -> guid_set = 0 ;
3026
+ bmc -> dyn_guid_set = 0 ;
3012
3027
goto out ;
3013
3028
}
3014
3029
3015
3030
if (msg -> msg .data_len < 17 ) {
3016
- intf -> bmc -> guid_set = 0 ;
3031
+ bmc -> dyn_guid_set = 0 ;
3017
3032
printk (KERN_WARNING PFX
3018
3033
"guid_handler: The GUID response from the BMC was too"
3019
3034
" short, it was %d but should have been 17. Assuming"
@@ -3022,24 +3037,34 @@ guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
3022
3037
goto out ;
3023
3038
}
3024
3039
3025
- memcpy (intf -> bmc -> guid , msg -> msg .data + 1 , 16 );
3026
- intf -> bmc -> guid_set = 1 ;
3040
+ memcpy (bmc -> fetch_guid , msg -> msg .data + 1 , 16 );
3041
+ /*
3042
+ * Make sure the guid data is available before setting
3043
+ * dyn_guid_set.
3044
+ */
3045
+ smp_wmb ();
3046
+ bmc -> dyn_guid_set = 1 ;
3027
3047
out :
3028
3048
wake_up (& intf -> waitq );
3029
3049
}
3030
3050
3031
- static void
3032
- get_guid (ipmi_smi_t intf )
3051
+ static void __get_guid (ipmi_smi_t intf )
3033
3052
{
3034
3053
int rv ;
3054
+ struct bmc_device * bmc = intf -> bmc ;
3035
3055
3036
- intf -> bmc -> guid_set = 0x2 ;
3056
+ bmc -> dyn_guid_set = 2 ;
3037
3057
intf -> null_user_handler = guid_handler ;
3038
3058
rv = send_guid_cmd (intf , 0 );
3039
3059
if (rv )
3040
3060
/* Send failed, no GUID available. */
3041
- intf -> bmc -> guid_set = 0 ;
3042
- wait_event (intf -> waitq , intf -> bmc -> guid_set != 2 );
3061
+ bmc -> dyn_guid_set = 0 ;
3062
+
3063
+ wait_event (intf -> waitq , bmc -> dyn_guid_set != 2 );
3064
+
3065
+ /* dyn_guid_set makes the guid data available. */
3066
+ smp_rmb ();
3067
+
3043
3068
intf -> null_user_handler = NULL ;
3044
3069
}
3045
3070
@@ -3254,8 +3279,6 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
3254
3279
if (rv )
3255
3280
goto out ;
3256
3281
3257
- get_guid (intf );
3258
-
3259
3282
rv = bmc_get_device_id (intf , NULL , & id , NULL , NULL );
3260
3283
if (rv ) {
3261
3284
dev_err (si_dev , "Unable to get the device id: %d\n" , rv );
0 commit comments