1*4418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
2*4418919fSjohnjiang  * Copyright(C) 2019 Marvell International Ltd.
3*4418919fSjohnjiang  */
4*4418919fSjohnjiang 
5*4418919fSjohnjiang #include <rte_malloc.h>
6*4418919fSjohnjiang 
7*4418919fSjohnjiang #include "nitrox_device.h"
8*4418919fSjohnjiang #include "nitrox_hal.h"
9*4418919fSjohnjiang #include "nitrox_sym.h"
10*4418919fSjohnjiang 
11*4418919fSjohnjiang #define PCI_VENDOR_ID_CAVIUM	0x177d
12*4418919fSjohnjiang #define NITROX_V_PCI_VF_DEV_ID	0x13
13*4418919fSjohnjiang 
14*4418919fSjohnjiang TAILQ_HEAD(ndev_list, nitrox_device);
15*4418919fSjohnjiang static struct ndev_list ndev_list = TAILQ_HEAD_INITIALIZER(ndev_list);
16*4418919fSjohnjiang 
17*4418919fSjohnjiang static struct nitrox_device *
ndev_allocate(struct rte_pci_device * pdev)18*4418919fSjohnjiang ndev_allocate(struct rte_pci_device *pdev)
19*4418919fSjohnjiang {
20*4418919fSjohnjiang 	struct nitrox_device *ndev;
21*4418919fSjohnjiang 
22*4418919fSjohnjiang 	ndev = rte_zmalloc_socket("nitrox device", sizeof(*ndev),
23*4418919fSjohnjiang 				   RTE_CACHE_LINE_SIZE,
24*4418919fSjohnjiang 				   pdev->device.numa_node);
25*4418919fSjohnjiang 	if (!ndev)
26*4418919fSjohnjiang 		return NULL;
27*4418919fSjohnjiang 
28*4418919fSjohnjiang 	TAILQ_INSERT_TAIL(&ndev_list, ndev, next);
29*4418919fSjohnjiang 	return ndev;
30*4418919fSjohnjiang }
31*4418919fSjohnjiang 
32*4418919fSjohnjiang static void
ndev_init(struct nitrox_device * ndev,struct rte_pci_device * pdev)33*4418919fSjohnjiang ndev_init(struct nitrox_device *ndev, struct rte_pci_device *pdev)
34*4418919fSjohnjiang {
35*4418919fSjohnjiang 	enum nitrox_vf_mode vf_mode;
36*4418919fSjohnjiang 
37*4418919fSjohnjiang 	ndev->pdev = pdev;
38*4418919fSjohnjiang 	ndev->bar_addr = pdev->mem_resource[0].addr;
39*4418919fSjohnjiang 	vf_mode = vf_get_vf_config_mode(ndev->bar_addr);
40*4418919fSjohnjiang 	ndev->nr_queues = vf_config_mode_to_nr_queues(vf_mode);
41*4418919fSjohnjiang }
42*4418919fSjohnjiang 
43*4418919fSjohnjiang static struct nitrox_device *
find_ndev(struct rte_pci_device * pdev)44*4418919fSjohnjiang find_ndev(struct rte_pci_device *pdev)
45*4418919fSjohnjiang {
46*4418919fSjohnjiang 	struct nitrox_device *ndev;
47*4418919fSjohnjiang 
48*4418919fSjohnjiang 	TAILQ_FOREACH(ndev, &ndev_list, next)
49*4418919fSjohnjiang 		if (ndev->pdev == pdev)
50*4418919fSjohnjiang 			return ndev;
51*4418919fSjohnjiang 
52*4418919fSjohnjiang 	return NULL;
53*4418919fSjohnjiang }
54*4418919fSjohnjiang 
55*4418919fSjohnjiang static void
ndev_release(struct nitrox_device * ndev)56*4418919fSjohnjiang ndev_release(struct nitrox_device *ndev)
57*4418919fSjohnjiang {
58*4418919fSjohnjiang 	if (!ndev)
59*4418919fSjohnjiang 		return;
60*4418919fSjohnjiang 
61*4418919fSjohnjiang 	TAILQ_REMOVE(&ndev_list, ndev, next);
62*4418919fSjohnjiang 	rte_free(ndev);
63*4418919fSjohnjiang }
64*4418919fSjohnjiang 
65*4418919fSjohnjiang static int
nitrox_pci_probe(struct rte_pci_driver * pci_drv __rte_unused,struct rte_pci_device * pdev)66*4418919fSjohnjiang nitrox_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
67*4418919fSjohnjiang 		struct rte_pci_device *pdev)
68*4418919fSjohnjiang {
69*4418919fSjohnjiang 	struct nitrox_device *ndev;
70*4418919fSjohnjiang 	int err;
71*4418919fSjohnjiang 
72*4418919fSjohnjiang 	/* Nitrox CSR space */
73*4418919fSjohnjiang 	if (!pdev->mem_resource[0].addr)
74*4418919fSjohnjiang 		return -EINVAL;
75*4418919fSjohnjiang 
76*4418919fSjohnjiang 	ndev = ndev_allocate(pdev);
77*4418919fSjohnjiang 	if (!ndev)
78*4418919fSjohnjiang 		return -ENOMEM;
79*4418919fSjohnjiang 
80*4418919fSjohnjiang 	ndev_init(ndev, pdev);
81*4418919fSjohnjiang 	err = nitrox_sym_pmd_create(ndev);
82*4418919fSjohnjiang 	if (err) {
83*4418919fSjohnjiang 		ndev_release(ndev);
84*4418919fSjohnjiang 		return err;
85*4418919fSjohnjiang 	}
86*4418919fSjohnjiang 
87*4418919fSjohnjiang 	return 0;
88*4418919fSjohnjiang }
89*4418919fSjohnjiang 
90*4418919fSjohnjiang static int
nitrox_pci_remove(struct rte_pci_device * pdev)91*4418919fSjohnjiang nitrox_pci_remove(struct rte_pci_device *pdev)
92*4418919fSjohnjiang {
93*4418919fSjohnjiang 	struct nitrox_device *ndev;
94*4418919fSjohnjiang 	int err;
95*4418919fSjohnjiang 
96*4418919fSjohnjiang 	ndev = find_ndev(pdev);
97*4418919fSjohnjiang 	if (!ndev)
98*4418919fSjohnjiang 		return -ENODEV;
99*4418919fSjohnjiang 
100*4418919fSjohnjiang 	err = nitrox_sym_pmd_destroy(ndev);
101*4418919fSjohnjiang 	if (err)
102*4418919fSjohnjiang 		return err;
103*4418919fSjohnjiang 
104*4418919fSjohnjiang 	ndev_release(ndev);
105*4418919fSjohnjiang 	return 0;
106*4418919fSjohnjiang }
107*4418919fSjohnjiang 
108*4418919fSjohnjiang static struct rte_pci_id pci_id_nitrox_map[] = {
109*4418919fSjohnjiang 	{
110*4418919fSjohnjiang 		/* Nitrox 5 VF */
111*4418919fSjohnjiang 		RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, NITROX_V_PCI_VF_DEV_ID)
112*4418919fSjohnjiang 	},
113*4418919fSjohnjiang 	{.device_id = 0},
114*4418919fSjohnjiang };
115*4418919fSjohnjiang 
116*4418919fSjohnjiang static struct rte_pci_driver nitrox_pmd = {
117*4418919fSjohnjiang 	.id_table       = pci_id_nitrox_map,
118*4418919fSjohnjiang 	.drv_flags      = RTE_PCI_DRV_NEED_MAPPING,
119*4418919fSjohnjiang 	.probe          = nitrox_pci_probe,
120*4418919fSjohnjiang 	.remove         = nitrox_pci_remove,
121*4418919fSjohnjiang };
122*4418919fSjohnjiang 
123*4418919fSjohnjiang RTE_PMD_REGISTER_PCI(nitrox, nitrox_pmd);
124*4418919fSjohnjiang RTE_PMD_REGISTER_PCI_TABLE(nitrox, pci_id_nitrox_map);
125