0b420ee0bcd9ccdcbf5d207903f55e0e926abdf5
[dpdk.git] / drivers / net / ionic / ionic_main.c
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3  */
4
5 #include <rte_memzone.h>
6
7 #include "ionic.h"
8
9 static int
10 ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait)
11 {
12         unsigned long step_msec = 100;
13         unsigned int max_wait_msec = max_wait * 1000;
14         unsigned long elapsed_msec = 0;
15         int done;
16
17         /* Wait for dev cmd to complete.. but no more than max_wait sec */
18
19         do {
20                 done = ionic_dev_cmd_done(idev);
21                 if (done) {
22                         IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld msecs",
23                                 idev->dev_cmd->cmd.cmd.opcode,
24                                 elapsed_msec);
25                         return 0;
26                 }
27
28                 msec_delay(step_msec);
29
30                 elapsed_msec += step_msec;
31         } while (elapsed_msec < max_wait_msec);
32
33         IONIC_PRINT(DEBUG, "DEVCMD %d timeout after %ld msecs",
34                 idev->dev_cmd->cmd.cmd.opcode,
35                 elapsed_msec);
36
37         return -ETIMEDOUT;
38 }
39
40 static int
41 ionic_dev_cmd_check_error(struct ionic_dev *idev)
42 {
43         uint8_t status;
44
45         status = ionic_dev_cmd_status(idev);
46         if (status == 0)
47                 return 0;
48
49         return -EIO;
50 }
51
52 int
53 ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait)
54 {
55         int err;
56
57         err = ionic_dev_cmd_wait(idev, max_wait);
58         if (err)
59                 return err;
60
61         return ionic_dev_cmd_check_error(idev);
62 }
63
64 int
65 ionic_setup(struct ionic_adapter *adapter)
66 {
67         return ionic_dev_setup(adapter);
68 }
69
70 int
71 ionic_identify(struct ionic_adapter *adapter)
72 {
73         struct ionic_dev *idev = &adapter->idev;
74         struct ionic_identity *ident = &adapter->ident;
75         int err = 0;
76         uint32_t i;
77         unsigned int nwords;
78         uint32_t drv_size = sizeof(ident->drv.words) /
79                 sizeof(ident->drv.words[0]);
80         uint32_t cmd_size = sizeof(idev->dev_cmd->data) /
81                 sizeof(idev->dev_cmd->data[0]);
82         uint32_t dev_size = sizeof(ident->dev.words) /
83                 sizeof(ident->dev.words[0]);
84
85         memset(ident, 0, sizeof(*ident));
86
87         ident->drv.os_type = IONIC_OS_TYPE_LINUX;
88         ident->drv.os_dist = 0;
89         snprintf(ident->drv.os_dist_str,
90                 sizeof(ident->drv.os_dist_str), "Unknown");
91         ident->drv.kernel_ver = 0;
92         snprintf(ident->drv.kernel_ver_str,
93                 sizeof(ident->drv.kernel_ver_str), "DPDK");
94         strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION,
95                 sizeof(ident->drv.driver_ver_str) - 1);
96
97         nwords = RTE_MIN(drv_size, cmd_size);
98         for (i = 0; i < nwords; i++)
99                 iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]);
100
101         ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1);
102         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
103         if (!err) {
104                 nwords = RTE_MIN(dev_size, cmd_size);
105                 for (i = 0; i < nwords; i++)
106                         ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]);
107         }
108
109         return err;
110 }
111
112 int
113 ionic_init(struct ionic_adapter *adapter)
114 {
115         struct ionic_dev *idev = &adapter->idev;
116         int err;
117
118         ionic_dev_cmd_init(idev);
119         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
120         return err;
121 }
122
123 int
124 ionic_reset(struct ionic_adapter *adapter)
125 {
126         struct ionic_dev *idev = &adapter->idev;
127         int err;
128
129         ionic_dev_cmd_reset(idev);
130         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
131         return err;
132 }
133
134 int
135 ionic_port_identify(struct ionic_adapter *adapter)
136 {
137         struct ionic_dev *idev = &adapter->idev;
138         struct ionic_identity *ident = &adapter->ident;
139         unsigned int port_words = sizeof(ident->port.words) /
140                 sizeof(ident->port.words[0]);
141         unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
142                 sizeof(idev->dev_cmd->data[0]);
143         unsigned int i;
144         unsigned int nwords;
145         int err;
146
147         ionic_dev_cmd_port_identify(idev);
148         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
149         if (!err) {
150                 nwords = RTE_MIN(port_words, cmd_words);
151                 for (i = 0; i < nwords; i++)
152                         ident->port.words[i] =
153                                 ioread32(&idev->dev_cmd->data[i]);
154         }
155
156         IONIC_PRINT(INFO, "speed %d ", ident->port.config.speed);
157         IONIC_PRINT(INFO, "mtu %d ", ident->port.config.mtu);
158         IONIC_PRINT(INFO, "state %d ", ident->port.config.state);
159         IONIC_PRINT(INFO, "an_enable %d ", ident->port.config.an_enable);
160         IONIC_PRINT(INFO, "fec_type %d ", ident->port.config.fec_type);
161         IONIC_PRINT(INFO, "pause_type %d ", ident->port.config.pause_type);
162         IONIC_PRINT(INFO, "loopback_mode %d",
163                 ident->port.config.loopback_mode);
164
165         return err;
166 }
167
168 static const struct rte_memzone *
169 ionic_memzone_reserve(const char *name, uint32_t len, int socket_id)
170 {
171         const struct rte_memzone *mz;
172
173         mz = rte_memzone_lookup(name);
174         if (mz)
175                 return mz;
176
177         mz = rte_memzone_reserve_aligned(name, len, socket_id,
178                 RTE_MEMZONE_IOVA_CONTIG, IONIC_ALIGN);
179         return mz;
180 }
181
182 int
183 ionic_port_init(struct ionic_adapter *adapter)
184 {
185         struct ionic_dev *idev = &adapter->idev;
186         struct ionic_identity *ident = &adapter->ident;
187         char z_name[RTE_MEMZONE_NAMESIZE];
188         unsigned int config_words = sizeof(ident->port.config.words) /
189                 sizeof(ident->port.config.words[0]);
190         unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
191                 sizeof(idev->dev_cmd->data[0]);
192         unsigned int nwords;
193         unsigned int i;
194         int err;
195
196         if (idev->port_info)
197                 return 0;
198
199         idev->port_info_sz = RTE_ALIGN(sizeof(*idev->port_info), PAGE_SIZE);
200
201         snprintf(z_name, sizeof(z_name), "%s_port_%s_info",
202                 IONIC_DRV_NAME,
203                 adapter->pci_dev->device.name);
204
205         idev->port_info_z = ionic_memzone_reserve(z_name, idev->port_info_sz,
206                 SOCKET_ID_ANY);
207         if (!idev->port_info_z) {
208                 IONIC_PRINT(ERR, "Cannot reserve port info DMA memory");
209                 return -ENOMEM;
210         }
211
212         idev->port_info = idev->port_info_z->addr;
213         idev->port_info_pa = idev->port_info_z->iova;
214
215         nwords = RTE_MIN(config_words, cmd_words);
216
217         for (i = 0; i < nwords; i++)
218                 iowrite32(ident->port.config.words[i], &idev->dev_cmd->data[i]);
219
220         ionic_dev_cmd_port_init(idev);
221         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
222         if (err) {
223                 IONIC_PRINT(ERR, "Failed to init port");
224                 return err;
225         }
226
227         ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
228         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
229         if (err) {
230                 IONIC_PRINT(WARNING, "Failed to bring port UP");
231                 return err;
232         }
233
234         return 0;
235 }
236
237 int
238 ionic_port_reset(struct ionic_adapter *adapter)
239 {
240         struct ionic_dev *idev = &adapter->idev;
241         int err;
242
243         if (!idev->port_info)
244                 return 0;
245
246         ionic_dev_cmd_port_reset(idev);
247         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
248         if (err) {
249                 IONIC_PRINT(ERR, "Failed to reset port");
250                 return err;
251         }
252
253         idev->port_info = NULL;
254         idev->port_info_pa = 0;
255
256         return 0;
257 }