1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (C) 2013 Emulex
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Emulex Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Contact Information:
34 * freebsd-drivers@emulex.com
35 *
36 * Emulex
37 * 3333 Susan Street
38 * Costa Mesa, CA 92626
39 */
40
41
42 #include "oce_if.h"
43
44 static int oce_POST(POCE_SOFTC sc);
45
46 /**
47 * @brief Function to post status
48 * @param sc software handle to the device
49 */
50 static int
oce_POST(POCE_SOFTC sc)51 oce_POST(POCE_SOFTC sc)
52 {
53 mpu_ep_semaphore_t post_status;
54 int tmo = 60000;
55
56 /* read semaphore CSR */
57 post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc));
58
59 /* if host is ready then wait for fw ready else send POST */
60 if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) {
61 post_status.bits.stage = POST_STAGE_CHIP_RESET;
62 OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0);
63 }
64
65 /* wait for FW ready */
66 for (;;) {
67 if (--tmo == 0)
68 break;
69
70 DELAY(1000);
71
72 post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc));
73 if (post_status.bits.error) {
74 device_printf(sc->dev,
75 "POST failed: %x\n", post_status.dw0);
76 return ENXIO;
77 }
78 if (post_status.bits.stage == POST_STAGE_ARMFW_READY)
79 return 0;
80 }
81
82 device_printf(sc->dev, "POST timed out: %x\n", post_status.dw0);
83
84 return ENXIO;
85 }
86
87 /**
88 * @brief Function for hardware initialization
89 * @param sc software handle to the device
90 */
91 int
oce_hw_init(POCE_SOFTC sc)92 oce_hw_init(POCE_SOFTC sc)
93 {
94 int rc = 0;
95
96 rc = oce_POST(sc);
97 if (rc)
98 return rc;
99
100 /* create the bootstrap mailbox */
101 rc = oce_dma_alloc(sc, sizeof(struct oce_bmbx), &sc->bsmbx, 0);
102 if (rc) {
103 device_printf(sc->dev, "Mailbox alloc failed\n");
104 return rc;
105 }
106
107 rc = oce_reset_fun(sc);
108 if (rc)
109 goto error;
110
111
112 rc = oce_mbox_init(sc);
113 if (rc)
114 goto error;
115
116 rc = oce_get_fw_version(sc);
117 if (rc)
118 goto error;
119
120 rc = oce_get_fw_config(sc);
121 if (rc)
122 goto error;
123
124 sc->macaddr.size_of_struct = 6;
125 rc = oce_read_mac_addr(sc, 0, 1, MAC_ADDRESS_TYPE_NETWORK,
126 &sc->macaddr);
127 if (rc)
128 goto error;
129
130 if ((IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) || IS_SH(sc)) {
131 rc = oce_mbox_check_native_mode(sc);
132 if (rc)
133 goto error;
134 } else
135 sc->be3_native = 0;
136
137 return rc;
138
139 error:
140 oce_dma_free(sc, &sc->bsmbx);
141 device_printf(sc->dev, "Hardware initialisation failed\n");
142 return rc;
143 }
144
145 /**
146 * @brief Releases the obtained pci resources
147 * @param sc software handle to the device
148 */
149 void
oce_hw_pci_free(POCE_SOFTC sc)150 oce_hw_pci_free(POCE_SOFTC sc)
151 {
152 int pci_cfg_barnum = 0;
153
154 if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2))
155 pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR;
156 else
157 pci_cfg_barnum = OCE_DEV_CFG_BAR;
158
159 if (sc->devcfg_res != NULL) {
160 bus_release_resource(sc->dev,
161 SYS_RES_MEMORY,
162 PCIR_BAR(pci_cfg_barnum), sc->devcfg_res);
163 sc->devcfg_res = (struct resource *)NULL;
164 sc->devcfg_btag = (bus_space_tag_t) 0;
165 sc->devcfg_bhandle = (bus_space_handle_t)0;
166 sc->devcfg_vhandle = (void *)NULL;
167 }
168
169 if (sc->csr_res != NULL) {
170 bus_release_resource(sc->dev,
171 SYS_RES_MEMORY,
172 PCIR_BAR(OCE_PCI_CSR_BAR), sc->csr_res);
173 sc->csr_res = (struct resource *)NULL;
174 sc->csr_btag = (bus_space_tag_t)0;
175 sc->csr_bhandle = (bus_space_handle_t)0;
176 sc->csr_vhandle = (void *)NULL;
177 }
178
179 if (sc->db_res != NULL) {
180 bus_release_resource(sc->dev,
181 SYS_RES_MEMORY,
182 PCIR_BAR(OCE_PCI_DB_BAR), sc->db_res);
183 sc->db_res = (struct resource *)NULL;
184 sc->db_btag = (bus_space_tag_t)0;
185 sc->db_bhandle = (bus_space_handle_t)0;
186 sc->db_vhandle = (void *)NULL;
187 }
188 }
189
190 /**
191 * @brief Function to get the PCI capabilities
192 * @param sc software handle to the device
193 */
194 static
oce_get_pci_capabilities(POCE_SOFTC sc)195 void oce_get_pci_capabilities(POCE_SOFTC sc)
196 {
197 uint32_t val;
198
199 if (pci_find_cap(sc->dev, PCIY_PCIX, &val) == 0) {
200 if (val != 0)
201 sc->flags |= OCE_FLAGS_PCIX;
202 }
203
204 if (pci_find_cap(sc->dev, PCIY_EXPRESS, &val) == 0) {
205 if (val != 0) {
206 uint16_t link_status =
207 pci_read_config(sc->dev, val + 0x12, 2);
208
209 sc->flags |= OCE_FLAGS_PCIE;
210 sc->pcie_link_speed = link_status & 0xf;
211 sc->pcie_link_width = (link_status >> 4) & 0x3f;
212 }
213 }
214
215 if (pci_find_cap(sc->dev, PCIY_MSI, &val) == 0) {
216 if (val != 0)
217 sc->flags |= OCE_FLAGS_MSI_CAPABLE;
218 }
219
220 if (pci_find_cap(sc->dev, PCIY_MSIX, &val) == 0) {
221 if (val != 0) {
222 val = pci_msix_count(sc->dev);
223 sc->flags |= OCE_FLAGS_MSIX_CAPABLE;
224 }
225 }
226 }
227
228 /**
229 * @brief Allocate PCI resources.
230 *
231 * @param sc software handle to the device
232 * @returns 0 if successful, or error
233 */
234 int
oce_hw_pci_alloc(POCE_SOFTC sc)235 oce_hw_pci_alloc(POCE_SOFTC sc)
236 {
237 int rr, pci_cfg_barnum = 0;
238 pci_sli_intf_t intf;
239
240 pci_enable_busmaster(sc->dev);
241
242 oce_get_pci_capabilities(sc);
243
244 sc->fn = pci_get_function(sc->dev);
245
246 /* setup the device config region */
247 if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2))
248 pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR;
249 else
250 pci_cfg_barnum = OCE_DEV_CFG_BAR;
251
252 rr = PCIR_BAR(pci_cfg_barnum);
253
254 if (IS_BE(sc) || IS_SH(sc))
255 sc->devcfg_res = bus_alloc_resource_any(sc->dev,
256 SYS_RES_MEMORY, &rr,
257 RF_ACTIVE|RF_SHAREABLE);
258 else
259 sc->devcfg_res = bus_alloc_resource_anywhere(sc->dev,
260 SYS_RES_MEMORY, &rr, 32768,
261 RF_ACTIVE|RF_SHAREABLE);
262
263 if (!sc->devcfg_res)
264 goto error;
265
266 sc->devcfg_btag = rman_get_bustag(sc->devcfg_res);
267 sc->devcfg_bhandle = rman_get_bushandle(sc->devcfg_res);
268 sc->devcfg_vhandle = rman_get_virtual(sc->devcfg_res);
269
270 /* Read the SLI_INTF register and determine whether we
271 * can use this port and its features
272 */
273 intf.dw0 = pci_read_config((sc)->dev,OCE_INTF_REG_OFFSET,4);
274
275 if (intf.bits.sli_valid != OCE_INTF_VALID_SIG)
276 goto error;
277
278 if (intf.bits.sli_rev != OCE_INTF_SLI_REV4) {
279 device_printf(sc->dev, "Adapter doesnt support SLI4\n");
280 goto error;
281 }
282
283 if (intf.bits.sli_if_type == OCE_INTF_IF_TYPE_1)
284 sc->flags |= OCE_FLAGS_MBOX_ENDIAN_RQD;
285
286 if (intf.bits.sli_hint1 == OCE_INTF_FUNC_RESET_REQD)
287 sc->flags |= OCE_FLAGS_FUNCRESET_RQD;
288
289 if (intf.bits.sli_func_type == OCE_INTF_VIRT_FUNC)
290 sc->flags |= OCE_FLAGS_VIRTUAL_PORT;
291
292 /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */
293 if (IS_BE(sc) || IS_SH(sc)) {
294 /* set up CSR region */
295 rr = PCIR_BAR(OCE_PCI_CSR_BAR);
296 sc->csr_res = bus_alloc_resource_any(sc->dev,
297 SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE);
298 if (!sc->csr_res)
299 goto error;
300 sc->csr_btag = rman_get_bustag(sc->csr_res);
301 sc->csr_bhandle = rman_get_bushandle(sc->csr_res);
302 sc->csr_vhandle = rman_get_virtual(sc->csr_res);
303
304 /* set up DB doorbell region */
305 rr = PCIR_BAR(OCE_PCI_DB_BAR);
306 sc->db_res = bus_alloc_resource_any(sc->dev,
307 SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE);
308 if (!sc->db_res)
309 goto error;
310 sc->db_btag = rman_get_bustag(sc->db_res);
311 sc->db_bhandle = rman_get_bushandle(sc->db_res);
312 sc->db_vhandle = rman_get_virtual(sc->db_res);
313 }
314
315 return 0;
316
317 error:
318 oce_hw_pci_free(sc);
319 return ENXIO;
320 }
321
322 /**
323 * @brief Function for device shutdown
324 * @param sc software handle to the device
325 * @returns 0 on success, error otherwise
326 */
327 void
oce_hw_shutdown(POCE_SOFTC sc)328 oce_hw_shutdown(POCE_SOFTC sc)
329 {
330
331 oce_stats_free(sc);
332 /* disable hardware interrupts */
333 oce_hw_intr_disable(sc);
334 #if defined(INET6) || defined(INET)
335 /* Free LRO resources */
336 oce_free_lro(sc);
337 #endif
338 /* Release queue*/
339 oce_queue_release_all(sc);
340 /*Delete Network Interface*/
341 oce_delete_nw_interface(sc);
342 /* After fw clean we dont send any cmds to fw.*/
343 oce_fw_clean(sc);
344 /* release intr resources */
345 oce_intr_free(sc);
346 /* release PCI resources */
347 oce_hw_pci_free(sc);
348 /* free mbox specific resources */
349 LOCK_DESTROY(&sc->bmbx_lock);
350 LOCK_DESTROY(&sc->dev_lock);
351
352 oce_dma_free(sc, &sc->bsmbx);
353 }
354
355 /**
356 * @brief Function for creating nw interface.
357 * @param sc software handle to the device
358 * @returns 0 on success, error otherwise
359 */
360 int
oce_create_nw_interface(POCE_SOFTC sc)361 oce_create_nw_interface(POCE_SOFTC sc)
362 {
363 int rc;
364 uint32_t capab_flags;
365 uint32_t capab_en_flags;
366
367 /* interface capabilities to give device when creating interface */
368 capab_flags = OCE_CAPAB_FLAGS;
369
370 /* capabilities to enable by default (others set dynamically) */
371 capab_en_flags = OCE_CAPAB_ENABLE;
372
373 if (IS_XE201(sc)) {
374 /* LANCER A0 workaround */
375 capab_en_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR;
376 capab_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR;
377 }
378
379 if (IS_SH(sc) || IS_XE201(sc))
380 capab_flags |= MBX_RX_IFACE_FLAGS_MULTICAST;
381
382 if (sc->enable_hwlro) {
383 capab_flags |= MBX_RX_IFACE_FLAGS_LRO;
384 capab_en_flags |= MBX_RX_IFACE_FLAGS_LRO;
385 }
386
387 /* enable capabilities controlled via driver startup parameters */
388 if (is_rss_enabled(sc))
389 capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS;
390 else {
391 capab_en_flags &= ~MBX_RX_IFACE_FLAGS_RSS;
392 capab_flags &= ~MBX_RX_IFACE_FLAGS_RSS;
393 }
394
395 rc = oce_if_create(sc,
396 capab_flags,
397 capab_en_flags,
398 0, &sc->macaddr.mac_addr[0], &sc->if_id);
399 if (rc)
400 return rc;
401
402 atomic_inc_32(&sc->nifs);
403
404 sc->if_cap_flags = capab_en_flags;
405
406 /* set default flow control */
407 rc = oce_set_flow_control(sc, sc->flow_control);
408 if (rc)
409 goto error;
410
411 rc = oce_rxf_set_promiscuous(sc, sc->promisc);
412 if (rc)
413 goto error;
414
415 return rc;
416
417 error:
418 oce_delete_nw_interface(sc);
419 return rc;
420
421 }
422
423 /**
424 * @brief Function to delete a nw interface.
425 * @param sc software handle to the device
426 */
427 void
oce_delete_nw_interface(POCE_SOFTC sc)428 oce_delete_nw_interface(POCE_SOFTC sc)
429 {
430 /* currently only single interface is implmeneted */
431 if (sc->nifs > 0) {
432 oce_if_del(sc, sc->if_id);
433 atomic_dec_32(&sc->nifs);
434 }
435 }
436
437 /**
438 * @brief Soft reset.
439 * @param sc software handle to the device
440 * @returns 0 on success, error otherwise
441 */
442 int
oce_pci_soft_reset(POCE_SOFTC sc)443 oce_pci_soft_reset(POCE_SOFTC sc)
444 {
445 int rc;
446 mpu_ep_control_t ctrl;
447
448 ctrl.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_CONTROL);
449 ctrl.bits.cpu_reset = 1;
450 OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_CONTROL, ctrl.dw0);
451 DELAY(50);
452 rc=oce_POST(sc);
453
454 return rc;
455 }
456
457 /**
458 * @brief Function for hardware start
459 * @param sc software handle to the device
460 * @returns 0 on success, error otherwise
461 */
462 int
oce_hw_start(POCE_SOFTC sc)463 oce_hw_start(POCE_SOFTC sc)
464 {
465 struct link_status link = { 0 };
466 int rc = 0;
467
468 rc = oce_get_link_status(sc, &link);
469 if (rc)
470 return 1;
471
472 if (link.logical_link_status == NTWK_LOGICAL_LINK_UP) {
473 sc->link_status = NTWK_LOGICAL_LINK_UP;
474 if_link_state_change(sc->ifp, LINK_STATE_UP);
475 } else {
476 sc->link_status = NTWK_LOGICAL_LINK_DOWN;
477 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
478 }
479
480 sc->link_speed = link.phys_port_speed;
481 sc->qos_link_speed = (uint32_t )link.qos_link_speed * 10;
482
483 rc = oce_start_mq(sc->mq);
484
485 /* we need to get MCC aync events. So enable intrs and arm
486 first EQ, Other EQs will be armed after interface is UP
487 */
488 oce_hw_intr_enable(sc);
489 oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE);
490
491 /* Send first mcc cmd and after that we get gracious
492 MCC notifications from FW
493 */
494 oce_first_mcc_cmd(sc);
495
496 return rc;
497 }
498
499 /**
500 * @brief Function for hardware enable interupts.
501 * @param sc software handle to the device
502 */
503 void
oce_hw_intr_enable(POCE_SOFTC sc)504 oce_hw_intr_enable(POCE_SOFTC sc)
505 {
506 uint32_t reg;
507
508 reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL);
509 reg |= HOSTINTR_MASK;
510 OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg);
511
512 }
513
514 /**
515 * @brief Function for hardware disable interupts
516 * @param sc software handle to the device
517 */
518 void
oce_hw_intr_disable(POCE_SOFTC sc)519 oce_hw_intr_disable(POCE_SOFTC sc)
520 {
521 uint32_t reg;
522
523 reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL);
524 reg &= ~HOSTINTR_MASK;
525 OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg);
526 }
527
528 static u_int
oce_copy_maddr(void * arg,struct sockaddr_dl * sdl,u_int cnt)529 oce_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
530 {
531 struct mbx_set_common_iface_multicast *req = arg;
532
533 if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE)
534 return (0);
535
536 bcopy(LLADDR(sdl), &req->params.req.mac[req->params.req.num_mac++],
537 ETHER_ADDR_LEN);
538
539 return (1);
540 }
541
542 /**
543 * @brief Function for hardware update multicast filter
544 * @param sc software handle to the device
545 */
546 int
oce_hw_update_multicast(POCE_SOFTC sc)547 oce_hw_update_multicast(POCE_SOFTC sc)
548 {
549 if_t ifp = sc->ifp;
550 struct mbx_set_common_iface_multicast *req = NULL;
551 OCE_DMA_MEM dma;
552 int rc = 0;
553
554 /* Allocate DMA mem*/
555 if (oce_dma_alloc(sc, sizeof(struct mbx_set_common_iface_multicast),
556 &dma, 0))
557 return ENOMEM;
558
559 req = OCE_DMAPTR(&dma, struct mbx_set_common_iface_multicast);
560 bzero(req, sizeof(struct mbx_set_common_iface_multicast));
561
562 if_foreach_llmaddr(ifp, oce_copy_maddr, req);
563 if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) {
564 /*More multicast addresses than our hardware table
565 So Enable multicast promiscus in our hardware to
566 accept all multicat packets
567 */
568 req->params.req.promiscuous = 1;
569 }
570
571 req->params.req.if_id = sc->if_id;
572 rc = oce_update_multicast(sc, &dma);
573 oce_dma_free(sc, &dma);
574 return rc;
575 }
576