net/ionic: add port management commands
[dpdk.git] / drivers / net / ionic / ionic_dev.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_malloc.h>
6
7 #include "ionic_dev.h"
8 #include "ionic.h"
9
10 int
11 ionic_dev_setup(struct ionic_adapter *adapter)
12 {
13         struct ionic_dev_bar *bar = adapter->bars;
14         unsigned int num_bars = adapter->num_bars;
15         struct ionic_dev *idev = &adapter->idev;
16         uint32_t sig;
17         u_char *bar0_base;
18
19         /* BAR0: dev_cmd and interrupts */
20         if (num_bars < 1) {
21                 IONIC_PRINT(ERR, "No bars found, aborting");
22                 return -EFAULT;
23         }
24
25         if (bar->len < IONIC_BAR0_SIZE) {
26                 IONIC_PRINT(ERR,
27                         "Resource bar size %lu too small, aborting",
28                         bar->len);
29                 return -EFAULT;
30         }
31
32         bar0_base = bar->vaddr;
33         idev->dev_info = (union ionic_dev_info_regs *)
34                 &bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET];
35         idev->dev_cmd = (union ionic_dev_cmd_regs *)
36                 &bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET];
37         idev->intr_status = (struct ionic_intr_status *)
38                 &bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET];
39         idev->intr_ctrl = (struct ionic_intr *)
40                 &bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET];
41
42         sig = ioread32(&idev->dev_info->signature);
43         if (sig != IONIC_DEV_INFO_SIGNATURE) {
44                 IONIC_PRINT(ERR, "Incompatible firmware signature %" PRIx32 "",
45                         sig);
46                 return -EFAULT;
47         }
48
49         /* BAR1: doorbells */
50         bar++;
51         if (num_bars < 2) {
52                 IONIC_PRINT(ERR, "Doorbell bar missing, aborting");
53                 return -EFAULT;
54         }
55
56         idev->db_pages = bar->vaddr;
57         idev->phy_db_pages = bar->bus_addr;
58
59         return 0;
60 }
61
62 /* Devcmd Interface */
63
64 uint8_t
65 ionic_dev_cmd_status(struct ionic_dev *idev)
66 {
67         return ioread8(&idev->dev_cmd->comp.comp.status);
68 }
69
70 bool
71 ionic_dev_cmd_done(struct ionic_dev *idev)
72 {
73         return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE;
74 }
75
76 void
77 ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem)
78 {
79         union ionic_dev_cmd_comp *comp = mem;
80         unsigned int i;
81         uint32_t comp_size = sizeof(comp->words) /
82                 sizeof(comp->words[0]);
83
84         for (i = 0; i < comp_size; i++)
85                 comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]);
86 }
87
88 void
89 ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd)
90 {
91         unsigned int i;
92         uint32_t cmd_size = sizeof(cmd->words) /
93                 sizeof(cmd->words[0]);
94
95         for (i = 0; i < cmd_size; i++)
96                 iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]);
97
98         iowrite32(0, &idev->dev_cmd->done);
99         iowrite32(1, &idev->dev_cmd->doorbell);
100 }
101
102 /* Device commands */
103
104 void
105 ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver)
106 {
107         union ionic_dev_cmd cmd = {
108                 .identify.opcode = IONIC_CMD_IDENTIFY,
109                 .identify.ver = ver,
110         };
111
112         ionic_dev_cmd_go(idev, &cmd);
113 }
114
115 void
116 ionic_dev_cmd_init(struct ionic_dev *idev)
117 {
118         union ionic_dev_cmd cmd = {
119                 .init.opcode = IONIC_CMD_INIT,
120                 .init.type = 0,
121         };
122
123         ionic_dev_cmd_go(idev, &cmd);
124 }
125
126 void
127 ionic_dev_cmd_reset(struct ionic_dev *idev)
128 {
129         union ionic_dev_cmd cmd = {
130                 .reset.opcode = IONIC_CMD_RESET,
131         };
132
133         ionic_dev_cmd_go(idev, &cmd);
134 }
135
136 /* Port commands */
137
138 void
139 ionic_dev_cmd_port_identify(struct ionic_dev *idev)
140 {
141         union ionic_dev_cmd cmd = {
142                 .port_init.opcode = IONIC_CMD_PORT_IDENTIFY,
143                 .port_init.index = 0,
144         };
145
146         ionic_dev_cmd_go(idev, &cmd);
147 }
148
149 void
150 ionic_dev_cmd_port_init(struct ionic_dev *idev)
151 {
152         union ionic_dev_cmd cmd = {
153                 .port_init.opcode = IONIC_CMD_PORT_INIT,
154                 .port_init.index = 0,
155                 .port_init.info_pa = idev->port_info_pa,
156         };
157
158         ionic_dev_cmd_go(idev, &cmd);
159 }
160
161 void
162 ionic_dev_cmd_port_reset(struct ionic_dev *idev)
163 {
164         union ionic_dev_cmd cmd = {
165                 .port_reset.opcode = IONIC_CMD_PORT_RESET,
166                 .port_reset.index = 0,
167         };
168
169         ionic_dev_cmd_go(idev, &cmd);
170 }
171
172 void
173 ionic_dev_cmd_port_state(struct ionic_dev *idev, uint8_t state)
174 {
175         union ionic_dev_cmd cmd = {
176                 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
177                 .port_setattr.index = 0,
178                 .port_setattr.attr = IONIC_PORT_ATTR_STATE,
179                 .port_setattr.state = state,
180         };
181
182         ionic_dev_cmd_go(idev, &cmd);
183 }
184
185 void
186 ionic_dev_cmd_port_speed(struct ionic_dev *idev, uint32_t speed)
187 {
188         union ionic_dev_cmd cmd = {
189                 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
190                 .port_setattr.index = 0,
191                 .port_setattr.attr = IONIC_PORT_ATTR_SPEED,
192                 .port_setattr.speed = speed,
193         };
194
195         ionic_dev_cmd_go(idev, &cmd);
196 }
197
198 void
199 ionic_dev_cmd_port_mtu(struct ionic_dev *idev, uint32_t mtu)
200 {
201         union ionic_dev_cmd cmd = {
202                 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
203                 .port_setattr.index = 0,
204                 .port_setattr.attr = IONIC_PORT_ATTR_MTU,
205                 .port_setattr.mtu = mtu,
206         };
207
208         ionic_dev_cmd_go(idev, &cmd);
209 }
210
211 void
212 ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, uint8_t an_enable)
213 {
214         union ionic_dev_cmd cmd = {
215                 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
216                 .port_setattr.index = 0,
217                 .port_setattr.attr = IONIC_PORT_ATTR_AUTONEG,
218                 .port_setattr.an_enable = an_enable,
219         };
220
221         ionic_dev_cmd_go(idev, &cmd);
222 }
223
224 void
225 ionic_dev_cmd_port_fec(struct ionic_dev *idev, uint8_t fec_type)
226 {
227         union ionic_dev_cmd cmd = {
228                 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
229                 .port_setattr.index = 0,
230                 .port_setattr.attr = IONIC_PORT_ATTR_FEC,
231                 .port_setattr.fec_type = fec_type,
232         };
233
234         ionic_dev_cmd_go(idev, &cmd);
235 }
236
237 void
238 ionic_dev_cmd_port_pause(struct ionic_dev *idev, uint8_t pause_type)
239 {
240         union ionic_dev_cmd cmd = {
241                 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
242                 .port_setattr.index = 0,
243                 .port_setattr.attr = IONIC_PORT_ATTR_PAUSE,
244                 .port_setattr.pause_type = pause_type,
245         };
246
247         ionic_dev_cmd_go(idev, &cmd);
248 }
249
250 void
251 ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode)
252 {
253         union ionic_dev_cmd cmd = {
254                 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
255                 .port_setattr.index = 0,
256                 .port_setattr.attr = IONIC_PORT_ATTR_LOOPBACK,
257                 .port_setattr.loopback_mode = loopback_mode,
258         };
259
260         ionic_dev_cmd_go(idev, &cmd);
261 }