},
};
+struct bphy_test {
+ int irq_num;
+ cnxk_bphy_intr_handler_t handler;
+ void *data;
+ int cpu;
+ bool handled_intr;
+ int handled_data;
+ int test_data;
+};
+
+static struct bphy_test *test;
+
+static void
+bphy_test_handler_fn(int irq_num, void *isr_data)
+{
+ test[irq_num].handled_intr = true;
+ test[irq_num].handled_data = *((int *)isr_data);
+}
+
+static int
+bphy_rawdev_selftest(uint16_t dev_id)
+{
+ unsigned int i, queues, descs;
+ uint16_t pf_func;
+ uint64_t max_irq;
+ int ret;
+
+ queues = rte_rawdev_queue_count(dev_id);
+ if (queues == 0)
+ return -ENODEV;
+ if (queues != BPHY_QUEUE_CNT)
+ return -EINVAL;
+
+ ret = rte_rawdev_start(dev_id);
+ if (ret)
+ return ret;
+
+ ret = rte_rawdev_queue_conf_get(dev_id, CNXK_BPHY_DEF_QUEUE, &descs,
+ sizeof(descs));
+ if (ret)
+ goto err_desc;
+ if (descs != 1) {
+ ret = -ENODEV;
+ plt_err("Wrong number of descs reported\n");
+ goto err_desc;
+ }
+
+ ret = rte_pmd_bphy_npa_pf_func_get(dev_id, &pf_func);
+ if (ret || pf_func == 0)
+ plt_warn("NPA pf_func is invalid");
+
+ ret = rte_pmd_bphy_sso_pf_func_get(dev_id, &pf_func);
+ if (ret || pf_func == 0)
+ plt_warn("SSO pf_func is invalid");
+
+ ret = rte_pmd_bphy_intr_init(dev_id);
+ if (ret) {
+ plt_err("intr init failed");
+ return ret;
+ }
+
+ max_irq = cnxk_bphy_irq_max_get(dev_id);
+
+ test = rte_zmalloc("BPHY", max_irq * sizeof(*test), 0);
+ if (test == NULL) {
+ plt_err("intr alloc failed");
+ goto err_alloc;
+ }
+
+ for (i = 0; i < max_irq; i++) {
+ test[i].test_data = i;
+ test[i].irq_num = i;
+ test[i].handler = bphy_test_handler_fn;
+ test[i].data = &test[i].test_data;
+ }
+
+ for (i = 0; i < max_irq; i++) {
+ ret = rte_pmd_bphy_intr_register(dev_id, test[i].irq_num,
+ test[i].handler, test[i].data,
+ 0);
+ if (ret == -ENOTSUP) {
+ /* In the test we iterate over all irq numbers
+ * so if some of them are not supported by given
+ * platform we treat respective results as valid
+ * ones. This way they have no impact on overall
+ * test results.
+ */
+ test[i].handled_intr = true;
+ test[i].handled_data = test[i].test_data;
+ ret = 0;
+ continue;
+ }
+
+ if (ret) {
+ plt_err("intr register failed at irq %d", i);
+ goto err_register;
+ }
+ }
+
+ for (i = 0; i < max_irq; i++)
+ roc_bphy_intr_handler(i);
+
+ for (i = 0; i < max_irq; i++) {
+ if (!test[i].handled_intr) {
+ plt_err("intr %u not handled", i);
+ ret = -1;
+ break;
+ }
+ if (test[i].handled_data != test[i].test_data) {
+ plt_err("intr %u has wrong handler", i);
+ ret = -1;
+ break;
+ }
+ }
+
+err_register:
+ /*
+ * In case of registration failure the loop goes over all
+ * interrupts which is safe due to internal guards in
+ * rte_pmd_bphy_intr_unregister().
+ */
+ for (i = 0; i < max_irq; i++)
+ rte_pmd_bphy_intr_unregister(dev_id, i);
+
+ rte_free(test);
+err_alloc:
+ rte_pmd_bphy_intr_fini(dev_id);
+err_desc:
+ rte_rawdev_stop(dev_id);
+
+ return ret;
+}
+
static void
bphy_rawdev_get_name(char *name, struct rte_pci_device *pci_dev)
{
- snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "BPHY:%x:%02x.%x",
+ snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "BPHY:%02x:%02x.%x",
pci_dev->addr.bus, pci_dev->addr.devid,
pci_dev->addr.function);
}
{
struct bphy_device *bphy_dev = (struct bphy_device *)dev->dev_private;
struct cnxk_bphy_irq_msg *msg = buffers[0]->buf_addr;
+ struct bphy_irq_queue *qp = &bphy_dev->queues[0];
unsigned int queue = (size_t)context;
- int ret = 0;
+ struct cnxk_bphy_irq_info *info;
+ struct cnxk_bphy_mem *mem;
+ uint16_t *pf_func;
+ void *rsp = NULL;
+ int ret;
if (queue >= RTE_DIM(bphy_dev->queues))
return -EINVAL;
return 0;
switch (msg->type) {
+ case CNXK_BPHY_IRQ_MSG_TYPE_INIT:
+ ret = cnxk_bphy_intr_init(dev->dev_id);
+ if (ret)
+ return ret;
+ break;
+ case CNXK_BPHY_IRQ_MSG_TYPE_FINI:
+ cnxk_bphy_intr_fini(dev->dev_id);
+ break;
+ case CNXK_BPHY_IRQ_MSG_TYPE_REGISTER:
+ info = (struct cnxk_bphy_irq_info *)msg->data;
+ ret = cnxk_bphy_intr_register(dev->dev_id, info->irq_num,
+ info->handler, info->data,
+ info->cpu);
+ if (ret)
+ return ret;
+ break;
+ case CNXK_BPHY_IRQ_MSG_TYPE_UNREGISTER:
+ info = (struct cnxk_bphy_irq_info *)msg->data;
+ cnxk_bphy_intr_unregister(dev->dev_id, info->irq_num);
+ break;
+ case CNXK_BPHY_IRQ_MSG_TYPE_MEM_GET:
+ mem = rte_zmalloc(NULL, sizeof(*mem), 0);
+ if (!mem)
+ return -ENOMEM;
+
+ *mem = bphy_dev->mem;
+ rsp = mem;
+ break;
+ case CNXK_BPHY_MSG_TYPE_NPA_PF_FUNC:
+ pf_func = rte_malloc(NULL, sizeof(*pf_func), 0);
+ if (!pf_func)
+ return -ENOMEM;
+
+ *pf_func = roc_bphy_npa_pf_func_get();
+ rsp = pf_func;
+ break;
+ case CNXK_BPHY_MSG_TYPE_SSO_PF_FUNC:
+ pf_func = rte_malloc(NULL, sizeof(*pf_func), 0);
+ if (!pf_func)
+ return -ENOMEM;
+
+ *pf_func = roc_bphy_sso_pf_func_get();
+ rsp = pf_func;
+ break;
default:
- ret = -EINVAL;
+ return -EINVAL;
}
- return ret;
+ /* get rid of last response if any */
+ if (qp->rsp) {
+ RTE_LOG(WARNING, PMD, "Previous response got overwritten\n");
+ rte_free(qp->rsp);
+ }
+ qp->rsp = rsp;
+
+ return 1;
}
static int
{
struct bphy_device *bphy_dev = (struct bphy_device *)dev->dev_private;
unsigned int queue = (size_t)context;
+ struct bphy_irq_queue *qp;
if (queue >= RTE_DIM(bphy_dev->queues))
return -EINVAL;
if (count == 0)
return 0;
- buffers[0]->buf_addr = bphy_dev->queues[queue].rsp;
+ qp = &bphy_dev->queues[queue];
+ if (qp->rsp) {
+ buffers[0]->buf_addr = qp->rsp;
+ qp->rsp = NULL;
+
+ return 1;
+ }
return 0;
}
.enqueue_bufs = cnxk_bphy_irq_enqueue_bufs,
.dequeue_bufs = cnxk_bphy_irq_dequeue_bufs,
.queue_count = cnxk_bphy_irq_queue_count,
+ .dev_selftest = bphy_rawdev_selftest,
};
static int
bphy_dev = (struct bphy_device *)bphy_rawdev->dev_private;
bphy_dev->mem.res0 = pci_dev->mem_resource[0];
bphy_dev->mem.res2 = pci_dev->mem_resource[2];
+ bphy_dev->bphy.pci_dev = pci_dev;
+
+ ret = roc_bphy_dev_init(&bphy_dev->bphy);
+ if (ret) {
+ rte_rawdev_pmd_release(bphy_rawdev);
+ return ret;
+ }
return 0;
}
bphy_rawdev_remove(struct rte_pci_device *pci_dev)
{
char name[RTE_RAWDEV_NAME_MAX_LEN];
+ struct bphy_device *bphy_dev;
struct rte_rawdev *rawdev;
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return -EINVAL;
}
+ bphy_rawdev_get_name(name, pci_dev);
rawdev = rte_rawdev_pmd_get_named_dev(name);
if (rawdev == NULL) {
plt_err("invalid device name (%s)", name);
return -EINVAL;
}
- bphy_rawdev_get_name(name, pci_dev);
+ bphy_dev = (struct bphy_device *)rawdev->dev_private;
+ roc_bphy_dev_fini(&bphy_dev->bphy);
return rte_rawdev_pmd_release(rawdev);
}