@@ -405,6 +405,144 @@ hisi_ptt_alloc_add_filter(struct hisi_ptt *hisi_ptt, u16 devid, bool is_port)
405405 return filter ;
406406}
407407
408+ static ssize_t hisi_ptt_filter_show (struct device * dev , struct device_attribute * attr ,
409+ char * buf )
410+ {
411+ struct hisi_ptt_filter_desc * filter ;
412+ unsigned long filter_val ;
413+
414+ filter = container_of (attr , struct hisi_ptt_filter_desc , attr );
415+ filter_val = hisi_ptt_get_filter_val (filter -> devid , filter -> is_port ) |
416+ (filter -> is_port ? HISI_PTT_PMU_FILTER_IS_PORT : 0 );
417+
418+ return sysfs_emit (buf , "0x%05lx\n" , filter_val );
419+ }
420+
421+ static int hisi_ptt_create_rp_filter_attr (struct hisi_ptt * hisi_ptt ,
422+ struct hisi_ptt_filter_desc * filter )
423+ {
424+ struct kobject * kobj = & hisi_ptt -> hisi_ptt_pmu .dev -> kobj ;
425+
426+ sysfs_attr_init (& filter -> attr .attr );
427+ filter -> attr .attr .name = filter -> name ;
428+ filter -> attr .attr .mode = 0400 ; /* DEVICE_ATTR_ADMIN_RO */
429+ filter -> attr .show = hisi_ptt_filter_show ;
430+
431+ return sysfs_add_file_to_group (kobj , & filter -> attr .attr ,
432+ HISI_PTT_RP_FILTERS_GRP_NAME );
433+ }
434+
435+ static void hisi_ptt_remove_rp_filter_attr (struct hisi_ptt * hisi_ptt ,
436+ struct hisi_ptt_filter_desc * filter )
437+ {
438+ struct kobject * kobj = & hisi_ptt -> hisi_ptt_pmu .dev -> kobj ;
439+
440+ sysfs_remove_file_from_group (kobj , & filter -> attr .attr ,
441+ HISI_PTT_RP_FILTERS_GRP_NAME );
442+ }
443+
444+ static int hisi_ptt_create_req_filter_attr (struct hisi_ptt * hisi_ptt ,
445+ struct hisi_ptt_filter_desc * filter )
446+ {
447+ struct kobject * kobj = & hisi_ptt -> hisi_ptt_pmu .dev -> kobj ;
448+
449+ sysfs_attr_init (& filter -> attr .attr );
450+ filter -> attr .attr .name = filter -> name ;
451+ filter -> attr .attr .mode = 0400 ; /* DEVICE_ATTR_ADMIN_RO */
452+ filter -> attr .show = hisi_ptt_filter_show ;
453+
454+ return sysfs_add_file_to_group (kobj , & filter -> attr .attr ,
455+ HISI_PTT_REQ_FILTERS_GRP_NAME );
456+ }
457+
458+ static void hisi_ptt_remove_req_filter_attr (struct hisi_ptt * hisi_ptt ,
459+ struct hisi_ptt_filter_desc * filter )
460+ {
461+ struct kobject * kobj = & hisi_ptt -> hisi_ptt_pmu .dev -> kobj ;
462+
463+ sysfs_remove_file_from_group (kobj , & filter -> attr .attr ,
464+ HISI_PTT_REQ_FILTERS_GRP_NAME );
465+ }
466+
467+ static int hisi_ptt_create_filter_attr (struct hisi_ptt * hisi_ptt ,
468+ struct hisi_ptt_filter_desc * filter )
469+ {
470+ int ret ;
471+
472+ if (filter -> is_port )
473+ ret = hisi_ptt_create_rp_filter_attr (hisi_ptt , filter );
474+ else
475+ ret = hisi_ptt_create_req_filter_attr (hisi_ptt , filter );
476+
477+ if (ret )
478+ pci_err (hisi_ptt -> pdev , "failed to create sysfs attribute for filter %s\n" ,
479+ filter -> name );
480+
481+ return ret ;
482+ }
483+
484+ static void hisi_ptt_remove_filter_attr (struct hisi_ptt * hisi_ptt ,
485+ struct hisi_ptt_filter_desc * filter )
486+ {
487+ if (filter -> is_port )
488+ hisi_ptt_remove_rp_filter_attr (hisi_ptt , filter );
489+ else
490+ hisi_ptt_remove_req_filter_attr (hisi_ptt , filter );
491+ }
492+
493+ static void hisi_ptt_remove_all_filter_attributes (void * data )
494+ {
495+ struct hisi_ptt_filter_desc * filter ;
496+ struct hisi_ptt * hisi_ptt = data ;
497+
498+ mutex_lock (& hisi_ptt -> filter_lock );
499+
500+ list_for_each_entry (filter , & hisi_ptt -> req_filters , list )
501+ hisi_ptt_remove_filter_attr (hisi_ptt , filter );
502+
503+ list_for_each_entry (filter , & hisi_ptt -> port_filters , list )
504+ hisi_ptt_remove_filter_attr (hisi_ptt , filter );
505+
506+ hisi_ptt -> sysfs_inited = false;
507+ mutex_unlock (& hisi_ptt -> filter_lock );
508+ }
509+
510+ static int hisi_ptt_init_filter_attributes (struct hisi_ptt * hisi_ptt )
511+ {
512+ struct hisi_ptt_filter_desc * filter ;
513+ int ret ;
514+
515+ mutex_lock (& hisi_ptt -> filter_lock );
516+
517+ /*
518+ * Register the reset callback in the first stage. In reset we traverse
519+ * the filters list to remove the sysfs attributes so the callback can
520+ * be called safely even without below filter attributes creation.
521+ */
522+ ret = devm_add_action (& hisi_ptt -> pdev -> dev ,
523+ hisi_ptt_remove_all_filter_attributes ,
524+ hisi_ptt );
525+ if (ret )
526+ goto out ;
527+
528+ list_for_each_entry (filter , & hisi_ptt -> port_filters , list ) {
529+ ret = hisi_ptt_create_filter_attr (hisi_ptt , filter );
530+ if (ret )
531+ goto out ;
532+ }
533+
534+ list_for_each_entry (filter , & hisi_ptt -> req_filters , list ) {
535+ ret = hisi_ptt_create_filter_attr (hisi_ptt , filter );
536+ if (ret )
537+ goto out ;
538+ }
539+
540+ hisi_ptt -> sysfs_inited = true;
541+ out :
542+ mutex_unlock (& hisi_ptt -> filter_lock );
543+ return ret ;
544+ }
545+
408546static void hisi_ptt_update_filters (struct work_struct * work )
409547{
410548 struct delayed_work * delayed_work = to_delayed_work (work );
@@ -429,6 +567,18 @@ static void hisi_ptt_update_filters(struct work_struct *work)
429567 filter = hisi_ptt_alloc_add_filter (hisi_ptt , info .devid , info .is_port );
430568 if (!filter )
431569 continue ;
570+
571+ /*
572+ * If filters' sysfs entries hasn't been initialized,
573+ * then we're still at probe stage. Add the filters to
574+ * the list and later hisi_ptt_init_filter_attributes()
575+ * will create sysfs attributes for all the filters.
576+ */
577+ if (hisi_ptt -> sysfs_inited &&
578+ hisi_ptt_create_filter_attr (hisi_ptt , filter )) {
579+ hisi_ptt_del_free_filter (hisi_ptt , filter );
580+ continue ;
581+ }
432582 } else {
433583 struct hisi_ptt_filter_desc * tmp ;
434584 struct list_head * target_list ;
@@ -438,6 +588,9 @@ static void hisi_ptt_update_filters(struct work_struct *work)
438588
439589 list_for_each_entry_safe (filter , tmp , target_list , list )
440590 if (filter -> devid == info .devid ) {
591+ if (hisi_ptt -> sysfs_inited )
592+ hisi_ptt_remove_filter_attr (hisi_ptt , filter );
593+
441594 hisi_ptt_del_free_filter (hisi_ptt , filter );
442595 break ;
443596 }
@@ -663,10 +816,58 @@ static struct attribute_group hisi_ptt_pmu_format_group = {
663816 .attrs = hisi_ptt_pmu_format_attrs ,
664817};
665818
819+ static ssize_t hisi_ptt_filter_multiselect_show (struct device * dev ,
820+ struct device_attribute * attr ,
821+ char * buf )
822+ {
823+ struct dev_ext_attribute * ext_attr ;
824+
825+ ext_attr = container_of (attr , struct dev_ext_attribute , attr );
826+ return sysfs_emit (buf , "%s\n" , (char * )ext_attr -> var );
827+ }
828+
829+ static struct dev_ext_attribute root_port_filters_multiselect = {
830+ .attr = {
831+ .attr = { .name = "multiselect" , .mode = 0400 },
832+ .show = hisi_ptt_filter_multiselect_show ,
833+ },
834+ .var = "1" ,
835+ };
836+
837+ static struct attribute * hisi_ptt_pmu_root_ports_attrs [] = {
838+ & root_port_filters_multiselect .attr .attr ,
839+ NULL
840+ };
841+
842+ static struct attribute_group hisi_ptt_pmu_root_ports_group = {
843+ .name = HISI_PTT_RP_FILTERS_GRP_NAME ,
844+ .attrs = hisi_ptt_pmu_root_ports_attrs ,
845+ };
846+
847+ static struct dev_ext_attribute requester_filters_multiselect = {
848+ .attr = {
849+ .attr = { .name = "multiselect" , .mode = 0400 },
850+ .show = hisi_ptt_filter_multiselect_show ,
851+ },
852+ .var = "0" ,
853+ };
854+
855+ static struct attribute * hisi_ptt_pmu_requesters_attrs [] = {
856+ & requester_filters_multiselect .attr .attr ,
857+ NULL
858+ };
859+
860+ static struct attribute_group hisi_ptt_pmu_requesters_group = {
861+ .name = HISI_PTT_REQ_FILTERS_GRP_NAME ,
862+ .attrs = hisi_ptt_pmu_requesters_attrs ,
863+ };
864+
666865static const struct attribute_group * hisi_ptt_pmu_groups [] = {
667866 & hisi_ptt_cpumask_attr_group ,
668867 & hisi_ptt_pmu_format_group ,
669868 & hisi_ptt_tune_group ,
869+ & hisi_ptt_pmu_root_ports_group ,
870+ & hisi_ptt_pmu_requesters_group ,
670871 NULL
671872};
672873
@@ -1147,6 +1348,12 @@ static int hisi_ptt_probe(struct pci_dev *pdev,
11471348 return ret ;
11481349 }
11491350
1351+ ret = hisi_ptt_init_filter_attributes (hisi_ptt );
1352+ if (ret ) {
1353+ pci_err (pdev , "failed to init sysfs filter attributes, ret = %d" , ret );
1354+ return ret ;
1355+ }
1356+
11501357 return 0 ;
11511358}
11521359
0 commit comments