Unverified Commit 2a45fac1 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!15185 hwtracing: hisi_ptt: Initialize the filter sysfs attribute when allocation

Merge Pull Request from: @lujunhuaHW 
 
The filter sysfs attribute is initialized when creating to the sysfs. This is unnecessary and could be done when allocation without distinguishing the filter type.

After the changes above, we don't need a wrapper for initializing and registering the filter's sysfs attributes. Remove them and call the sysfs creating/removing functions in place.

Abnormally it's reported duplicated filters added in the filter list, though the filter we created should be unique maintained by the PCIe framework. Add a duplicate filters check before allocation to prevent this case.

Issue:
https://gitee.com/openeuler/kernel/issues/IBNZ64 
 
Link:https://gitee.com/openeuler/kernel/pulls/15185

 

Reviewed-by: default avatarYang Shen <shenyang39@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 1c55f6bf 8945c86d
Loading
Loading
Loading
Loading
+58 −63
Original line number Diff line number Diff line
@@ -368,6 +368,45 @@ static void hisi_ptt_del_free_filter(struct hisi_ptt *hisi_ptt,
	kfree(filter);
}

static ssize_t hisi_ptt_filter_show(struct device *dev, struct device_attribute *attr,
				    char *buf)
{
	struct hisi_ptt_filter_desc *filter;
	unsigned long filter_val;

	filter = container_of(attr, struct hisi_ptt_filter_desc, attr);
	filter_val = hisi_ptt_get_filter_val(filter->devid, filter->is_port) |
		     (filter->is_port ? HISI_PTT_PMU_FILTER_IS_PORT : 0);

	return sysfs_emit(buf, "0x%05lx\n", filter_val);
}

static int hisi_ptt_check_duplicated_filters(struct hisi_ptt *hisi_ptt, u16 devid, bool is_port)
{
	struct hisi_ptt_filter_desc *filter;
	struct list_head *target_list;
	u8 devfn = devid & 0xff;

	if (is_port)
		target_list = &hisi_ptt->port_filters;
	else
		target_list = &hisi_ptt->req_filters;

	list_for_each_entry(filter, target_list, list) {
		if (filter->devid == devid) {
			pci_warn(hisi_ptt->pdev,
				 "ignore duplicated filter %04x:%02x:%02x.%d\n",
				 pci_domain_nr(hisi_ptt->pdev->bus),
				 PCI_BUS_NUM(devid), PCI_SLOT(devfn),
				 PCI_FUNC(devfn));

			return -EEXIST;
		}
	}

	return 0;
}

