@@ -259,80 +259,6 @@ static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm)
259
259
return devm_add_action_or_reset (host , disable_hdm , cxlhdm );
260
260
}
261
261
262
- static bool __cxl_hdm_decode_init (struct cxl_dev_state * cxlds ,
263
- struct cxl_hdm * cxlhdm ,
264
- struct cxl_endpoint_dvsec_info * info )
265
- {
266
- void __iomem * hdm = cxlhdm -> regs .hdm_decoder ;
267
- struct cxl_port * port = cxlhdm -> port ;
268
- struct device * dev = cxlds -> dev ;
269
- struct cxl_port * root ;
270
- int i , rc , allowed ;
271
- u32 global_ctrl ;
272
-
273
- global_ctrl = readl (hdm + CXL_HDM_DECODER_CTRL_OFFSET );
274
-
275
- /*
276
- * If the HDM Decoder Capability is already enabled then assume
277
- * that some other agent like platform firmware set it up.
278
- */
279
- if (global_ctrl & CXL_HDM_DECODER_ENABLE ) {
280
- rc = devm_cxl_enable_mem (& port -> dev , cxlds );
281
- if (rc )
282
- return false;
283
- return true;
284
- }
285
-
286
- root = to_cxl_port (port -> dev .parent );
287
- while (!is_cxl_root (root ) && is_cxl_port (root -> dev .parent ))
288
- root = to_cxl_port (root -> dev .parent );
289
- if (!is_cxl_root (root )) {
290
- dev_err (dev , "Failed to acquire root port for HDM enable\n" );
291
- return false;
292
- }
293
-
294
- for (i = 0 , allowed = 0 ; info -> mem_enabled && i < info -> ranges ; i ++ ) {
295
- struct device * cxld_dev ;
296
-
297
- cxld_dev = device_find_child (& root -> dev , & info -> dvsec_range [i ],
298
- dvsec_range_allowed );
299
- if (!cxld_dev ) {
300
- dev_dbg (dev , "DVSEC Range%d denied by platform\n" , i );
301
- continue ;
302
- }
303
- dev_dbg (dev , "DVSEC Range%d allowed by platform\n" , i );
304
- put_device (cxld_dev );
305
- allowed ++ ;
306
- }
307
-
308
- if (!allowed ) {
309
- cxl_set_mem_enable (cxlds , 0 );
310
- info -> mem_enabled = 0 ;
311
- }
312
-
313
- /*
314
- * Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base
315
- * [High,Low] when HDM operation is enabled the range register values
316
- * are ignored by the device, but the spec also recommends matching the
317
- * DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges
318
- * are expected even though Linux does not require or maintain that
319
- * match. If at least one DVSEC range is enabled and allowed, skip HDM
320
- * Decoder Capability Enable.
321
- */
322
- if (info -> mem_enabled )
323
- return false;
324
-
325
- rc = devm_cxl_enable_hdm (& port -> dev , cxlhdm );
326
- if (rc )
327
- return false;
328
-
329
- rc = devm_cxl_enable_mem (& port -> dev , cxlds );
330
- if (rc )
331
- return false;
332
-
333
- return true;
334
- }
335
-
336
262
int cxl_dvsec_rr_decode (struct device * dev , int d ,
337
263
struct cxl_endpoint_dvsec_info * info )
338
264
{
@@ -447,19 +373,66 @@ EXPORT_SYMBOL_NS_GPL(cxl_dvsec_rr_decode, CXL);
447
373
int cxl_hdm_decode_init (struct cxl_dev_state * cxlds , struct cxl_hdm * cxlhdm ,
448
374
struct cxl_endpoint_dvsec_info * info )
449
375
{
376
+ void __iomem * hdm = cxlhdm -> regs .hdm_decoder ;
377
+ struct cxl_port * port = cxlhdm -> port ;
450
378
struct device * dev = cxlds -> dev ;
379
+ struct cxl_port * root ;
380
+ int i , rc , allowed ;
381
+ u32 global_ctrl ;
382
+
383
+ global_ctrl = readl (hdm + CXL_HDM_DECODER_CTRL_OFFSET );
451
384
452
385
/*
453
- * If DVSEC ranges are being used instead of HDM decoder registers there
454
- * is no use in trying to manage those .
386
+ * If the HDM Decoder Capability is already enabled then assume
387
+ * that some other agent like platform firmware set it up .
455
388
*/
456
- if (!__cxl_hdm_decode_init (cxlds , cxlhdm , info )) {
457
- dev_err (dev ,
458
- "Legacy range registers configuration prevents HDM operation.\n" );
459
- return - EBUSY ;
389
+ if (global_ctrl & CXL_HDM_DECODER_ENABLE )
390
+ return devm_cxl_enable_mem (& port -> dev , cxlds );
391
+
392
+ root = to_cxl_port (port -> dev .parent );
393
+ while (!is_cxl_root (root ) && is_cxl_port (root -> dev .parent ))
394
+ root = to_cxl_port (root -> dev .parent );
395
+ if (!is_cxl_root (root )) {
396
+ dev_err (dev , "Failed to acquire root port for HDM enable\n" );
397
+ return - ENODEV ;
460
398
}
461
399
462
- return 0 ;
400
+ for (i = 0 , allowed = 0 ; info -> mem_enabled && i < info -> ranges ; i ++ ) {
401
+ struct device * cxld_dev ;
402
+
403
+ cxld_dev = device_find_child (& root -> dev , & info -> dvsec_range [i ],
404
+ dvsec_range_allowed );
405
+ if (!cxld_dev ) {
406
+ dev_dbg (dev , "DVSEC Range%d denied by platform\n" , i );
407
+ continue ;
408
+ }
409
+ dev_dbg (dev , "DVSEC Range%d allowed by platform\n" , i );
410
+ put_device (cxld_dev );
411
+ allowed ++ ;
412
+ }
413
+
414
+ if (!allowed ) {
415
+ cxl_set_mem_enable (cxlds , 0 );
416
+ info -> mem_enabled = 0 ;
417
+ }
418
+
419
+ /*
420
+ * Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base
421
+ * [High,Low] when HDM operation is enabled the range register values
422
+ * are ignored by the device, but the spec also recommends matching the
423
+ * DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges
424
+ * are expected even though Linux does not require or maintain that
425
+ * match. If at least one DVSEC range is enabled and allowed, skip HDM
426
+ * Decoder Capability Enable.
427
+ */
428
+ if (info -> mem_enabled )
429
+ return - EBUSY ;
430
+
431
+ rc = devm_cxl_enable_hdm (& port -> dev , cxlhdm );
432
+ if (rc )
433
+ return rc ;
434
+
435
+ return devm_cxl_enable_mem (& port -> dev , cxlds );
463
436
}
464
437
EXPORT_SYMBOL_NS_GPL (cxl_hdm_decode_init , CXL );
465
438
0 commit comments