2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (C) 2013 Emulex
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
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.
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.
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.
33 * Contact Information:
34 * freebsd-drivers@emulex.com
38 * Costa Mesa, CA 92626
46 static int oce_POST(POCE_SOFTC sc);
49 * @brief Function to post status
50 * @param sc software handle to the device
53 oce_POST(POCE_SOFTC sc)
55 mpu_ep_semaphore_t post_status;
58 /* read semaphore CSR */
59 post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc));
61 /* if host is ready then wait for fw ready else send POST */
62 if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) {
63 post_status.bits.stage = POST_STAGE_CHIP_RESET;
64 OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0);
67 /* wait for FW ready */
74 post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc));
75 if (post_status.bits.error) {
76 device_printf(sc->dev,
77 "POST failed: %x\n", post_status.dw0);
80 if (post_status.bits.stage == POST_STAGE_ARMFW_READY)
84 device_printf(sc->dev, "POST timed out: %x\n", post_status.dw0);
90 * @brief Function for hardware initialization
91 * @param sc software handle to the device
94 oce_hw_init(POCE_SOFTC sc)
102 /* create the bootstrap mailbox */
103 rc = oce_dma_alloc(sc, sizeof(struct oce_bmbx), &sc->bsmbx, 0);
105 device_printf(sc->dev, "Mailbox alloc failed\n");
109 rc = oce_reset_fun(sc);
114 rc = oce_mbox_init(sc);
119 rc = oce_get_fw_version(sc);
124 rc = oce_get_fw_config(sc);
129 sc->macaddr.size_of_struct = 6;
130 rc = oce_read_mac_addr(sc, 0, 1, MAC_ADDRESS_TYPE_NETWORK,
135 if ((IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) || IS_SH(sc)) {
136 rc = oce_mbox_check_native_mode(sc);
145 oce_dma_free(sc, &sc->bsmbx);
146 device_printf(sc->dev, "Hardware initialisation failed\n");
153 * @brief Releases the obtained pci resources
154 * @param sc software handle to the device
157 oce_hw_pci_free(POCE_SOFTC sc)
159 int pci_cfg_barnum = 0;
161 if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2))
162 pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR;
164 pci_cfg_barnum = OCE_DEV_CFG_BAR;
166 if (sc->devcfg_res != NULL) {
167 bus_release_resource(sc->dev,
169 PCIR_BAR(pci_cfg_barnum), sc->devcfg_res);
170 sc->devcfg_res = (struct resource *)NULL;
171 sc->devcfg_btag = (bus_space_tag_t) 0;
172 sc->devcfg_bhandle = (bus_space_handle_t)0;
173 sc->devcfg_vhandle = (void *)NULL;
176 if (sc->csr_res != NULL) {
177 bus_release_resource(sc->dev,
179 PCIR_BAR(OCE_PCI_CSR_BAR), sc->csr_res);
180 sc->csr_res = (struct resource *)NULL;
181 sc->csr_btag = (bus_space_tag_t)0;
182 sc->csr_bhandle = (bus_space_handle_t)0;
183 sc->csr_vhandle = (void *)NULL;
186 if (sc->db_res != NULL) {
187 bus_release_resource(sc->dev,
189 PCIR_BAR(OCE_PCI_DB_BAR), sc->db_res);
190 sc->db_res = (struct resource *)NULL;
191 sc->db_btag = (bus_space_tag_t)0;
192 sc->db_bhandle = (bus_space_handle_t)0;
193 sc->db_vhandle = (void *)NULL;
201 * @brief Function to get the PCI capabilities
202 * @param sc software handle to the device
205 void oce_get_pci_capabilities(POCE_SOFTC sc)
209 #if __FreeBSD_version >= 1000000
210 #define pci_find_extcap pci_find_cap
213 if (pci_find_extcap(sc->dev, PCIY_PCIX, &val) == 0) {
215 sc->flags |= OCE_FLAGS_PCIX;
218 if (pci_find_extcap(sc->dev, PCIY_EXPRESS, &val) == 0) {
220 uint16_t link_status =
221 pci_read_config(sc->dev, val + 0x12, 2);
223 sc->flags |= OCE_FLAGS_PCIE;
224 sc->pcie_link_speed = link_status & 0xf;
225 sc->pcie_link_width = (link_status >> 4) & 0x3f;
229 if (pci_find_extcap(sc->dev, PCIY_MSI, &val) == 0) {
231 sc->flags |= OCE_FLAGS_MSI_CAPABLE;
234 if (pci_find_extcap(sc->dev, PCIY_MSIX, &val) == 0) {
236 val = pci_msix_count(sc->dev);
237 sc->flags |= OCE_FLAGS_MSIX_CAPABLE;
243 * @brief Allocate PCI resources.
245 * @param sc software handle to the device
246 * @returns 0 if successful, or error
249 oce_hw_pci_alloc(POCE_SOFTC sc)
251 int rr, pci_cfg_barnum = 0;
254 pci_enable_busmaster(sc->dev);
256 oce_get_pci_capabilities(sc);
258 sc->fn = pci_get_function(sc->dev);
260 /* setup the device config region */
261 if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2))
262 pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR;
264 pci_cfg_barnum = OCE_DEV_CFG_BAR;
266 rr = PCIR_BAR(pci_cfg_barnum);
268 if (IS_BE(sc) || IS_SH(sc))
269 sc->devcfg_res = bus_alloc_resource_any(sc->dev,
271 RF_ACTIVE|RF_SHAREABLE);
273 sc->devcfg_res = bus_alloc_resource_anywhere(sc->dev,
274 SYS_RES_MEMORY, &rr, 32768,
275 RF_ACTIVE|RF_SHAREABLE);
280 sc->devcfg_btag = rman_get_bustag(sc->devcfg_res);
281 sc->devcfg_bhandle = rman_get_bushandle(sc->devcfg_res);
282 sc->devcfg_vhandle = rman_get_virtual(sc->devcfg_res);
284 /* Read the SLI_INTF register and determine whether we
285 * can use this port and its features
287 intf.dw0 = pci_read_config((sc)->dev,OCE_INTF_REG_OFFSET,4);
289 if (intf.bits.sli_valid != OCE_INTF_VALID_SIG)
292 if (intf.bits.sli_rev != OCE_INTF_SLI_REV4) {
293 device_printf(sc->dev, "Adapter doesnt support SLI4\n");
297 if (intf.bits.sli_if_type == OCE_INTF_IF_TYPE_1)
298 sc->flags |= OCE_FLAGS_MBOX_ENDIAN_RQD;
300 if (intf.bits.sli_hint1 == OCE_INTF_FUNC_RESET_REQD)
301 sc->flags |= OCE_FLAGS_FUNCRESET_RQD;
303 if (intf.bits.sli_func_type == OCE_INTF_VIRT_FUNC)
304 sc->flags |= OCE_FLAGS_VIRTUAL_PORT;
306 /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */
307 if (IS_BE(sc) || IS_SH(sc)) {
308 /* set up CSR region */
309 rr = PCIR_BAR(OCE_PCI_CSR_BAR);
310 sc->csr_res = bus_alloc_resource_any(sc->dev,
311 SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE);
314 sc->csr_btag = rman_get_bustag(sc->csr_res);
315 sc->csr_bhandle = rman_get_bushandle(sc->csr_res);
316 sc->csr_vhandle = rman_get_virtual(sc->csr_res);
318 /* set up DB doorbell region */
319 rr = PCIR_BAR(OCE_PCI_DB_BAR);
320 sc->db_res = bus_alloc_resource_any(sc->dev,
321 SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE);
324 sc->db_btag = rman_get_bustag(sc->db_res);
325 sc->db_bhandle = rman_get_bushandle(sc->db_res);
326 sc->db_vhandle = rman_get_virtual(sc->db_res);
338 * @brief Function for device shutdown
339 * @param sc software handle to the device
340 * @returns 0 on success, error otherwise
343 oce_hw_shutdown(POCE_SOFTC sc)
347 /* disable hardware interrupts */
348 oce_hw_intr_disable(sc);
349 #if defined(INET6) || defined(INET)
350 /* Free LRO resources */
354 oce_queue_release_all(sc);
355 /*Delete Network Interface*/
356 oce_delete_nw_interface(sc);
357 /* After fw clean we dont send any cmds to fw.*/
359 /* release intr resources */
361 /* release PCI resources */
363 /* free mbox specific resources */
364 LOCK_DESTROY(&sc->bmbx_lock);
365 LOCK_DESTROY(&sc->dev_lock);
367 oce_dma_free(sc, &sc->bsmbx);
372 * @brief Function for creating nw interface.
373 * @param sc software handle to the device
374 * @returns 0 on success, error otherwise
377 oce_create_nw_interface(POCE_SOFTC sc)
380 uint32_t capab_flags;
381 uint32_t capab_en_flags;
383 /* interface capabilities to give device when creating interface */
384 capab_flags = OCE_CAPAB_FLAGS;
386 /* capabilities to enable by default (others set dynamically) */
387 capab_en_flags = OCE_CAPAB_ENABLE;
390 /* LANCER A0 workaround */
391 capab_en_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR;
392 capab_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR;
395 if (IS_SH(sc) || IS_XE201(sc))
396 capab_flags |= MBX_RX_IFACE_FLAGS_MULTICAST;
398 if (sc->enable_hwlro) {
399 capab_flags |= MBX_RX_IFACE_FLAGS_LRO;
400 capab_en_flags |= MBX_RX_IFACE_FLAGS_LRO;
403 /* enable capabilities controlled via driver startup parameters */
404 if (is_rss_enabled(sc))
405 capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS;
407 capab_en_flags &= ~MBX_RX_IFACE_FLAGS_RSS;
408 capab_flags &= ~MBX_RX_IFACE_FLAGS_RSS;
411 rc = oce_if_create(sc,
414 0, &sc->macaddr.mac_addr[0], &sc->if_id);
418 atomic_inc_32(&sc->nifs);
420 sc->if_cap_flags = capab_en_flags;
422 /* set default flow control */
423 rc = oce_set_flow_control(sc, sc->flow_control);
427 rc = oce_rxf_set_promiscuous(sc, sc->promisc);
434 oce_delete_nw_interface(sc);
440 * @brief Function to delete a nw interface.
441 * @param sc software handle to the device
444 oce_delete_nw_interface(POCE_SOFTC sc)
446 /* currently only single interface is implmeneted */
448 oce_if_del(sc, sc->if_id);
449 atomic_dec_32(&sc->nifs);
455 * @param sc software handle to the device
456 * @returns 0 on success, error otherwise
459 oce_pci_soft_reset(POCE_SOFTC sc)
462 mpu_ep_control_t ctrl;
464 ctrl.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_CONTROL);
465 ctrl.bits.cpu_reset = 1;
466 OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_CONTROL, ctrl.dw0);
474 * @brief Function for hardware start
475 * @param sc software handle to the device
476 * @returns 0 on success, error otherwise
479 oce_hw_start(POCE_SOFTC sc)
481 struct link_status link = { 0 };
484 rc = oce_get_link_status(sc, &link);
488 if (link.logical_link_status == NTWK_LOGICAL_LINK_UP) {
489 sc->link_status = NTWK_LOGICAL_LINK_UP;
490 if_link_state_change(sc->ifp, LINK_STATE_UP);
492 sc->link_status = NTWK_LOGICAL_LINK_DOWN;
493 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
496 sc->link_speed = link.phys_port_speed;
497 sc->qos_link_speed = (uint32_t )link.qos_link_speed * 10;
499 rc = oce_start_mq(sc->mq);
501 /* we need to get MCC aync events. So enable intrs and arm
502 first EQ, Other EQs will be armed after interface is UP
504 oce_hw_intr_enable(sc);
505 oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE);
507 /* Send first mcc cmd and after that we get gracious
508 MCC notifications from FW
510 oce_first_mcc_cmd(sc);
517 * @brief Function for hardware enable interupts.
518 * @param sc software handle to the device
521 oce_hw_intr_enable(POCE_SOFTC sc)
525 reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL);
526 reg |= HOSTINTR_MASK;
527 OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg);
533 * @brief Function for hardware disable interupts
534 * @param sc software handle to the device
537 oce_hw_intr_disable(POCE_SOFTC sc)
541 reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL);
542 reg &= ~HOSTINTR_MASK;
543 OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg);
548 oce_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
550 struct mbx_set_common_iface_multicast *req = arg;
552 if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE)
555 bcopy(LLADDR(sdl), &req->params.req.mac[req->params.req.num_mac++],
563 * @brief Function for hardware update multicast filter
564 * @param sc software handle to the device
567 oce_hw_update_multicast(POCE_SOFTC sc)
569 struct ifnet *ifp = sc->ifp;
570 struct mbx_set_common_iface_multicast *req = NULL;
574 /* Allocate DMA mem*/
575 if (oce_dma_alloc(sc, sizeof(struct mbx_set_common_iface_multicast),
579 req = OCE_DMAPTR(&dma, struct mbx_set_common_iface_multicast);
580 bzero(req, sizeof(struct mbx_set_common_iface_multicast));
582 if_foreach_llmaddr(ifp, oce_copy_maddr, req);
583 if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) {
584 /*More multicast addresses than our hardware table
585 So Enable multicast promiscus in our hardware to
586 accept all multicat packets
588 req->params.req.promiscuous = 1;
591 req->params.req.if_id = sc->if_id;
592 rc = oce_update_multicast(sc, &dma);
593 oce_dma_free(sc, &dma);