24
24
#include <linux/bitops.h>
25
25
#include <linux/cpufeature.h>
26
26
#include <linux/cpumask.h>
27
+ #include <linux/delay.h>
27
28
#include <linux/gfp.h>
28
29
#include <linux/io.h>
29
30
#include <linux/kernel.h>
@@ -347,6 +348,52 @@ static void init_hfi_instance(struct hfi_instance *hfi_instance)
347
348
hfi_instance -> data = hfi_instance -> hdr + hfi_features .hdr_size ;
348
349
}
349
350
351
+ /* Caller must hold hfi_instance_lock. */
352
+ static void hfi_enable (void )
353
+ {
354
+ u64 msr_val ;
355
+
356
+ rdmsrl (MSR_IA32_HW_FEEDBACK_CONFIG , msr_val );
357
+ msr_val |= HW_FEEDBACK_CONFIG_HFI_ENABLE_BIT ;
358
+ wrmsrl (MSR_IA32_HW_FEEDBACK_CONFIG , msr_val );
359
+ }
360
+
361
+ static void hfi_set_hw_table (struct hfi_instance * hfi_instance )
362
+ {
363
+ phys_addr_t hw_table_pa ;
364
+ u64 msr_val ;
365
+
366
+ hw_table_pa = virt_to_phys (hfi_instance -> hw_table );
367
+ msr_val = hw_table_pa | HW_FEEDBACK_PTR_VALID_BIT ;
368
+ wrmsrl (MSR_IA32_HW_FEEDBACK_PTR , msr_val );
369
+ }
370
+
371
+ /* Caller must hold hfi_instance_lock. */
372
+ static void hfi_disable (void )
373
+ {
374
+ u64 msr_val ;
375
+ int i ;
376
+
377
+ rdmsrl (MSR_IA32_HW_FEEDBACK_CONFIG , msr_val );
378
+ msr_val &= ~HW_FEEDBACK_CONFIG_HFI_ENABLE_BIT ;
379
+ wrmsrl (MSR_IA32_HW_FEEDBACK_CONFIG , msr_val );
380
+
381
+ /*
382
+ * Wait for hardware to acknowledge the disabling of HFI. Some
383
+ * processors may not do it. Wait for ~2ms. This is a reasonable
384
+ * time for hardware to complete any pending actions on the HFI
385
+ * memory.
386
+ */
387
+ for (i = 0 ; i < 2000 ; i ++ ) {
388
+ rdmsrl (MSR_IA32_PACKAGE_THERM_STATUS , msr_val );
389
+ if (msr_val & PACKAGE_THERM_STATUS_HFI_UPDATED )
390
+ break ;
391
+
392
+ udelay (1 );
393
+ cpu_relax ();
394
+ }
395
+ }
396
+
350
397
/**
351
398
* intel_hfi_online() - Enable HFI on @cpu
352
399
* @cpu: CPU in which the HFI will be enabled
@@ -364,8 +411,6 @@ void intel_hfi_online(unsigned int cpu)
364
411
{
365
412
struct hfi_instance * hfi_instance ;
366
413
struct hfi_cpu_info * info ;
367
- phys_addr_t hw_table_pa ;
368
- u64 msr_val ;
369
414
u16 die_id ;
370
415
371
416
/* Nothing to do if hfi_instances are missing. */
@@ -392,25 +437,26 @@ void intel_hfi_online(unsigned int cpu)
392
437
/*
393
438
* Now check if the HFI instance of the package/die of @cpu has been
394
439
* initialized (by checking its header). In such case, all we have to
395
- * do is to add @cpu to this instance's cpumask.
440
+ * do is to add @cpu to this instance's cpumask and enable the instance
441
+ * if needed.
396
442
*/
397
443
mutex_lock (& hfi_instance_lock );
398
- if (hfi_instance -> hdr ) {
399
- cpumask_set_cpu (cpu , hfi_instance -> cpus );
400
- goto unlock ;
401
- }
444
+ if (hfi_instance -> hdr )
445
+ goto enable ;
402
446
403
447
/*
404
448
* Hardware is programmed with the physical address of the first page
405
449
* frame of the table. Hence, the allocated memory must be page-aligned.
450
+ *
451
+ * Some processors do not forget the initial address of the HFI table
452
+ * even after having been reprogrammed. Keep using the same pages. Do
453
+ * not free them.
406
454
*/
407
455
hfi_instance -> hw_table = alloc_pages_exact (hfi_features .nr_table_pages ,
408
456
GFP_KERNEL | __GFP_ZERO );
409
457
if (!hfi_instance -> hw_table )
410
458
goto unlock ;
411
459
412
- hw_table_pa = virt_to_phys (hfi_instance -> hw_table );
413
-
414
460
/*
415
461
* Allocate memory to keep a local copy of the table that
416
462
* hardware generates.
@@ -420,31 +466,20 @@ void intel_hfi_online(unsigned int cpu)
420
466
if (!hfi_instance -> local_table )
421
467
goto free_hw_table ;
422
468
423
- /*
424
- * Program the address of the feedback table of this die/package. On
425
- * some processors, hardware remembers the old address of the HFI table
426
- * even after having been reprogrammed and re-enabled. Thus, do not free
427
- * the pages allocated for the table or reprogram the hardware with a
428
- * new base address. Namely, program the hardware only once.
429
- */
430
- msr_val = hw_table_pa | HW_FEEDBACK_PTR_VALID_BIT ;
431
- wrmsrl (MSR_IA32_HW_FEEDBACK_PTR , msr_val );
432
-
433
469
init_hfi_instance (hfi_instance );
434
470
435
471
INIT_DELAYED_WORK (& hfi_instance -> update_work , hfi_update_work_fn );
436
472
raw_spin_lock_init (& hfi_instance -> table_lock );
437
473
raw_spin_lock_init (& hfi_instance -> event_lock );
438
474
475
+ enable :
439
476
cpumask_set_cpu (cpu , hfi_instance -> cpus );
440
477
441
- /*
442
- * Enable the hardware feedback interface and never disable it. See
443
- * comment on programming the address of the table.
444
- */
445
- rdmsrl (MSR_IA32_HW_FEEDBACK_CONFIG , msr_val );
446
- msr_val |= HW_FEEDBACK_CONFIG_HFI_ENABLE_BIT ;
447
- wrmsrl (MSR_IA32_HW_FEEDBACK_CONFIG , msr_val );
478
+ /* Enable this HFI instance if this is its first online CPU. */
479
+ if (cpumask_weight (hfi_instance -> cpus ) == 1 ) {
480
+ hfi_set_hw_table (hfi_instance );
481
+ hfi_enable ();
482
+ }
448
483
449
484
unlock :
450
485
mutex_unlock (& hfi_instance_lock );
@@ -484,6 +519,10 @@ void intel_hfi_offline(unsigned int cpu)
484
519
485
520
mutex_lock (& hfi_instance_lock );
486
521
cpumask_clear_cpu (cpu , hfi_instance -> cpus );
522
+
523
+ if (!cpumask_weight (hfi_instance -> cpus ))
524
+ hfi_disable ();
525
+
487
526
mutex_unlock (& hfi_instance_lock );
488
527
}
489
528
0 commit comments