net/sfc: add configure and close stubs
[dpdk.git] / drivers / net / sfc / sfc.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 /* sysconf() */
31 #include <unistd.h>
32
33 #include <rte_errno.h>
34
35 #include "efx.h"
36
37 #include "sfc.h"
38 #include "sfc_log.h"
39
40
41 int
42 sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id,
43               size_t len, int socket_id, efsys_mem_t *esmp)
44 {
45         const struct rte_memzone *mz;
46
47         sfc_log_init(sa, "name=%s id=%u len=%lu socket_id=%d",
48                      name, id, len, socket_id);
49
50         mz = rte_eth_dma_zone_reserve(sa->eth_dev, name, id, len,
51                                       sysconf(_SC_PAGESIZE), socket_id);
52         if (mz == NULL) {
53                 sfc_err(sa, "cannot reserve DMA zone for %s:%u %#x@%d: %s",
54                         name, (unsigned int)id, (unsigned int)len, socket_id,
55                         rte_strerror(rte_errno));
56                 return ENOMEM;
57         }
58
59         esmp->esm_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
60         if (esmp->esm_addr == RTE_BAD_PHYS_ADDR) {
61                 (void)rte_memzone_free(mz);
62                 return EFAULT;
63         }
64
65         esmp->esm_mz = mz;
66         esmp->esm_base = mz->addr;
67
68         return 0;
69 }
70
71 void
72 sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp)
73 {
74         int rc;
75
76         sfc_log_init(sa, "name=%s", esmp->esm_mz->name);
77
78         rc = rte_memzone_free(esmp->esm_mz);
79         if (rc != 0)
80                 sfc_err(sa, "rte_memzone_free(() failed: %d", rc);
81
82         memset(esmp, 0, sizeof(*esmp));
83 }
84
85 int
86 sfc_configure(struct sfc_adapter *sa)
87 {
88         sfc_log_init(sa, "entry");
89
90         SFC_ASSERT(sfc_adapter_is_locked(sa));
91
92         SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
93         sa->state = SFC_ADAPTER_CONFIGURING;
94
95         sa->state = SFC_ADAPTER_CONFIGURED;
96         sfc_log_init(sa, "done");
97         return 0;
98 }
99
100 void
101 sfc_close(struct sfc_adapter *sa)
102 {
103         sfc_log_init(sa, "entry");
104
105         SFC_ASSERT(sfc_adapter_is_locked(sa));
106
107         SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED);
108         sa->state = SFC_ADAPTER_CLOSING;
109
110         sa->state = SFC_ADAPTER_INITIALIZED;
111         sfc_log_init(sa, "done");
112 }
113
114 static int
115 sfc_mem_bar_init(struct sfc_adapter *sa)
116 {
117         struct rte_eth_dev *eth_dev = sa->eth_dev;
118         struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(eth_dev);
119         efsys_bar_t *ebp = &sa->mem_bar;
120         unsigned int i;
121         struct rte_mem_resource *res;
122
123         for (i = 0; i < RTE_DIM(pci_dev->mem_resource); i++) {
124                 res = &pci_dev->mem_resource[i];
125                 if ((res->len != 0) && (res->phys_addr != 0)) {
126                         /* Found first memory BAR */
127                         SFC_BAR_LOCK_INIT(ebp, eth_dev->data->name);
128                         ebp->esb_rid = i;
129                         ebp->esb_dev = pci_dev;
130                         ebp->esb_base = res->addr;
131                         return 0;
132                 }
133         }
134
135         return EFAULT;
136 }
137
138 static void
139 sfc_mem_bar_fini(struct sfc_adapter *sa)
140 {
141         efsys_bar_t *ebp = &sa->mem_bar;
142
143         SFC_BAR_LOCK_DESTROY(ebp);
144         memset(ebp, 0, sizeof(*ebp));
145 }
146
147 int
148 sfc_attach(struct sfc_adapter *sa)
149 {
150         struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(sa->eth_dev);
151         efx_nic_t *enp;
152         int rc;
153
154         sfc_log_init(sa, "entry");
155
156         SFC_ASSERT(sfc_adapter_is_locked(sa));
157
158         sa->socket_id = rte_socket_id();
159
160         sfc_log_init(sa, "init mem bar");
161         rc = sfc_mem_bar_init(sa);
162         if (rc != 0)
163                 goto fail_mem_bar_init;
164
165         sfc_log_init(sa, "get family");
166         rc = efx_family(pci_dev->id.vendor_id, pci_dev->id.device_id,
167                         &sa->family);
168         if (rc != 0)
169                 goto fail_family;
170         sfc_log_init(sa, "family is %u", sa->family);
171
172         sfc_log_init(sa, "create nic");
173         rte_spinlock_init(&sa->nic_lock);
174         rc = efx_nic_create(sa->family, (efsys_identifier_t *)sa,
175                             &sa->mem_bar, &sa->nic_lock, &enp);
176         if (rc != 0)
177                 goto fail_nic_create;
178         sa->nic = enp;
179
180         rc = sfc_mcdi_init(sa);
181         if (rc != 0)
182                 goto fail_mcdi_init;
183
184         sfc_log_init(sa, "probe nic");
185         rc = efx_nic_probe(enp);
186         if (rc != 0)
187                 goto fail_nic_probe;
188
189         efx_mcdi_new_epoch(enp);
190
191         sfc_log_init(sa, "reset nic");
192         rc = efx_nic_reset(enp);
193         if (rc != 0)
194                 goto fail_nic_reset;
195
196         /* Initialize NIC to double-check hardware */
197         sfc_log_init(sa, "init nic");
198         rc = efx_nic_init(enp);
199         if (rc != 0)
200                 goto fail_nic_init;
201
202         sfc_log_init(sa, "fini nic");
203         efx_nic_fini(enp);
204
205         sa->rxq_max = 1;
206         sa->txq_max = 1;
207
208         sa->state = SFC_ADAPTER_INITIALIZED;
209
210         sfc_log_init(sa, "done");
211         return 0;
212
213 fail_nic_init:
214 fail_nic_reset:
215         sfc_log_init(sa, "unprobe nic");
216         efx_nic_unprobe(enp);
217
218 fail_nic_probe:
219         sfc_mcdi_fini(sa);
220
221 fail_mcdi_init:
222         sfc_log_init(sa, "destroy nic");
223         sa->nic = NULL;
224         efx_nic_destroy(enp);
225
226 fail_nic_create:
227 fail_family:
228         sfc_mem_bar_fini(sa);
229
230 fail_mem_bar_init:
231         sfc_log_init(sa, "failed %d", rc);
232         return rc;
233 }
234
235 void
236 sfc_detach(struct sfc_adapter *sa)
237 {
238         efx_nic_t *enp = sa->nic;
239
240         sfc_log_init(sa, "entry");
241
242         SFC_ASSERT(sfc_adapter_is_locked(sa));
243
244         sfc_log_init(sa, "unprobe nic");
245         efx_nic_unprobe(enp);
246
247         sfc_mcdi_fini(sa);
248
249         sfc_log_init(sa, "destroy nic");
250         sa->nic = NULL;
251         efx_nic_destroy(enp);
252
253         sfc_mem_bar_fini(sa);
254
255         sa->state = SFC_ADAPTER_UNINITIALIZED;
256 }