@@ -357,24 +357,42 @@ static int hisi_ptt_register_irq(struct hisi_ptt *hisi_ptt)
357357static void hisi_ptt_del_free_filter (struct hisi_ptt * hisi_ptt ,
358358 struct hisi_ptt_filter_desc * filter )
359359{
360+ if (filter -> is_port )
361+ hisi_ptt -> port_mask &= ~hisi_ptt_get_filter_val (filter -> devid , true);
362+
360363 list_del (& filter -> list );
364+ kfree (filter -> name );
361365 kfree (filter );
362366}
363367
364368static struct hisi_ptt_filter_desc *
365- hisi_ptt_alloc_add_filter (struct hisi_ptt * hisi_ptt , struct pci_dev * pdev )
369+ hisi_ptt_alloc_add_filter (struct hisi_ptt * hisi_ptt , u16 devid , bool is_port )
366370{
367371 struct hisi_ptt_filter_desc * filter ;
372+ u8 devfn = devid & 0xff ;
373+ char * filter_name ;
374+
375+ filter_name = kasprintf (GFP_KERNEL , "%04x:%02x:%02x.%d" , pci_domain_nr (hisi_ptt -> pdev -> bus ),
376+ PCI_BUS_NUM (devid ), PCI_SLOT (devfn ), PCI_FUNC (devfn ));
377+ if (!filter_name ) {
378+ pci_err (hisi_ptt -> pdev , "failed to allocate name for filter %04x:%02x:%02x.%d\n" ,
379+ pci_domain_nr (hisi_ptt -> pdev -> bus ), PCI_BUS_NUM (devid ),
380+ PCI_SLOT (devfn ), PCI_FUNC (devfn ));
381+ return NULL ;
382+ }
368383
369384 filter = kzalloc (sizeof (* filter ), GFP_KERNEL );
370385 if (!filter ) {
371386 pci_err (hisi_ptt -> pdev , "failed to add filter for %s\n" ,
372- pci_name (pdev ));
387+ filter_name );
388+ kfree (filter_name );
373389 return NULL ;
374390 }
375391
376- filter -> devid = PCI_DEVID (pdev -> bus -> number , pdev -> devfn );
377- filter -> is_port = pci_pcie_type (pdev ) == PCI_EXP_TYPE_ROOT_PORT ;
392+ filter -> name = filter_name ;
393+ filter -> is_port = is_port ;
394+ filter -> devid = devid ;
395+
378396 if (filter -> is_port ) {
379397 list_add_tail (& filter -> list , & hisi_ptt -> port_filters );
380398
@@ -387,6 +405,102 @@ hisi_ptt_alloc_add_filter(struct hisi_ptt *hisi_ptt, struct pci_dev *pdev)
387405 return filter ;
388406}
389407
408+ static void hisi_ptt_update_filters (struct work_struct * work )
409+ {
410+ struct delayed_work * delayed_work = to_delayed_work (work );
411+ struct hisi_ptt_filter_update_info info ;
412+ struct hisi_ptt_filter_desc * filter ;
413+ struct hisi_ptt * hisi_ptt ;
414+
415+ hisi_ptt = container_of (delayed_work , struct hisi_ptt , work );
416+
417+ if (!mutex_trylock (& hisi_ptt -> filter_lock )) {
418+ schedule_delayed_work (& hisi_ptt -> work , HISI_PTT_WORK_DELAY_MS );
419+ return ;
420+ }
421+
422+ while (kfifo_get (& hisi_ptt -> filter_update_kfifo , & info )) {
423+ if (info .is_add ) {
424+ /*
425+ * Notify the users if failed to add this filter, others
426+ * still work and available. See the comments in
427+ * hisi_ptt_init_filters().
428+ */
429+ filter = hisi_ptt_alloc_add_filter (hisi_ptt , info .devid , info .is_port );
430+ if (!filter )
431+ continue ;
432+ } else {
433+ struct hisi_ptt_filter_desc * tmp ;
434+ struct list_head * target_list ;
435+
436+ target_list = info .is_port ? & hisi_ptt -> port_filters :
437+ & hisi_ptt -> req_filters ;
438+
439+ list_for_each_entry_safe (filter , tmp , target_list , list )
440+ if (filter -> devid == info .devid ) {
441+ hisi_ptt_del_free_filter (hisi_ptt , filter );
442+ break ;
443+ }
444+ }
445+ }
446+
447+ mutex_unlock (& hisi_ptt -> filter_lock );
448+ }
449+
450+ /*
451+ * A PCI bus notifier is used here for dynamically updating the filter
452+ * list.
453+ */
454+ static int hisi_ptt_notifier_call (struct notifier_block * nb , unsigned long action ,
455+ void * data )
456+ {
457+ struct hisi_ptt * hisi_ptt = container_of (nb , struct hisi_ptt , hisi_ptt_nb );
458+ struct hisi_ptt_filter_update_info info ;
459+ struct pci_dev * pdev , * root_port ;
460+ struct device * dev = data ;
461+ u32 port_devid ;
462+
463+ pdev = to_pci_dev (dev );
464+ root_port = pcie_find_root_port (pdev );
465+ if (!root_port )
466+ return 0 ;
467+
468+ port_devid = PCI_DEVID (root_port -> bus -> number , root_port -> devfn );
469+ if (port_devid < hisi_ptt -> lower_bdf ||
470+ port_devid > hisi_ptt -> upper_bdf )
471+ return 0 ;
472+
473+ info .is_port = pci_pcie_type (pdev ) == PCI_EXP_TYPE_ROOT_PORT ;
474+ info .devid = PCI_DEVID (pdev -> bus -> number , pdev -> devfn );
475+
476+ switch (action ) {
477+ case BUS_NOTIFY_ADD_DEVICE :
478+ info .is_add = true;
479+ break ;
480+ case BUS_NOTIFY_DEL_DEVICE :
481+ info .is_add = false;
482+ break ;
483+ default :
484+ return 0 ;
485+ }
486+
487+ /*
488+ * The FIFO size is 16 which is sufficient for almost all the cases,
489+ * since each PCIe core will have most 8 Root Ports (typically only
490+ * 1~4 Root Ports). On failure log the failed filter and let user
491+ * handle it.
492+ */
493+ if (kfifo_in_spinlocked (& hisi_ptt -> filter_update_kfifo , & info , 1 ,
494+ & hisi_ptt -> filter_update_lock ))
495+ schedule_delayed_work (& hisi_ptt -> work , 0 );
496+ else
497+ pci_warn (hisi_ptt -> pdev ,
498+ "filter update fifo overflow for target %s\n" ,
499+ pci_name (pdev ));
500+
501+ return 0 ;
502+ }
503+
390504static int hisi_ptt_init_filters (struct pci_dev * pdev , void * data )
391505{
392506 struct pci_dev * root_port = pcie_find_root_port (pdev );
@@ -407,7 +521,8 @@ static int hisi_ptt_init_filters(struct pci_dev *pdev, void *data)
407521 * should be partial initialized and users would know which filter fails
408522 * through the log. Other functions of PTT device are still available.
409523 */
410- filter = hisi_ptt_alloc_add_filter (hisi_ptt , pdev );
524+ filter = hisi_ptt_alloc_add_filter (hisi_ptt , PCI_DEVID (pdev -> bus -> number , pdev -> devfn ),
525+ pci_pcie_type (pdev ) == PCI_EXP_TYPE_ROOT_PORT );
411526 if (!filter )
412527 return - ENOMEM ;
413528
@@ -466,8 +581,13 @@ static int hisi_ptt_init_ctrls(struct hisi_ptt *hisi_ptt)
466581 int ret ;
467582 u32 reg ;
468583
584+ INIT_DELAYED_WORK (& hisi_ptt -> work , hisi_ptt_update_filters );
585+ INIT_KFIFO (hisi_ptt -> filter_update_kfifo );
586+ spin_lock_init (& hisi_ptt -> filter_update_lock );
587+
469588 INIT_LIST_HEAD (& hisi_ptt -> port_filters );
470589 INIT_LIST_HEAD (& hisi_ptt -> req_filters );
590+ mutex_init (& hisi_ptt -> filter_lock );
471591
472592 ret = hisi_ptt_config_trace_buf (hisi_ptt );
473593 if (ret )
@@ -620,6 +740,7 @@ static int hisi_ptt_trace_valid_filter(struct hisi_ptt *hisi_ptt, u64 config)
620740{
621741 unsigned long val , port_mask = hisi_ptt -> port_mask ;
622742 struct hisi_ptt_filter_desc * filter ;
743+ int ret = 0 ;
623744
624745 hisi_ptt -> trace_ctrl .is_port = FIELD_GET (HISI_PTT_PMU_FILTER_IS_PORT , config );
625746 val = FIELD_GET (HISI_PTT_PMU_FILTER_VAL_MASK , config );
@@ -633,16 +754,20 @@ static int hisi_ptt_trace_valid_filter(struct hisi_ptt *hisi_ptt, u64 config)
633754 * For Requester ID filters, walk the available filter list to see
634755 * whether we have one matched.
635756 */
757+ mutex_lock (& hisi_ptt -> filter_lock );
636758 if (!hisi_ptt -> trace_ctrl .is_port ) {
637759 list_for_each_entry (filter , & hisi_ptt -> req_filters , list ) {
638760 if (val == hisi_ptt_get_filter_val (filter -> devid , filter -> is_port ))
639- return 0 ;
761+ goto out ;
640762 }
641763 } else if (bitmap_subset (& val , & port_mask , BITS_PER_LONG )) {
642- return 0 ;
764+ goto out ;
643765 }
644766
645- return - EINVAL ;
767+ ret = - EINVAL ;
768+ out :
769+ mutex_unlock (& hisi_ptt -> filter_lock );
770+ return ret ;
646771}
647772
648773static void hisi_ptt_pmu_init_configs (struct hisi_ptt * hisi_ptt , struct perf_event * event )
@@ -916,6 +1041,31 @@ static int hisi_ptt_register_pmu(struct hisi_ptt *hisi_ptt)
9161041 & hisi_ptt -> hisi_ptt_pmu );
9171042}
9181043
1044+ static void hisi_ptt_unregister_filter_update_notifier (void * data )
1045+ {
1046+ struct hisi_ptt * hisi_ptt = data ;
1047+
1048+ bus_unregister_notifier (& pci_bus_type , & hisi_ptt -> hisi_ptt_nb );
1049+
1050+ /* Cancel any work that has been queued */
1051+ cancel_delayed_work_sync (& hisi_ptt -> work );
1052+ }
1053+
1054+ /* Register the bus notifier for dynamically updating the filter list */
1055+ static int hisi_ptt_register_filter_update_notifier (struct hisi_ptt * hisi_ptt )
1056+ {
1057+ int ret ;
1058+
1059+ hisi_ptt -> hisi_ptt_nb .notifier_call = hisi_ptt_notifier_call ;
1060+ ret = bus_register_notifier (& pci_bus_type , & hisi_ptt -> hisi_ptt_nb );
1061+ if (ret )
1062+ return ret ;
1063+
1064+ return devm_add_action_or_reset (& hisi_ptt -> pdev -> dev ,
1065+ hisi_ptt_unregister_filter_update_notifier ,
1066+ hisi_ptt );
1067+ }
1068+
9191069/*
9201070 * The DMA of PTT trace can only use direct mappings due to some
9211071 * hardware restriction. Check whether there is no IOMMU or the
@@ -987,6 +1137,10 @@ static int hisi_ptt_probe(struct pci_dev *pdev,
9871137 return ret ;
9881138 }
9891139
1140+ ret = hisi_ptt_register_filter_update_notifier (hisi_ptt );
1141+ if (ret )
1142+ pci_warn (pdev , "failed to register filter update notifier, ret = %d" , ret );
1143+
9901144 ret = hisi_ptt_register_pmu (hisi_ptt );
9911145 if (ret ) {
9921146 pci_err (pdev , "failed to register PMU device, ret = %d" , ret );
0 commit comments