net/cnxk: add platform specific probe and remove
[dpdk.git] / drivers / net / cnxk / cnxk_ethdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 #include <cnxk_ethdev.h>
5
6 static inline uint64_t
7 nix_get_rx_offload_capa(struct cnxk_eth_dev *dev)
8 {
9         uint64_t capa = CNXK_NIX_RX_OFFLOAD_CAPA;
10
11         if (roc_nix_is_vf_or_sdp(&dev->nix))
12                 capa &= ~DEV_RX_OFFLOAD_TIMESTAMP;
13
14         return capa;
15 }
16
17 static inline uint64_t
18 nix_get_tx_offload_capa(struct cnxk_eth_dev *dev)
19 {
20         RTE_SET_USED(dev);
21         return CNXK_NIX_TX_OFFLOAD_CAPA;
22 }
23
24 static inline uint32_t
25 nix_get_speed_capa(struct cnxk_eth_dev *dev)
26 {
27         uint32_t speed_capa;
28
29         /* Auto negotiation disabled */
30         speed_capa = ETH_LINK_SPEED_FIXED;
31         if (!roc_nix_is_vf_or_sdp(&dev->nix) && !roc_nix_is_lbk(&dev->nix)) {
32                 speed_capa |= ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
33                               ETH_LINK_SPEED_25G | ETH_LINK_SPEED_40G |
34                               ETH_LINK_SPEED_50G | ETH_LINK_SPEED_100G;
35         }
36
37         return speed_capa;
38 }
39
40 /* CNXK platform independent eth dev ops */
41 struct eth_dev_ops cnxk_eth_dev_ops;
42
43 static int
44 cnxk_eth_dev_init(struct rte_eth_dev *eth_dev)
45 {
46         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
47         struct roc_nix *nix = &dev->nix;
48         struct rte_pci_device *pci_dev;
49         int rc, max_entries;
50
51         eth_dev->dev_ops = &cnxk_eth_dev_ops;
52
53         /* For secondary processes, the primary has done all the work */
54         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
55                 return 0;
56
57         pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
58         rte_eth_copy_pci_info(eth_dev, pci_dev);
59
60         /* Initialize base roc nix */
61         nix->pci_dev = pci_dev;
62         rc = roc_nix_dev_init(nix);
63         if (rc) {
64                 plt_err("Failed to initialize roc nix rc=%d", rc);
65                 goto error;
66         }
67
68         dev->eth_dev = eth_dev;
69
70         /* For vfs, returned max_entries will be 0. but to keep default mac
71          * address, one entry must be allocated. so setting up to 1.
72          */
73         if (roc_nix_is_vf_or_sdp(nix))
74                 max_entries = 1;
75         else
76                 max_entries = roc_nix_mac_max_entries_get(nix);
77
78         if (max_entries <= 0) {
79                 plt_err("Failed to get max entries for mac addr");
80                 rc = -ENOTSUP;
81                 goto dev_fini;
82         }
83
84         eth_dev->data->mac_addrs =
85                 rte_zmalloc("mac_addr", max_entries * RTE_ETHER_ADDR_LEN, 0);
86         if (eth_dev->data->mac_addrs == NULL) {
87                 plt_err("Failed to allocate memory for mac addr");
88                 rc = -ENOMEM;
89                 goto dev_fini;
90         }
91
92         dev->max_mac_entries = max_entries;
93
94         /* Get mac address */
95         rc = roc_nix_npc_mac_addr_get(nix, dev->mac_addr);
96         if (rc) {
97                 plt_err("Failed to get mac addr, rc=%d", rc);
98                 goto free_mac_addrs;
99         }
100
101         /* Update the mac address */
102         memcpy(eth_dev->data->mac_addrs, dev->mac_addr, RTE_ETHER_ADDR_LEN);
103
104         if (!roc_nix_is_vf_or_sdp(nix)) {
105                 /* Sync same MAC address to CGX/RPM table */
106                 rc = roc_nix_mac_addr_set(nix, dev->mac_addr);
107                 if (rc) {
108                         plt_err("Failed to set mac addr, rc=%d", rc);
109                         goto free_mac_addrs;
110                 }
111         }
112
113         /* Union of all capabilities supported by CNXK.
114          * Platform specific capabilities will be
115          * updated later.
116          */
117         dev->rx_offload_capa = nix_get_rx_offload_capa(dev);
118         dev->tx_offload_capa = nix_get_tx_offload_capa(dev);
119         dev->speed_capa = nix_get_speed_capa(dev);
120
121         /* Initialize roc npc */
122         plt_nix_dbg("Port=%d pf=%d vf=%d ver=%s hwcap=0x%" PRIx64
123                     " rxoffload_capa=0x%" PRIx64 " txoffload_capa=0x%" PRIx64,
124                     eth_dev->data->port_id, roc_nix_get_pf(nix),
125                     roc_nix_get_vf(nix), CNXK_ETH_DEV_PMD_VERSION, dev->hwcap,
126                     dev->rx_offload_capa, dev->tx_offload_capa);
127         return 0;
128
129 free_mac_addrs:
130         rte_free(eth_dev->data->mac_addrs);
131 dev_fini:
132         roc_nix_dev_fini(nix);
133 error:
134         plt_err("Failed to init nix eth_dev rc=%d", rc);
135         return rc;
136 }
137
138 static int
139 cnxk_eth_dev_uninit(struct rte_eth_dev *eth_dev, bool mbox_close)
140 {
141         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
142         const struct eth_dev_ops *dev_ops = eth_dev->dev_ops;
143         struct roc_nix *nix = &dev->nix;
144         int rc, i;
145
146         /* Nothing to be done for secondary processes */
147         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
148                 return 0;
149
150         roc_nix_npc_rx_ena_dis(nix, false);
151
152         /* Free up SQs */
153         for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
154                 dev_ops->tx_queue_release(eth_dev->data->tx_queues[i]);
155                 eth_dev->data->tx_queues[i] = NULL;
156         }
157         eth_dev->data->nb_tx_queues = 0;
158
159         /* Free up RQ's and CQ's */
160         for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
161                 dev_ops->rx_queue_release(eth_dev->data->rx_queues[i]);
162                 eth_dev->data->rx_queues[i] = NULL;
163         }
164         eth_dev->data->nb_rx_queues = 0;
165
166         /* Free tm resources */
167         roc_nix_tm_fini(nix);
168
169         /* Unregister queue irqs */
170         roc_nix_unregister_queue_irqs(nix);
171
172         /* Unregister cq irqs */
173         if (eth_dev->data->dev_conf.intr_conf.rxq)
174                 roc_nix_unregister_cq_irqs(nix);
175
176         /* Free nix lf resources */
177         rc = roc_nix_lf_free(nix);
178         if (rc)
179                 plt_err("Failed to free nix lf, rc=%d", rc);
180
181         rte_free(eth_dev->data->mac_addrs);
182         eth_dev->data->mac_addrs = NULL;
183
184         /* Check if mbox close is needed */
185         if (!mbox_close)
186                 return 0;
187
188         rc = roc_nix_dev_fini(nix);
189         /* Can be freed later by PMD if NPA LF is in use */
190         if (rc == -EAGAIN) {
191                 eth_dev->data->dev_private = NULL;
192                 return 0;
193         } else if (rc) {
194                 plt_err("Failed in nix dev fini, rc=%d", rc);
195         }
196
197         return rc;
198 }
199
200 int
201 cnxk_nix_remove(struct rte_pci_device *pci_dev)
202 {
203         struct rte_eth_dev *eth_dev;
204         struct roc_nix *nix;
205         int rc = -EINVAL;
206
207         eth_dev = rte_eth_dev_allocated(pci_dev->device.name);
208         if (eth_dev) {
209                 /* Cleanup eth dev */
210                 rc = cnxk_eth_dev_uninit(eth_dev, true);
211                 if (rc)
212                         return rc;
213
214                 rte_eth_dev_release_port(eth_dev);
215         }
216
217         /* Nothing to be done for secondary processes */
218         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
219                 return 0;
220
221         /* Check if this device is hosting common resource */
222         nix = roc_idev_npa_nix_get();
223         if (nix->pci_dev != pci_dev)
224                 return 0;
225
226         /* Try nix fini now */
227         rc = roc_nix_dev_fini(nix);
228         if (rc == -EAGAIN) {
229                 plt_info("%s: common resource in use by other devices",
230                          pci_dev->name);
231                 goto exit;
232         } else if (rc) {
233                 plt_err("Failed in nix dev fini, rc=%d", rc);
234                 goto exit;
235         }
236
237         /* Free device pointer as rte_ethdev does not have it anymore */
238         rte_free(nix);
239 exit:
240         return rc;
241 }
242
243 int
244 cnxk_nix_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
245 {
246         int rc;
247
248         RTE_SET_USED(pci_drv);
249
250         rc = rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct cnxk_eth_dev),
251                                            cnxk_eth_dev_init);
252
253         /* On error on secondary, recheck if port exists in primary or
254          * in mid of detach state.
255          */
256         if (rte_eal_process_type() != RTE_PROC_PRIMARY && rc)
257                 if (!rte_eth_dev_allocated(pci_dev->device.name))
258                         return 0;
259         return rc;
260 }