static struct hisi_ptt_filter_desc *
hisi_ptt_alloc_add_filter(struct hisi_ptt *hisi_ptt, u16 devid, bool is_port)
{
@@ -375,6 +414,9 @@ hisi_ptt_alloc_add_filter(struct hisi_ptt *hisi_ptt, u16 devid, bool is_port)
	u8 devfn = devid & 0xff;
	char *filter_name;

	if (hisi_ptt_check_duplicated_filters(hisi_ptt, devid, is_port))
		return NULL;

	filter_name = kasprintf(GFP_KERNEL, "%04x:%02x:%02x.%d", pci_domain_nr(hisi_ptt->pdev->bus),
				 PCI_BUS_NUM(devid), PCI_SLOT(devfn), PCI_FUNC(devfn));
	if (!filter_name) {
@@ -396,6 +438,11 @@ hisi_ptt_alloc_add_filter(struct hisi_ptt *hisi_ptt, u16 devid, bool is_port)
	filter->is_port = is_port;
	filter->devid = devid;

	sysfs_attr_init(&filter->attr.attr);
	filter->attr.attr.name = filter->name;
	filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */
	filter->attr.show = hisi_ptt_filter_show;

	if (filter->is_port) {
		list_add_tail(&filter->list, &hisi_ptt->port_filters);

@@ -408,74 +455,18 @@ hisi_ptt_alloc_add_filter(struct hisi_ptt *hisi_ptt, u16 devid, bool is_port)
	return filter;
}

static ssize_t hisi_ptt_filter_show(struct device *dev, struct device_attribute *attr,
				    char *buf)
{
	struct hisi_ptt_filter_desc *filter;
	unsigned long filter_val;

	filter = container_of(attr, struct hisi_ptt_filter_desc, attr);
	filter_val = hisi_ptt_get_filter_val(filter->devid, filter->is_port) |
		     (filter->is_port ? HISI_PTT_PMU_FILTER_IS_PORT : 0);

	return sysfs_emit(buf, "0x%05lx\n", filter_val);
}

static int hisi_ptt_create_rp_filter_attr(struct hisi_ptt *hisi_ptt,
					  struct hisi_ptt_filter_desc *filter)
{
	struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;

	sysfs_attr_init(&filter->attr.attr);
	filter->attr.attr.name = filter->name;
	filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */
	filter->attr.show = hisi_ptt_filter_show;

	return sysfs_add_file_to_group(kobj, &filter->attr.attr,
				       HISI_PTT_RP_FILTERS_GRP_NAME);
}

static void hisi_ptt_remove_rp_filter_attr(struct hisi_ptt *hisi_ptt,
					  struct hisi_ptt_filter_desc *filter)
{
	struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;

	sysfs_remove_file_from_group(kobj, &filter->attr.attr,
				     HISI_PTT_RP_FILTERS_GRP_NAME);
}

static int hisi_ptt_create_req_filter_attr(struct hisi_ptt *hisi_ptt,
					   struct hisi_ptt_filter_desc *filter)
{
	struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;

	sysfs_attr_init(&filter->attr.attr);
	filter->attr.attr.name = filter->name;
	filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */
	filter->attr.show = hisi_ptt_filter_show;

	return sysfs_add_file_to_group(kobj, &filter->attr.attr,
				       HISI_PTT_REQ_FILTERS_GRP_NAME);
}

static void hisi_ptt_remove_req_filter_attr(struct hisi_ptt *hisi_ptt,
					   struct hisi_ptt_filter_desc *filter)
{
	struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;

	sysfs_remove_file_from_group(kobj, &filter->attr.attr,
				     HISI_PTT_REQ_FILTERS_GRP_NAME);
}

static int hisi_ptt_create_filter_attr(struct hisi_ptt *hisi_ptt,
				       struct hisi_ptt_filter_desc *filter)
{
	struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;
	int ret;

	if (filter->is_port)
		ret = hisi_ptt_create_rp_filter_attr(hisi_ptt, filter);
		ret = sysfs_add_file_to_group(kobj, &filter->attr.attr,
					      HISI_PTT_RP_FILTERS_GRP_NAME);
	else
		ret = hisi_ptt_create_req_filter_attr(hisi_ptt, filter);
		ret = sysfs_add_file_to_group(kobj, &filter->attr.attr,
					      HISI_PTT_REQ_FILTERS_GRP_NAME);

	if (ret)
		pci_err(hisi_ptt->pdev, "failed to create sysfs attribute for filter %s\n",
@@ -487,10 +478,14 @@ static int hisi_ptt_create_filter_attr(struct hisi_ptt *hisi_ptt,
static void hisi_ptt_remove_filter_attr(struct hisi_ptt *hisi_ptt,
					struct hisi_ptt_filter_desc *filter)
{
	struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;

	if (filter->is_port)
		hisi_ptt_remove_rp_filter_attr(hisi_ptt, filter);
		sysfs_remove_file_from_group(kobj, &filter->attr.attr,
					     HISI_PTT_RP_FILTERS_GRP_NAME);
	else
		hisi_ptt_remove_req_filter_attr(hisi_ptt, filter);
		sysfs_remove_file_from_group(kobj, &filter->attr.attr,
					     HISI_PTT_REQ_FILTERS_GRP_NAME);
}

static void hisi_ptt_remove_all_filter_attributes(void *data)