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
45 static int oce_POST(POCE_SOFTC sc);
48 * @brief Function to post status
49 * @param sc software handle to the device
52 oce_POST(POCE_SOFTC sc)
54 mpu_ep_semaphore_t post_status;
57 /* read semaphore CSR */
58 post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc));
60 /* if host is ready then wait for fw ready else send POST */
61 if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) {
62 post_status.bits.stage = POST_STAGE_CHIP_RESET;
63 OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0);
66 /* wait for FW ready */
73 post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc));
74 if (post_status.bits.error) {
75 device_printf(sc->dev,
76 "POST failed: %x\n", post_status.dw0);
79 if (post_status.bits.stage == POST_STAGE_ARMFW_READY)
83 device_printf(sc->dev, "POST timed out: %x\n", post_status.dw0);
89 * @brief Function for hardware initialization
90 * @param sc software handle to the device
93 oce_hw_init(POCE_SOFTC sc)
101 /* create the bootstrap mailbox */
102 rc = oce_dma_alloc(sc, sizeof(struct oce_bmbx), &sc->bsmbx, 0);
104 device_printf(sc->dev, "Mailbox alloc failed\n");
108 rc = oce_reset_fun(sc);
113 rc = oce_mbox_init(sc);
117 rc = oce_get_fw_version(sc);
121 rc = oce_get_fw_config(sc);
125 sc->macaddr.size_of_struct = 6;
126 rc = oce_read_mac_addr(sc, 0, 1, MAC_ADDRESS_TYPE_NETWORK,
131 if ((IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) || IS_SH(sc)) {
132 rc = oce_mbox_check_native_mode(sc);
141 oce_dma_free(sc, &sc->bsmbx);
142 device_printf(sc->dev, "Hardware initialisation failed\n");
147 * @brief Releases the obtained pci resources
148 * @param sc software handle to the device
151 oce_hw_pci_free(POCE_SOFTC sc)
153 int pci_cfg_barnum = 0;
155 if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2))
156 pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR;
158 pci_cfg_barnum = OCE_DEV_CFG_BAR;
160 if (sc->devcfg_res != NULL) {
161 bus_release_resource(sc->dev,
163 PCIR_BAR(pci_cfg_barnum), sc->devcfg_res);
164 sc->devcfg_res = (struct resource *)NULL;
165 sc->devcfg_btag = (bus_space_tag_t) 0;
166 sc->devcfg_bhandle = (bus_space_handle_t)0;
167 sc->devcfg_vhandle = (void *)NULL;
170 if (sc->csr_res != NULL) {
171 bus_release_resource(sc->dev,
173 PCIR_BAR(OCE_PCI_CSR_BAR), sc->csr_res);
174 sc->csr_res = (struct resource *)NULL;
175 sc->csr_btag = (bus_space_tag_t)0;
176 sc->csr_bhandle = (bus_space_handle_t)0;
177 sc->csr_vhandle = (void *)NULL;
180 if (sc->db_res != NULL) {
181 bus_release_resource(sc->dev,
183 PCIR_BAR(OCE_PCI_DB_BAR), sc->db_res);
184 sc->db_res = (struct resource *)NULL;
185 sc->db_btag = (bus_space_tag_t)0;
186 sc->db_bhandle = (bus_space_handle_t)0;
187 sc->db_vhandle = (void *)NULL;
192 * @brief Function to get the PCI capabilities
193 * @param sc software handle to the device
196 void oce_get_pci_capabilities(POCE_SOFTC sc)
200 if (pci_find_cap(sc->dev, PCIY_PCIX, &val) == 0) {
202 sc->flags |= OCE_FLAGS_PCIX;
205 if (pci_find_cap(sc->dev, PCIY_EXPRESS, &val) == 0) {
207 uint16_t link_status =
208 pci_read_config(sc->dev, val + 0x12, 2);
210 sc->flags |= OCE_FLAGS_PCIE;
211 sc->pcie_link_speed = link_status & 0xf;
212 sc->pcie_link_width = (link_status >> 4) & 0x3f;
216 if (pci_find_cap(sc->dev, PCIY_MSI, &val) == 0) {
218 sc->flags |= OCE_FLAGS_MSI_CAPABLE;
221 if (pci_find_cap(sc->dev, PCIY_MSIX, &val) == 0) {
223 val = pci_msix_count(sc->dev);
224 sc->flags |= OCE_FLAGS_MSIX_CAPABLE;
230 * @brief Allocate PCI resources.
232 * @param sc software handle to the device
233 * @returns 0 if successful, or error
236 oce_hw_pci_alloc(POCE_SOFTC sc)
238 int rr, pci_cfg_barnum = 0;
241 pci_enable_busmaster(sc->dev);
243 oce_get_pci_capabilities(sc);
245 sc->fn = pci_get_function(sc->dev);
247 /* setup the device config region */
248 if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2))
249 pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR;
251 pci_cfg_barnum = OCE_DEV_CFG_BAR;
253 rr = PCIR_BAR(pci_cfg_barnum);
255 if (IS_BE(sc) || IS_SH(sc))
256 sc->devcfg_res = bus_alloc_resource_any(sc->dev,
258 RF_ACTIVE|RF_SHAREABLE);
260 sc->devcfg_res = bus_alloc_resource_anywhere(sc->dev,
261 SYS_RES_MEMORY, &rr, 32768,
262 RF_ACTIVE|RF_SHAREABLE);
267 sc->devcfg_btag = rman_get_bustag(sc->devcfg_res);
268 sc->devcfg_bhandle = rman_get_bushandle(sc->devcfg_res);
269 sc->devcfg_vhandle = rman_get_virtual(sc->devcfg_res);
271 /* Read the SLI_INTF register and determine whether we
272 * can use this port and its features
274 intf.dw0 = pci_read_config((sc)->dev,OCE_INTF_REG_OFFSET,4);
276 if (intf.bits.sli_valid != OCE_INTF_VALID_SIG)
279 if (intf.bits.sli_rev != OCE_INTF_SLI_REV4) {
280 device_printf(sc->dev, "Adapter doesnt support SLI4\n");
284 if (intf.bits.sli_if_type == OCE_INTF_IF_TYPE_1)
285 sc->flags |= OCE_FLAGS_MBOX_ENDIAN_RQD;
287 if (intf.bits.sli_hint1 == OCE_INTF_FUNC_RESET_REQD)
288 sc->flags |= OCE_FLAGS_FUNCRESET_RQD;
290 if (intf.bits.sli_func_type == OCE_INTF_VIRT_FUNC)
291 sc->flags |= OCE_FLAGS_VIRTUAL_PORT;
293 /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */
294 if (IS_BE(sc) || IS_SH(sc)) {
295 /* set up CSR region */
296 rr = PCIR_BAR(OCE_PCI_CSR_BAR);
297 sc->csr_res = bus_alloc_resource_any(sc->dev,
298 SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE);
301 sc->csr_btag = rman_get_bustag(sc->csr_res);
302 sc->csr_bhandle = rman_get_bushandle(sc->csr_res);
303 sc->csr_vhandle = rman_get_virtual(sc->csr_res);
305 /* set up DB doorbell region */
306 rr = PCIR_BAR(OCE_PCI_DB_BAR);
307 sc->db_res = bus_alloc_resource_any(sc->dev,
308 SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE);
311 sc->db_btag = rman_get_bustag(sc->db_res);
312 sc->db_bhandle = rman_get_bushandle(sc->db_res);
313 sc->db_vhandle = rman_get_virtual(sc->db_res);
324 * @brief Function for device shutdown
325 * @param sc software handle to the device
326 * @returns 0 on success, error otherwise
329 oce_hw_shutdown(POCE_SOFTC sc)
333 /* disable hardware interrupts */
334 oce_hw_intr_disable(sc);
335 #if defined(INET6) || defined(INET)
336 /* Free LRO resources */
340 oce_queue_release_all(sc);
341 /*Delete Network Interface*/
342 oce_delete_nw_interface(sc);
343 /* After fw clean we dont send any cmds to fw.*/
345 /* release intr resources */
347 /* release PCI resources */
349 /* free mbox specific resources */
350 LOCK_DESTROY(&sc->bmbx_lock);
351 LOCK_DESTROY(&sc->dev_lock);
353 oce_dma_free(sc, &sc->bsmbx);
357 * @brief Function for creating nw interface.
358 * @param sc software handle to the device
359 * @returns 0 on success, error otherwise
362 oce_create_nw_interface(POCE_SOFTC sc)
365 uint32_t capab_flags;
366 uint32_t capab_en_flags;
368 /* interface capabilities to give device when creating interface */
369 capab_flags = OCE_CAPAB_FLAGS;
371 /* capabilities to enable by default (others set dynamically) */
372 capab_en_flags = OCE_CAPAB_ENABLE;
375 /* LANCER A0 workaround */
376 capab_en_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR;
377 capab_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR;
380 if (IS_SH(sc) || IS_XE201(sc))
381 capab_flags |= MBX_RX_IFACE_FLAGS_MULTICAST;
383 if (sc->enable_hwlro) {
384 capab_flags |= MBX_RX_IFACE_FLAGS_LRO;
385 capab_en_flags |= MBX_RX_IFACE_FLAGS_LRO;
388 /* enable capabilities controlled via driver startup parameters */
389 if (is_rss_enabled(sc))
390 capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS;
392 capab_en_flags &= ~MBX_RX_IFACE_FLAGS_RSS;
393 capab_flags &= ~MBX_RX_IFACE_FLAGS_RSS;
396 rc = oce_if_create(sc,
399 0, &sc->macaddr.mac_addr[0], &sc->if_id);
403 atomic_inc_32(&sc->nifs);
405 sc->if_cap_flags = capab_en_flags;
407 /* set default flow control */
408 rc = oce_set_flow_control(sc, sc->flow_control);
412 rc = oce_rxf_set_promiscuous(sc, sc->promisc);
419 oce_delete_nw_interface(sc);
425 * @brief Function to delete a nw interface.
426 * @param sc software handle to the device
429 oce_delete_nw_interface(POCE_SOFTC sc)
431 /* currently only single interface is implmeneted */
433 oce_if_del(sc, sc->if_id);
434 atomic_dec_32(&sc->nifs);
440 * @param sc software handle to the device
441 * @returns 0 on success, error otherwise
444 oce_pci_soft_reset(POCE_SOFTC sc)
447 mpu_ep_control_t ctrl;
449 ctrl.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_CONTROL);
450 ctrl.bits.cpu_reset = 1;
451 OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_CONTROL, ctrl.dw0);
459 * @brief Function for hardware start
460 * @param sc software handle to the device
461 * @returns 0 on success, error otherwise
464 oce_hw_start(POCE_SOFTC sc)
466 struct link_status link = { 0 };
469 rc = oce_get_link_status(sc, &link);
473 if (link.logical_link_status == NTWK_LOGICAL_LINK_UP) {
474 sc->link_status = NTWK_LOGICAL_LINK_UP;
475 if_link_state_change(sc->ifp, LINK_STATE_UP);
477 sc->link_status = NTWK_LOGICAL_LINK_DOWN;
478 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
481 sc->link_speed = link.phys_port_speed;
482 sc->qos_link_speed = (uint32_t )link.qos_link_speed * 10;
484 rc = oce_start_mq(sc->mq);
486 /* we need to get MCC aync events. So enable intrs and arm
487 first EQ, Other EQs will be armed after interface is UP
489 oce_hw_intr_enable(sc);
490 oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE);
492 /* Send first mcc cmd and after that we get gracious
493 MCC notifications from FW
495 oce_first_mcc_cmd(sc);
501 * @brief Function for hardware enable interupts.
502 * @param sc software handle to the device
505 oce_hw_intr_enable(POCE_SOFTC sc)
509 reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL);
510 reg |= HOSTINTR_MASK;
511 OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg);
516 * @brief Function for hardware disable interupts
517 * @param sc software handle to the device
520 oce_hw_intr_disable(POCE_SOFTC sc)
524 reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL);
525 reg &= ~HOSTINTR_MASK;
526 OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg);
530 oce_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
532 struct mbx_set_common_iface_multicast *req = arg;
534 if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE)
537 bcopy(LLADDR(sdl), &req->params.req.mac[req->params.req.num_mac++],
544 * @brief Function for hardware update multicast filter
545 * @param sc software handle to the device
548 oce_hw_update_multicast(POCE_SOFTC sc)
550 struct ifnet *ifp = sc->ifp;
551 struct mbx_set_common_iface_multicast *req = NULL;
555 /* Allocate DMA mem*/
556 if (oce_dma_alloc(sc, sizeof(struct mbx_set_common_iface_multicast),
560 req = OCE_DMAPTR(&dma, struct mbx_set_common_iface_multicast);
561 bzero(req, sizeof(struct mbx_set_common_iface_multicast));
563 if_foreach_llmaddr(ifp, oce_copy_maddr, req);
564 if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) {
565 /*More multicast addresses than our hardware table
566 So Enable multicast promiscus in our hardware to
567 accept all multicat packets
569 req->params.req.promiscuous = 1;
572 req->params.req.if_id = sc->if_id;
573 rc = oce_update_multicast(sc, &dma);
574 oce_dma_free(sc, &dma);