xref: /dpdk/drivers/net/sfc/sfc_ethdev.c (revision 886f8d8a05bfda9ce8afb1c88c024838a3b3f04b)
1 /*-
2  * Copyright (c) 2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * This software was jointly developed between OKTET Labs (under contract
6  * for Solarflare) and Solarflare Communications, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <rte_dev.h>
31 #include <rte_ethdev.h>
32 #include <rte_pci.h>
33 
34 #include "efx.h"
35 
36 #include "sfc.h"
37 #include "sfc_debug.h"
38 #include "sfc_log.h"
39 #include "sfc_kvargs.h"
40 #include "sfc_ev.h"
41 
42 
43 static void
44 sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
45 {
46 	struct sfc_adapter *sa = dev->data->dev_private;
47 
48 	sfc_log_init(sa, "entry");
49 
50 	dev_info->pci_dev = RTE_DEV_TO_PCI(dev->device);
51 	dev_info->max_rx_pktlen = EFX_MAC_PDU_MAX;
52 }
53 
54 static int
55 sfc_dev_configure(struct rte_eth_dev *dev)
56 {
57 	struct rte_eth_dev_data *dev_data = dev->data;
58 	struct sfc_adapter *sa = dev_data->dev_private;
59 	int rc;
60 
61 	sfc_log_init(sa, "entry n_rxq=%u n_txq=%u",
62 		     dev_data->nb_rx_queues, dev_data->nb_tx_queues);
63 
64 	sfc_adapter_lock(sa);
65 	switch (sa->state) {
66 	case SFC_ADAPTER_CONFIGURED:
67 		sfc_close(sa);
68 		SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
69 		/* FALLTHROUGH */
70 	case SFC_ADAPTER_INITIALIZED:
71 		rc = sfc_configure(sa);
72 		break;
73 	default:
74 		sfc_err(sa, "unexpected adapter state %u to configure",
75 			sa->state);
76 		rc = EINVAL;
77 		break;
78 	}
79 	sfc_adapter_unlock(sa);
80 
81 	sfc_log_init(sa, "done %d", rc);
82 	SFC_ASSERT(rc >= 0);
83 	return -rc;
84 }
85 
86 static int
87 sfc_dev_start(struct rte_eth_dev *dev)
88 {
89 	struct sfc_adapter *sa = dev->data->dev_private;
90 	int rc;
91 
92 	sfc_log_init(sa, "entry");
93 
94 	sfc_adapter_lock(sa);
95 	rc = sfc_start(sa);
96 	sfc_adapter_unlock(sa);
97 
98 	sfc_log_init(sa, "done %d", rc);
99 	SFC_ASSERT(rc >= 0);
100 	return -rc;
101 }
102 
103 static int
104 sfc_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
105 {
106 	struct sfc_adapter *sa = dev->data->dev_private;
107 	struct rte_eth_link *dev_link = &dev->data->dev_link;
108 	struct rte_eth_link old_link;
109 	struct rte_eth_link current_link;
110 
111 	sfc_log_init(sa, "entry");
112 
113 	if (sa->state != SFC_ADAPTER_STARTED)
114 		return 0;
115 
116 retry:
117 	EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
118 	*(int64_t *)&old_link = rte_atomic64_read((rte_atomic64_t *)dev_link);
119 
120 	if (wait_to_complete) {
121 		efx_link_mode_t link_mode;
122 
123 		efx_port_poll(sa->nic, &link_mode);
124 		sfc_port_link_mode_to_info(link_mode, &current_link);
125 
126 		if (!rte_atomic64_cmpset((volatile uint64_t *)dev_link,
127 					 *(uint64_t *)&old_link,
128 					 *(uint64_t *)&current_link))
129 			goto retry;
130 	} else {
131 		sfc_ev_mgmt_qpoll(sa);
132 		*(int64_t *)&current_link =
133 			rte_atomic64_read((rte_atomic64_t *)dev_link);
134 	}
135 
136 	if (old_link.link_status != current_link.link_status)
137 		sfc_info(sa, "Link status is %s",
138 			 current_link.link_status ? "UP" : "DOWN");
139 
140 	return old_link.link_status == current_link.link_status ? 0 : -1;
141 }
142 
143 static void
144 sfc_dev_stop(struct rte_eth_dev *dev)
145 {
146 	struct sfc_adapter *sa = dev->data->dev_private;
147 
148 	sfc_log_init(sa, "entry");
149 
150 	sfc_adapter_lock(sa);
151 	sfc_stop(sa);
152 	sfc_adapter_unlock(sa);
153 
154 	sfc_log_init(sa, "done");
155 }
156 
157 static void
158 sfc_dev_close(struct rte_eth_dev *dev)
159 {
160 	struct sfc_adapter *sa = dev->data->dev_private;
161 
162 	sfc_log_init(sa, "entry");
163 
164 	sfc_adapter_lock(sa);
165 	switch (sa->state) {
166 	case SFC_ADAPTER_STARTED:
167 		sfc_stop(sa);
168 		SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED);
169 		/* FALLTHROUGH */
170 	case SFC_ADAPTER_CONFIGURED:
171 		sfc_close(sa);
172 		SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
173 		/* FALLTHROUGH */
174 	case SFC_ADAPTER_INITIALIZED:
175 		break;
176 	default:
177 		sfc_err(sa, "unexpected adapter state %u on close", sa->state);
178 		break;
179 	}
180 	sfc_adapter_unlock(sa);
181 
182 	sfc_log_init(sa, "done");
183 }
184 
185 static const struct eth_dev_ops sfc_eth_dev_ops = {
186 	.dev_configure			= sfc_dev_configure,
187 	.dev_start			= sfc_dev_start,
188 	.dev_stop			= sfc_dev_stop,
189 	.dev_close			= sfc_dev_close,
190 	.link_update			= sfc_dev_link_update,
191 	.dev_infos_get			= sfc_dev_infos_get,
192 };
193 
194 static int
195 sfc_eth_dev_init(struct rte_eth_dev *dev)
196 {
197 	struct sfc_adapter *sa = dev->data->dev_private;
198 	struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(dev);
199 	int rc;
200 	const efx_nic_cfg_t *encp;
201 	const struct ether_addr *from;
202 
203 	/* Required for logging */
204 	sa->eth_dev = dev;
205 
206 	/* Copy PCI device info to the dev->data */
207 	rte_eth_copy_pci_info(dev, pci_dev);
208 
209 	rc = sfc_kvargs_parse(sa);
210 	if (rc != 0)
211 		goto fail_kvargs_parse;
212 
213 	rc = sfc_kvargs_process(sa, SFC_KVARG_DEBUG_INIT,
214 				sfc_kvarg_bool_handler, &sa->debug_init);
215 	if (rc != 0)
216 		goto fail_kvarg_debug_init;
217 
218 	sfc_log_init(sa, "entry");
219 
220 	dev->data->mac_addrs = rte_zmalloc("sfc", ETHER_ADDR_LEN, 0);
221 	if (dev->data->mac_addrs == NULL) {
222 		rc = ENOMEM;
223 		goto fail_mac_addrs;
224 	}
225 
226 	sfc_adapter_lock_init(sa);
227 	sfc_adapter_lock(sa);
228 
229 	sfc_log_init(sa, "attaching");
230 	rc = sfc_attach(sa);
231 	if (rc != 0)
232 		goto fail_attach;
233 
234 	encp = efx_nic_cfg_get(sa->nic);
235 
236 	/*
237 	 * The arguments are really reverse order in comparison to
238 	 * Linux kernel. Copy from NIC config to Ethernet device data.
239 	 */
240 	from = (const struct ether_addr *)(encp->enc_mac_addr);
241 	ether_addr_copy(from, &dev->data->mac_addrs[0]);
242 
243 	dev->dev_ops = &sfc_eth_dev_ops;
244 
245 	sfc_adapter_unlock(sa);
246 
247 	sfc_log_init(sa, "done");
248 	return 0;
249 
250 fail_attach:
251 	sfc_adapter_unlock(sa);
252 	sfc_adapter_lock_fini(sa);
253 	rte_free(dev->data->mac_addrs);
254 	dev->data->mac_addrs = NULL;
255 
256 fail_mac_addrs:
257 fail_kvarg_debug_init:
258 	sfc_kvargs_cleanup(sa);
259 
260 fail_kvargs_parse:
261 	sfc_log_init(sa, "failed %d", rc);
262 	SFC_ASSERT(rc > 0);
263 	return -rc;
264 }
265 
266 static int
267 sfc_eth_dev_uninit(struct rte_eth_dev *dev)
268 {
269 	struct sfc_adapter *sa = dev->data->dev_private;
270 
271 	sfc_log_init(sa, "entry");
272 
273 	sfc_adapter_lock(sa);
274 
275 	sfc_detach(sa);
276 
277 	rte_free(dev->data->mac_addrs);
278 	dev->data->mac_addrs = NULL;
279 
280 	dev->dev_ops = NULL;
281 
282 	sfc_kvargs_cleanup(sa);
283 
284 	sfc_adapter_unlock(sa);
285 	sfc_adapter_lock_fini(sa);
286 
287 	sfc_log_init(sa, "done");
288 
289 	/* Required for logging, so cleanup last */
290 	sa->eth_dev = NULL;
291 	return 0;
292 }
293 
294 static const struct rte_pci_id pci_id_sfc_efx_map[] = {
295 	{ RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_FARMINGDALE) },
296 	{ RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_GREENPORT) },
297 	{ RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD) },
298 	{ .vendor_id = 0 /* sentinel */ }
299 };
300 
301 static struct eth_driver sfc_efx_pmd = {
302 	.pci_drv = {
303 		.id_table = pci_id_sfc_efx_map,
304 		.drv_flags =
305 			RTE_PCI_DRV_NEED_MAPPING,
306 		.probe = rte_eth_dev_pci_probe,
307 		.remove = rte_eth_dev_pci_remove,
308 	},
309 	.eth_dev_init = sfc_eth_dev_init,
310 	.eth_dev_uninit = sfc_eth_dev_uninit,
311 	.dev_private_size = sizeof(struct sfc_adapter),
312 };
313 
314 RTE_PMD_REGISTER_PCI(net_sfc_efx, sfc_efx_pmd.pci_drv);
315 RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map);
316 RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx,
317 	SFC_KVARG_DEBUG_INIT "=" SFC_KVARG_VALUES_BOOL);
318