mem: add dirty malloc element support
[dpdk.git] / drivers / raw / cnxk_bphy / cnxk_bphy.c
index 7e541ba..349d551 100644 (file)
@@ -22,10 +22,143 @@ static const struct rte_pci_id pci_bphy_map[] = {
        },
 };
 
+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);
 }
@@ -37,8 +170,13 @@ cnxk_bphy_irq_enqueue_bufs(struct rte_rawdev *dev,
 {
        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;
@@ -47,11 +185,62 @@ cnxk_bphy_irq_enqueue_bufs(struct rte_rawdev *dev,
                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
@@ -61,6 +250,7 @@ cnxk_bphy_irq_dequeue_bufs(struct rte_rawdev *dev,
 {
        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;
@@ -68,7 +258,13 @@ cnxk_bphy_irq_dequeue_bufs(struct rte_rawdev *dev,
        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;
 }
@@ -102,6 +298,7 @@ static const struct rte_rawdev_ops bphy_rawdev_ops = {
        .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
@@ -144,6 +341,13 @@ bphy_rawdev_probe(struct rte_pci_driver *pci_drv,
        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;
 }
@@ -152,6 +356,7 @@ static int
 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)
@@ -162,13 +367,15 @@ bphy_rawdev_remove(struct rte_pci_device *pci_dev)
                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);
 }