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