Lines Matching +full:trace +full:- +full:buffer +full:- +full:extension

1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for HiSilicon PCIe tune and trace device
13 #include <linux/dma-mapping.h>
31 return !readl_poll_timeout(hisi_ptt->iobase + HISI_PTT_TUNING_INT_STAT, in hisi_ptt_wait_tuning_finish()
48 desc = ext_attr->var; in hisi_ptt_tune_attr_show()
50 mutex_lock(&hisi_ptt->tune_lock); in hisi_ptt_tune_attr_show()
52 reg = readl(hisi_ptt->iobase + HISI_PTT_TUNING_CTRL); in hisi_ptt_tune_attr_show()
55 desc->event_code); in hisi_ptt_tune_attr_show()
56 writel(reg, hisi_ptt->iobase + HISI_PTT_TUNING_CTRL); in hisi_ptt_tune_attr_show()
59 writel(~0U, hisi_ptt->iobase + HISI_PTT_TUNING_DATA); in hisi_ptt_tune_attr_show()
62 mutex_unlock(&hisi_ptt->tune_lock); in hisi_ptt_tune_attr_show()
63 return -ETIMEDOUT; in hisi_ptt_tune_attr_show()
66 reg = readl(hisi_ptt->iobase + HISI_PTT_TUNING_DATA); in hisi_ptt_tune_attr_show()
70 mutex_unlock(&hisi_ptt->tune_lock); in hisi_ptt_tune_attr_show()
85 desc = ext_attr->var; in hisi_ptt_tune_attr_store()
88 return -EINVAL; in hisi_ptt_tune_attr_store()
90 mutex_lock(&hisi_ptt->tune_lock); in hisi_ptt_tune_attr_store()
92 reg = readl(hisi_ptt->iobase + HISI_PTT_TUNING_CTRL); in hisi_ptt_tune_attr_store()
95 desc->event_code); in hisi_ptt_tune_attr_store()
96 writel(reg, hisi_ptt->iobase + HISI_PTT_TUNING_CTRL); in hisi_ptt_tune_attr_store()
98 hisi_ptt->iobase + HISI_PTT_TUNING_DATA); in hisi_ptt_tune_attr_store()
101 mutex_unlock(&hisi_ptt->tune_lock); in hisi_ptt_tune_attr_store()
102 return -ETIMEDOUT; in hisi_ptt_tune_attr_store()
105 mutex_unlock(&hisi_ptt->tune_lock); in hisi_ptt_tune_attr_store()
168 return !readl_poll_timeout_atomic(hisi_ptt->iobase + HISI_PTT_TRACE_STS, in hisi_ptt_wait_trace_hw_idle()
178 readl_poll_timeout_atomic(hisi_ptt->iobase + HISI_PTT_TRACE_WR_STS, in hisi_ptt_wait_dma_reset_done()
185 writel(0, hisi_ptt->iobase + HISI_PTT_TRACE_CTRL); in hisi_ptt_trace_end()
188 writel(HISI_PTT_TRACE_INT_MASK_ALL, hisi_ptt->iobase + HISI_PTT_TRACE_INT_MASK); in hisi_ptt_trace_end()
190 hisi_ptt->trace_ctrl.started = false; in hisi_ptt_trace_end()
195 struct hisi_ptt_trace_ctrl *ctrl = &hisi_ptt->trace_ctrl; in hisi_ptt_trace_start()
199 /* Check device idle before start trace */ in hisi_ptt_trace_start()
201 pci_err(hisi_ptt->pdev, "Failed to start trace, the device is still busy\n"); in hisi_ptt_trace_start()
202 return -EBUSY; in hisi_ptt_trace_start()
205 ctrl->started = true; in hisi_ptt_trace_start()
208 val = readl(hisi_ptt->iobase + HISI_PTT_TRACE_CTRL); in hisi_ptt_trace_start()
210 writel(val, hisi_ptt->iobase + HISI_PTT_TRACE_CTRL); in hisi_ptt_trace_start()
214 val = readl(hisi_ptt->iobase + HISI_PTT_TRACE_CTRL); in hisi_ptt_trace_start()
216 writel(val, hisi_ptt->iobase + HISI_PTT_TRACE_CTRL); in hisi_ptt_trace_start()
218 /* Reset the index of current buffer */ in hisi_ptt_trace_start()
219 hisi_ptt->trace_ctrl.buf_index = 0; in hisi_ptt_trace_start()
221 /* Zero the trace buffers */ in hisi_ptt_trace_start()
223 memset(ctrl->trace_buf[i].addr, 0, HISI_PTT_TRACE_BUF_SIZE); in hisi_ptt_trace_start()
226 writel(HISI_PTT_TRACE_INT_STAT_MASK, hisi_ptt->iobase + HISI_PTT_TRACE_INT_STAT); in hisi_ptt_trace_start()
227 writel(0, hisi_ptt->iobase + HISI_PTT_TRACE_INT_MASK); in hisi_ptt_trace_start()
229 /* Set the trace control register */ in hisi_ptt_trace_start()
230 val = FIELD_PREP(HISI_PTT_TRACE_CTRL_TYPE_SEL, ctrl->type); in hisi_ptt_trace_start()
231 val |= FIELD_PREP(HISI_PTT_TRACE_CTRL_RXTX_SEL, ctrl->direction); in hisi_ptt_trace_start()
232 val |= FIELD_PREP(HISI_PTT_TRACE_CTRL_DATA_FORMAT, ctrl->format); in hisi_ptt_trace_start()
233 val |= FIELD_PREP(HISI_PTT_TRACE_CTRL_TARGET_SEL, hisi_ptt->trace_ctrl.filter); in hisi_ptt_trace_start()
234 if (!hisi_ptt->trace_ctrl.is_port) in hisi_ptt_trace_start()
237 /* Start the Trace */ in hisi_ptt_trace_start()
239 writel(val, hisi_ptt->iobase + HISI_PTT_TRACE_CTRL); in hisi_ptt_trace_start()
246 struct hisi_ptt_trace_ctrl *ctrl = &hisi_ptt->trace_ctrl; in hisi_ptt_update_aux()
247 struct perf_output_handle *handle = &ctrl->handle; in hisi_ptt_update_aux()
248 struct perf_event *event = handle->event; in hisi_ptt_update_aux()
254 if (!buf || !handle->size) in hisi_ptt_update_aux()
255 return -EINVAL; in hisi_ptt_update_aux()
257 addr = ctrl->trace_buf[ctrl->buf_index].addr; in hisi_ptt_update_aux()
267 reg = readl(hisi_ptt->iobase + HISI_PTT_TRACE_WR_STS); in hisi_ptt_update_aux()
273 memcpy(buf->base + buf->pos, addr, size); in hisi_ptt_update_aux()
274 buf->pos += size; in hisi_ptt_update_aux()
277 * Always commit the data to the AUX buffer in time to make sure in hisi_ptt_update_aux()
281 * there's enough room for the next trace. in hisi_ptt_update_aux()
287 return -EINVAL; in hisi_ptt_update_aux()
289 buf->pos = handle->head % buf->length; in hisi_ptt_update_aux()
290 if (buf->length - buf->pos < HISI_PTT_TRACE_BUF_SIZE) { in hisi_ptt_update_aux()
292 return -EINVAL; in hisi_ptt_update_aux()
304 status = readl(hisi_ptt->iobase + HISI_PTT_TRACE_INT_STAT); in hisi_ptt_isr()
308 buf_idx = ffs(status) - 1; in hisi_ptt_isr()
310 /* Clear the interrupt status of buffer @buf_idx */ in hisi_ptt_isr()
311 writel(status, hisi_ptt->iobase + HISI_PTT_TRACE_INT_STAT); in hisi_ptt_isr()
314 * Update the AUX buffer and cache the current buffer index, in hisi_ptt_isr()
315 * as we need to know this and save the data when the trace in hisi_ptt_isr()
316 * is ended out of the interrupt handler. End the trace in hisi_ptt_isr()
322 hisi_ptt->trace_ctrl.buf_index = (buf_idx + 1) % HISI_PTT_TRACE_BUF_CNT; in hisi_ptt_isr()
334 struct pci_dev *pdev = hisi_ptt->pdev; in hisi_ptt_register_irq()
343 ret = devm_add_action_or_reset(&pdev->dev, hisi_ptt_irq_free_vectors, pdev); in hisi_ptt_register_irq()
347 hisi_ptt->trace_irq = pci_irq_vector(pdev, HISI_PTT_TRACE_DMA_IRQ); in hisi_ptt_register_irq()
348 ret = devm_request_irq(&pdev->dev, hisi_ptt->trace_irq, hisi_ptt_isr, in hisi_ptt_register_irq()
353 hisi_ptt->trace_irq, ret); in hisi_ptt_register_irq()
363 if (filter->is_port) in hisi_ptt_del_free_filter()
364 hisi_ptt->port_mask &= ~hisi_ptt_get_filter_val(filter->devid, true); in hisi_ptt_del_free_filter()
366 list_del(&filter->list); in hisi_ptt_del_free_filter()
367 kfree(filter->name); in hisi_ptt_del_free_filter()
378 filter_name = kasprintf(GFP_KERNEL, "%04x:%02x:%02x.%d", pci_domain_nr(hisi_ptt->pdev->bus), in hisi_ptt_alloc_add_filter()
381 pci_err(hisi_ptt->pdev, "failed to allocate name for filter %04x:%02x:%02x.%d\n", in hisi_ptt_alloc_add_filter()
382 pci_domain_nr(hisi_ptt->pdev->bus), PCI_BUS_NUM(devid), in hisi_ptt_alloc_add_filter()
389 pci_err(hisi_ptt->pdev, "failed to add filter for %s\n", in hisi_ptt_alloc_add_filter()
395 filter->name = filter_name; in hisi_ptt_alloc_add_filter()
396 filter->is_port = is_port; in hisi_ptt_alloc_add_filter()
397 filter->devid = devid; in hisi_ptt_alloc_add_filter()
399 if (filter->is_port) { in hisi_ptt_alloc_add_filter()
400 list_add_tail(&filter->list, &hisi_ptt->port_filters); in hisi_ptt_alloc_add_filter()
403 hisi_ptt->port_mask |= hisi_ptt_get_filter_val(filter->devid, true); in hisi_ptt_alloc_add_filter()
405 list_add_tail(&filter->list, &hisi_ptt->req_filters); in hisi_ptt_alloc_add_filter()
418 filter_val = hisi_ptt_get_filter_val(filter->devid, filter->is_port) | in hisi_ptt_filter_show()
419 (filter->is_port ? HISI_PTT_PMU_FILTER_IS_PORT : 0); in hisi_ptt_filter_show()
427 struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj; in hisi_ptt_create_rp_filter_attr()
429 sysfs_attr_init(&filter->attr.attr); in hisi_ptt_create_rp_filter_attr()
430 filter->attr.attr.name = filter->name; in hisi_ptt_create_rp_filter_attr()
431 filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */ in hisi_ptt_create_rp_filter_attr()
432 filter->attr.show = hisi_ptt_filter_show; in hisi_ptt_create_rp_filter_attr()
434 return sysfs_add_file_to_group(kobj, &filter->attr.attr, in hisi_ptt_create_rp_filter_attr()
441 struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj; in hisi_ptt_remove_rp_filter_attr()
443 sysfs_remove_file_from_group(kobj, &filter->attr.attr, in hisi_ptt_remove_rp_filter_attr()
450 struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj; in hisi_ptt_create_req_filter_attr()
452 sysfs_attr_init(&filter->attr.attr); in hisi_ptt_create_req_filter_attr()
453 filter->attr.attr.name = filter->name; in hisi_ptt_create_req_filter_attr()
454 filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */ in hisi_ptt_create_req_filter_attr()
455 filter->attr.show = hisi_ptt_filter_show; in hisi_ptt_create_req_filter_attr()
457 return sysfs_add_file_to_group(kobj, &filter->attr.attr, in hisi_ptt_create_req_filter_attr()
464 struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj; in hisi_ptt_remove_req_filter_attr()
466 sysfs_remove_file_from_group(kobj, &filter->attr.attr, in hisi_ptt_remove_req_filter_attr()
475 if (filter->is_port) in hisi_ptt_create_filter_attr()
481 pci_err(hisi_ptt->pdev, "failed to create sysfs attribute for filter %s\n", in hisi_ptt_create_filter_attr()
482 filter->name); in hisi_ptt_create_filter_attr()
490 if (filter->is_port) in hisi_ptt_remove_filter_attr()
501 mutex_lock(&hisi_ptt->filter_lock); in hisi_ptt_remove_all_filter_attributes()
503 list_for_each_entry(filter, &hisi_ptt->req_filters, list) in hisi_ptt_remove_all_filter_attributes()
506 list_for_each_entry(filter, &hisi_ptt->port_filters, list) in hisi_ptt_remove_all_filter_attributes()
509 hisi_ptt->sysfs_inited = false; in hisi_ptt_remove_all_filter_attributes()
510 mutex_unlock(&hisi_ptt->filter_lock); in hisi_ptt_remove_all_filter_attributes()
518 mutex_lock(&hisi_ptt->filter_lock); in hisi_ptt_init_filter_attributes()
525 ret = devm_add_action(&hisi_ptt->pdev->dev, in hisi_ptt_init_filter_attributes()
531 list_for_each_entry(filter, &hisi_ptt->port_filters, list) { in hisi_ptt_init_filter_attributes()
537 list_for_each_entry(filter, &hisi_ptt->req_filters, list) { in hisi_ptt_init_filter_attributes()
543 hisi_ptt->sysfs_inited = true; in hisi_ptt_init_filter_attributes()
545 mutex_unlock(&hisi_ptt->filter_lock); in hisi_ptt_init_filter_attributes()
558 if (!mutex_trylock(&hisi_ptt->filter_lock)) { in hisi_ptt_update_filters()
559 schedule_delayed_work(&hisi_ptt->work, HISI_PTT_WORK_DELAY_MS); in hisi_ptt_update_filters()
563 while (kfifo_get(&hisi_ptt->filter_update_kfifo, &info)) { in hisi_ptt_update_filters()
580 if (hisi_ptt->sysfs_inited && in hisi_ptt_update_filters()
589 target_list = info.is_port ? &hisi_ptt->port_filters : in hisi_ptt_update_filters()
590 &hisi_ptt->req_filters; in hisi_ptt_update_filters()
593 if (filter->devid == info.devid) { in hisi_ptt_update_filters()
594 if (hisi_ptt->sysfs_inited) in hisi_ptt_update_filters()
603 mutex_unlock(&hisi_ptt->filter_lock); in hisi_ptt_update_filters()
625 if (port_devid < hisi_ptt->lower_bdf || in hisi_ptt_notifier_call()
626 port_devid > hisi_ptt->upper_bdf) in hisi_ptt_notifier_call()
649 if (kfifo_in_spinlocked(&hisi_ptt->filter_update_kfifo, &info, 1, in hisi_ptt_notifier_call()
650 &hisi_ptt->filter_update_lock)) in hisi_ptt_notifier_call()
651 schedule_delayed_work(&hisi_ptt->work, 0); in hisi_ptt_notifier_call()
653 pci_warn(hisi_ptt->pdev, in hisi_ptt_notifier_call()
671 if (port_devid < hisi_ptt->lower_bdf || in hisi_ptt_init_filters()
672 port_devid > hisi_ptt->upper_bdf) in hisi_ptt_init_filters()
683 return -ENOMEM; in hisi_ptt_init_filters()
693 list_for_each_entry_safe(filter, tmp, &hisi_ptt->req_filters, list) in hisi_ptt_release_filters()
696 list_for_each_entry_safe(filter, tmp, &hisi_ptt->port_filters, list) in hisi_ptt_release_filters()
702 struct hisi_ptt_trace_ctrl *ctrl = &hisi_ptt->trace_ctrl; in hisi_ptt_config_trace_buf()
703 struct device *dev = &hisi_ptt->pdev->dev; in hisi_ptt_config_trace_buf()
706 ctrl->trace_buf = devm_kcalloc(dev, HISI_PTT_TRACE_BUF_CNT, in hisi_ptt_config_trace_buf()
707 sizeof(*ctrl->trace_buf), GFP_KERNEL); in hisi_ptt_config_trace_buf()
708 if (!ctrl->trace_buf) in hisi_ptt_config_trace_buf()
709 return -ENOMEM; in hisi_ptt_config_trace_buf()
712 ctrl->trace_buf[i].addr = dmam_alloc_coherent(dev, HISI_PTT_TRACE_BUF_SIZE, in hisi_ptt_config_trace_buf()
713 &ctrl->trace_buf[i].dma, in hisi_ptt_config_trace_buf()
715 if (!ctrl->trace_buf[i].addr) in hisi_ptt_config_trace_buf()
716 return -ENOMEM; in hisi_ptt_config_trace_buf()
719 /* Configure the trace DMA buffer */ in hisi_ptt_config_trace_buf()
721 writel(lower_32_bits(ctrl->trace_buf[i].dma), in hisi_ptt_config_trace_buf()
722 hisi_ptt->iobase + HISI_PTT_TRACE_ADDR_BASE_LO_0 + in hisi_ptt_config_trace_buf()
724 writel(upper_32_bits(ctrl->trace_buf[i].dma), in hisi_ptt_config_trace_buf()
725 hisi_ptt->iobase + HISI_PTT_TRACE_ADDR_BASE_HI_0 + in hisi_ptt_config_trace_buf()
728 writel(HISI_PTT_TRACE_BUF_SIZE, hisi_ptt->iobase + HISI_PTT_TRACE_ADDR_SIZE); in hisi_ptt_config_trace_buf()
735 struct pci_dev *pdev = hisi_ptt->pdev; in hisi_ptt_init_ctrls()
740 INIT_DELAYED_WORK(&hisi_ptt->work, hisi_ptt_update_filters); in hisi_ptt_init_ctrls()
741 INIT_KFIFO(hisi_ptt->filter_update_kfifo); in hisi_ptt_init_ctrls()
742 spin_lock_init(&hisi_ptt->filter_update_lock); in hisi_ptt_init_ctrls()
744 INIT_LIST_HEAD(&hisi_ptt->port_filters); in hisi_ptt_init_ctrls()
745 INIT_LIST_HEAD(&hisi_ptt->req_filters); in hisi_ptt_init_ctrls()
746 mutex_init(&hisi_ptt->filter_lock); in hisi_ptt_init_ctrls()
754 * ports which the RCiEP can control and trace. The RCiEP and the root in hisi_ptt_init_ctrls()
761 reg = readl(hisi_ptt->iobase + HISI_PTT_DEVICE_RANGE); in hisi_ptt_init_ctrls()
762 hisi_ptt->upper_bdf = FIELD_GET(HISI_PTT_DEVICE_RANGE_UPPER, reg); in hisi_ptt_init_ctrls()
763 hisi_ptt->lower_bdf = FIELD_GET(HISI_PTT_DEVICE_RANGE_LOWER, reg); in hisi_ptt_init_ctrls()
765 bus = pci_find_bus(pci_domain_nr(pdev->bus), PCI_BUS_NUM(hisi_ptt->upper_bdf)); in hisi_ptt_init_ctrls()
769 ret = devm_add_action_or_reset(&pdev->dev, hisi_ptt_release_filters, hisi_ptt); in hisi_ptt_init_ctrls()
773 hisi_ptt->trace_ctrl.on_cpu = -1; in hisi_ptt_init_ctrls()
781 const cpumask_t *cpumask = cpumask_of_node(dev_to_node(&hisi_ptt->pdev->dev)); in cpumask_show()
800 * of the desired PCIe function. Bit[18:16] is reserved for extension.
804 PMU_FORMAT_ATTR(filter, "config:0-19");
805 PMU_FORMAT_ATTR(direction, "config:20-23");
806 PMU_FORMAT_ATTR(type, "config:24-31");
807 PMU_FORMAT_ATTR(format, "config:32-35");
829 return sysfs_emit(buf, "%s\n", (char *)ext_attr->var); in hisi_ptt_filter_multiselect_show()
897 return -EINVAL; in hisi_ptt_trace_valid_direction()
905 2, /* non-posted_request */ in hisi_ptt_trace_valid_type()
911 return -EINVAL; in hisi_ptt_trace_valid_type()
922 return -EINVAL; in hisi_ptt_trace_valid_type()
940 return -EINVAL; in hisi_ptt_trace_valid_format()
945 unsigned long val, port_mask = hisi_ptt->port_mask; in hisi_ptt_trace_valid_filter()
949 hisi_ptt->trace_ctrl.is_port = FIELD_GET(HISI_PTT_PMU_FILTER_IS_PORT, config); in hisi_ptt_trace_valid_filter()
954 * the bits in the @val are within the range of hisi_ptt->port_mask in hisi_ptt_trace_valid_filter()
961 mutex_lock(&hisi_ptt->filter_lock); in hisi_ptt_trace_valid_filter()
962 if (!hisi_ptt->trace_ctrl.is_port) { in hisi_ptt_trace_valid_filter()
963 list_for_each_entry(filter, &hisi_ptt->req_filters, list) { in hisi_ptt_trace_valid_filter()
964 if (val == hisi_ptt_get_filter_val(filter->devid, filter->is_port)) in hisi_ptt_trace_valid_filter()
971 ret = -EINVAL; in hisi_ptt_trace_valid_filter()
973 mutex_unlock(&hisi_ptt->filter_lock); in hisi_ptt_trace_valid_filter()
979 struct hisi_ptt_trace_ctrl *ctrl = &hisi_ptt->trace_ctrl; in hisi_ptt_pmu_init_configs()
982 val = FIELD_GET(HISI_PTT_PMU_FILTER_VAL_MASK, event->attr.config); in hisi_ptt_pmu_init_configs()
983 hisi_ptt->trace_ctrl.filter = val; in hisi_ptt_pmu_init_configs()
985 val = FIELD_GET(HISI_PTT_PMU_DIRECTION_MASK, event->attr.config); in hisi_ptt_pmu_init_configs()
986 ctrl->direction = val; in hisi_ptt_pmu_init_configs()
988 val = FIELD_GET(HISI_PTT_PMU_TYPE_MASK, event->attr.config); in hisi_ptt_pmu_init_configs()
989 ctrl->type = val; in hisi_ptt_pmu_init_configs()
991 val = FIELD_GET(HISI_PTT_PMU_FORMAT_MASK, event->attr.config); in hisi_ptt_pmu_init_configs()
992 ctrl->format = val; in hisi_ptt_pmu_init_configs()
997 struct hisi_ptt *hisi_ptt = to_hisi_ptt(event->pmu); in hisi_ptt_pmu_event_init()
1001 if (event->attr.type != hisi_ptt->hisi_ptt_pmu.type) in hisi_ptt_pmu_event_init()
1002 return -ENOENT; in hisi_ptt_pmu_event_init()
1004 if (event->cpu < 0) { in hisi_ptt_pmu_event_init()
1005 dev_dbg(event->pmu->dev, "Per-task mode not supported\n"); in hisi_ptt_pmu_event_init()
1006 return -EOPNOTSUPP; in hisi_ptt_pmu_event_init()
1009 if (event->attach_state & PERF_ATTACH_TASK) in hisi_ptt_pmu_event_init()
1010 return -EOPNOTSUPP; in hisi_ptt_pmu_event_init()
1012 ret = hisi_ptt_trace_valid_filter(hisi_ptt, event->attr.config); in hisi_ptt_pmu_event_init()
1016 val = FIELD_GET(HISI_PTT_PMU_DIRECTION_MASK, event->attr.config); in hisi_ptt_pmu_event_init()
1021 val = FIELD_GET(HISI_PTT_PMU_TYPE_MASK, event->attr.config); in hisi_ptt_pmu_event_init()
1026 val = FIELD_GET(HISI_PTT_PMU_FORMAT_MASK, event->attr.config); in hisi_ptt_pmu_event_init()
1038 dev_warn(event->pmu->dev, "Overwrite mode is not supported\n"); in hisi_ptt_pmu_setup_aux()
1042 /* If the pages size less than buffers, we cannot start trace */ in hisi_ptt_pmu_setup_aux()
1057 buf->base = vmap(pagelist, nr_pages, VM_MAP, PAGE_KERNEL); in hisi_ptt_pmu_setup_aux()
1058 if (!buf->base) { in hisi_ptt_pmu_setup_aux()
1063 buf->nr_pages = nr_pages; in hisi_ptt_pmu_setup_aux()
1064 buf->length = nr_pages * PAGE_SIZE; in hisi_ptt_pmu_setup_aux()
1065 buf->pos = 0; in hisi_ptt_pmu_setup_aux()
1078 vunmap(buf->base); in hisi_ptt_pmu_free_aux()
1084 struct hisi_ptt *hisi_ptt = to_hisi_ptt(event->pmu); in hisi_ptt_pmu_start()
1085 struct perf_output_handle *handle = &hisi_ptt->trace_ctrl.handle; in hisi_ptt_pmu_start()
1086 struct hw_perf_event *hwc = &event->hw; in hisi_ptt_pmu_start()
1087 struct device *dev = event->pmu->dev; in hisi_ptt_pmu_start()
1089 int cpu = event->cpu; in hisi_ptt_pmu_start()
1092 hwc->state = 0; in hisi_ptt_pmu_start()
1095 spin_lock(&hisi_ptt->pmu_lock); in hisi_ptt_pmu_start()
1096 if (hisi_ptt->trace_ctrl.started) { in hisi_ptt_pmu_start()
1097 dev_dbg(dev, "trace has already started\n"); in hisi_ptt_pmu_start()
1102 * Handle the interrupt on the same cpu which starts the trace to avoid in hisi_ptt_pmu_start()
1107 ret = irq_set_affinity(hisi_ptt->trace_irq, cpumask_of(cpu)); in hisi_ptt_pmu_start()
1109 dev_warn(dev, "failed to set the affinity of trace interrupt\n"); in hisi_ptt_pmu_start()
1111 hisi_ptt->trace_ctrl.on_cpu = cpu; in hisi_ptt_pmu_start()
1119 buf->pos = handle->head % buf->length; in hisi_ptt_pmu_start()
1125 dev_dbg(dev, "trace start failed, ret = %d\n", ret); in hisi_ptt_pmu_start()
1130 spin_unlock(&hisi_ptt->pmu_lock); in hisi_ptt_pmu_start()
1133 event->hw.state |= PERF_HES_STOPPED; in hisi_ptt_pmu_start()
1134 spin_unlock(&hisi_ptt->pmu_lock); in hisi_ptt_pmu_start()
1139 struct hisi_ptt *hisi_ptt = to_hisi_ptt(event->pmu); in hisi_ptt_pmu_stop()
1140 struct hw_perf_event *hwc = &event->hw; in hisi_ptt_pmu_stop()
1142 if (hwc->state & PERF_HES_STOPPED) in hisi_ptt_pmu_stop()
1145 spin_lock(&hisi_ptt->pmu_lock); in hisi_ptt_pmu_stop()
1146 if (hisi_ptt->trace_ctrl.started) { in hisi_ptt_pmu_stop()
1150 dev_warn(event->pmu->dev, "Device is still busy\n"); in hisi_ptt_pmu_stop()
1152 hisi_ptt_update_aux(hisi_ptt, hisi_ptt->trace_ctrl.buf_index, true); in hisi_ptt_pmu_stop()
1154 spin_unlock(&hisi_ptt->pmu_lock); in hisi_ptt_pmu_stop()
1156 hwc->state |= PERF_HES_STOPPED; in hisi_ptt_pmu_stop()
1158 hwc->state |= PERF_HES_UPTODATE; in hisi_ptt_pmu_stop()
1163 struct hisi_ptt *hisi_ptt = to_hisi_ptt(event->pmu); in hisi_ptt_pmu_add()
1164 struct hw_perf_event *hwc = &event->hw; in hisi_ptt_pmu_add()
1165 int cpu = event->cpu; in hisi_ptt_pmu_add()
1168 if (!cpumask_test_cpu(cpu, cpumask_of_node(dev_to_node(&hisi_ptt->pdev->dev)))) in hisi_ptt_pmu_add()
1171 hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; in hisi_ptt_pmu_add()
1175 if (hwc->state & PERF_HES_STOPPED) in hisi_ptt_pmu_add()
1176 return -EINVAL; in hisi_ptt_pmu_add()
1209 &hisi_ptt->hotplug_node); in hisi_ptt_register_pmu()
1213 ret = devm_add_action_or_reset(&hisi_ptt->pdev->dev, in hisi_ptt_register_pmu()
1215 &hisi_ptt->hotplug_node); in hisi_ptt_register_pmu()
1219 mutex_init(&hisi_ptt->tune_lock); in hisi_ptt_register_pmu()
1220 spin_lock_init(&hisi_ptt->pmu_lock); in hisi_ptt_register_pmu()
1222 hisi_ptt->hisi_ptt_pmu = (struct pmu) { in hisi_ptt_register_pmu()
1224 .parent = &hisi_ptt->pdev->dev, in hisi_ptt_register_pmu()
1238 reg = readl(hisi_ptt->iobase + HISI_PTT_LOCATION); in hisi_ptt_register_pmu()
1242 pmu_name = devm_kasprintf(&hisi_ptt->pdev->dev, GFP_KERNEL, "hisi_ptt%u_%u", in hisi_ptt_register_pmu()
1245 return -ENOMEM; in hisi_ptt_register_pmu()
1247 ret = perf_pmu_register(&hisi_ptt->hisi_ptt_pmu, pmu_name, -1); in hisi_ptt_register_pmu()
1251 return devm_add_action_or_reset(&hisi_ptt->pdev->dev, in hisi_ptt_register_pmu()
1253 &hisi_ptt->hisi_ptt_pmu); in hisi_ptt_register_pmu()
1260 bus_unregister_notifier(&pci_bus_type, &hisi_ptt->hisi_ptt_nb); in hisi_ptt_unregister_filter_update_notifier()
1263 cancel_delayed_work_sync(&hisi_ptt->work); in hisi_ptt_unregister_filter_update_notifier()
1271 hisi_ptt->hisi_ptt_nb.notifier_call = hisi_ptt_notifier_call; in hisi_ptt_register_filter_update_notifier()
1272 ret = bus_register_notifier(&pci_bus_type, &hisi_ptt->hisi_ptt_nb); in hisi_ptt_register_filter_update_notifier()
1276 return devm_add_action_or_reset(&hisi_ptt->pdev->dev, in hisi_ptt_register_filter_update_notifier()
1282 * The DMA of PTT trace can only use direct mappings due to some
1284 * policy of the IOMMU domain is passthrough, otherwise the trace
1294 iommu_domain = iommu_get_domain_for_dev(&pdev->dev); in hisi_ptt_check_iommu_mapping()
1295 if (!iommu_domain || iommu_domain->type == IOMMU_DOMAIN_IDENTITY) in hisi_ptt_check_iommu_mapping()
1298 return -EOPNOTSUPP; in hisi_ptt_check_iommu_mapping()
1313 hisi_ptt = devm_kzalloc(&pdev->dev, sizeof(*hisi_ptt), GFP_KERNEL); in hisi_ptt_probe()
1315 return -ENOMEM; in hisi_ptt_probe()
1317 hisi_ptt->pdev = pdev; in hisi_ptt_probe()
1332 hisi_ptt->iobase = pcim_iomap_table(pdev)[2]; in hisi_ptt_probe()
1334 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); in hisi_ptt_probe()
1390 src = hisi_ptt->trace_ctrl.on_cpu; in hisi_ptt_cpu_teardown()
1391 dev = hisi_ptt->hisi_ptt_pmu.dev; in hisi_ptt_cpu_teardown()
1393 if (!hisi_ptt->trace_ctrl.started || src != cpu) in hisi_ptt_cpu_teardown()
1396 target = cpumask_any_but(cpumask_of_node(dev_to_node(&hisi_ptt->pdev->dev)), cpu); in hisi_ptt_cpu_teardown()
1402 perf_pmu_migrate_context(&hisi_ptt->hisi_ptt_pmu, src, target); in hisi_ptt_cpu_teardown()
1408 if (irq_set_affinity(hisi_ptt->trace_irq, cpumask_of(target))) in hisi_ptt_cpu_teardown()
1409 dev_warn(dev, "failed to set the affinity of trace interrupt\n"); in hisi_ptt_cpu_teardown()
1411 hisi_ptt->trace_ctrl.on_cpu = target; in hisi_ptt_cpu_teardown()
1442 MODULE_DESCRIPTION("Driver for HiSilicon PCIe tune and trace device");