net/sfc: minimum port control sufficient to receive traffic
[dpdk.git] / drivers / net / sfc / sfc_ethdev.c
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
41
42 static void
43 sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
44 {
45         struct sfc_adapter *sa = dev->data->dev_private;
46
47         sfc_log_init(sa, "entry");
48
49         dev_info->pci_dev = RTE_DEV_TO_PCI(dev->device);
50         dev_info->max_rx_pktlen = EFX_MAC_PDU_MAX;
51 }
52
53 static int
54 sfc_dev_configure(struct rte_eth_dev *dev)
55 {
56         struct rte_eth_dev_data *dev_data = dev->data;
57         struct sfc_adapter *sa = dev_data->dev_private;
58         int rc;
59
60         sfc_log_init(sa, "entry n_rxq=%u n_txq=%u",
61                      dev_data->nb_rx_queues, dev_data->nb_tx_queues);
62
63         sfc_adapter_lock(sa);
64         switch (sa->state) {
65         case SFC_ADAPTER_CONFIGURED:
66                 sfc_close(sa);
67                 SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
68                 /* FALLTHROUGH */
69         case SFC_ADAPTER_INITIALIZED:
70                 rc = sfc_configure(sa);
71                 break;
72         default:
73                 sfc_err(sa, "unexpected adapter state %u to configure",
74                         sa->state);
75                 rc = EINVAL;
76                 break;
77         }
78         sfc_adapter_unlock(sa);
79
80         sfc_log_init(sa, "done %d", rc);
81         SFC_ASSERT(rc >= 0);
82         return -rc;
83 }
84
85 static int
86 sfc_dev_start(struct rte_eth_dev *dev)
87 {
88         struct sfc_adapter *sa = dev->data->dev_private;
89         int rc;
90
91         sfc_log_init(sa, "entry");
92
93         sfc_adapter_lock(sa);
94         rc = sfc_start(sa);
95         sfc_adapter_unlock(sa);
96
97         sfc_log_init(sa, "done %d", rc);
98         SFC_ASSERT(rc >= 0);
99         return -rc;
100 }
101
102 static void
103 sfc_dev_stop(struct rte_eth_dev *dev)
104 {
105         struct sfc_adapter *sa = dev->data->dev_private;
106
107         sfc_log_init(sa, "entry");
108
109         sfc_adapter_lock(sa);
110         sfc_stop(sa);
111         sfc_adapter_unlock(sa);
112
113         sfc_log_init(sa, "done");
114 }
115
116 static void
117 sfc_dev_close(struct rte_eth_dev *dev)
118 {
119         struct sfc_adapter *sa = dev->data->dev_private;
120
121         sfc_log_init(sa, "entry");
122
123         sfc_adapter_lock(sa);
124         switch (sa->state) {
125         case SFC_ADAPTER_STARTED:
126                 sfc_stop(sa);
127                 SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED);
128                 /* FALLTHROUGH */
129         case SFC_ADAPTER_CONFIGURED:
130                 sfc_close(sa);
131                 SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
132                 /* FALLTHROUGH */
133         case SFC_ADAPTER_INITIALIZED:
134                 break;
135         default:
136                 sfc_err(sa, "unexpected adapter state %u on close", sa->state);
137                 break;
138         }
139         sfc_adapter_unlock(sa);
140
141         sfc_log_init(sa, "done");
142 }
143
144 static const struct eth_dev_ops sfc_eth_dev_ops = {
145         .dev_configure                  = sfc_dev_configure,
146         .dev_start                      = sfc_dev_start,
147         .dev_stop                       = sfc_dev_stop,
148         .dev_close                      = sfc_dev_close,
149         .dev_infos_get                  = sfc_dev_infos_get,
150 };
151
152 static int
153 sfc_eth_dev_init(struct rte_eth_dev *dev)
154 {
155         struct sfc_adapter *sa = dev->data->dev_private;
156         struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(dev);
157         int rc;
158         const efx_nic_cfg_t *encp;
159         const struct ether_addr *from;
160
161         /* Required for logging */
162         sa->eth_dev = dev;
163
164         /* Copy PCI device info to the dev->data */
165         rte_eth_copy_pci_info(dev, pci_dev);
166
167         rc = sfc_kvargs_parse(sa);
168         if (rc != 0)
169                 goto fail_kvargs_parse;
170
171         rc = sfc_kvargs_process(sa, SFC_KVARG_DEBUG_INIT,
172                                 sfc_kvarg_bool_handler, &sa->debug_init);
173         if (rc != 0)
174                 goto fail_kvarg_debug_init;
175
176         sfc_log_init(sa, "entry");
177
178         dev->data->mac_addrs = rte_zmalloc("sfc", ETHER_ADDR_LEN, 0);
179         if (dev->data->mac_addrs == NULL) {
180                 rc = ENOMEM;
181                 goto fail_mac_addrs;
182         }
183
184         sfc_adapter_lock_init(sa);
185         sfc_adapter_lock(sa);
186
187         sfc_log_init(sa, "attaching");
188         rc = sfc_attach(sa);
189         if (rc != 0)
190                 goto fail_attach;
191
192         encp = efx_nic_cfg_get(sa->nic);
193
194         /*
195          * The arguments are really reverse order in comparison to
196          * Linux kernel. Copy from NIC config to Ethernet device data.
197          */
198         from = (const struct ether_addr *)(encp->enc_mac_addr);
199         ether_addr_copy(from, &dev->data->mac_addrs[0]);
200
201         dev->dev_ops = &sfc_eth_dev_ops;
202
203         sfc_adapter_unlock(sa);
204
205         sfc_log_init(sa, "done");
206         return 0;
207
208 fail_attach:
209         sfc_adapter_unlock(sa);
210         sfc_adapter_lock_fini(sa);
211         rte_free(dev->data->mac_addrs);
212         dev->data->mac_addrs = NULL;
213
214 fail_mac_addrs:
215 fail_kvarg_debug_init:
216         sfc_kvargs_cleanup(sa);
217
218 fail_kvargs_parse:
219         sfc_log_init(sa, "failed %d", rc);
220         SFC_ASSERT(rc > 0);
221         return -rc;
222 }
223
224 static int
225 sfc_eth_dev_uninit(struct rte_eth_dev *dev)
226 {
227         struct sfc_adapter *sa = dev->data->dev_private;
228
229         sfc_log_init(sa, "entry");
230
231         sfc_adapter_lock(sa);
232
233         sfc_detach(sa);
234
235         rte_free(dev->data->mac_addrs);
236         dev->data->mac_addrs = NULL;
237
238         dev->dev_ops = NULL;
239
240         sfc_kvargs_cleanup(sa);
241
242         sfc_adapter_unlock(sa);
243         sfc_adapter_lock_fini(sa);
244
245         sfc_log_init(sa, "done");
246
247         /* Required for logging, so cleanup last */
248         sa->eth_dev = NULL;
249         return 0;
250 }
251
252 static const struct rte_pci_id pci_id_sfc_efx_map[] = {
253         { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_FARMINGDALE) },
254         { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_GREENPORT) },
255         { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD) },
256         { .vendor_id = 0 /* sentinel */ }
257 };
258
259 static struct eth_driver sfc_efx_pmd = {
260         .pci_drv = {
261                 .id_table = pci_id_sfc_efx_map,
262                 .drv_flags =
263                         RTE_PCI_DRV_NEED_MAPPING,
264                 .probe = rte_eth_dev_pci_probe,
265                 .remove = rte_eth_dev_pci_remove,
266         },
267         .eth_dev_init = sfc_eth_dev_init,
268         .eth_dev_uninit = sfc_eth_dev_uninit,
269         .dev_private_size = sizeof(struct sfc_adapter),
270 };
271
272 RTE_PMD_REGISTER_PCI(net_sfc_efx, sfc_efx_pmd.pci_drv);
273 RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map);
274 RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx,
275         SFC_KVARG_DEBUG_INIT "=" SFC_KVARG_VALUES_BOOL);