Print this page
NEX-1890 update oce from source provided by Emulex

*** 17,36 **** * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ ! /* Copyright © 2003-2011 Emulex. All rights reserved. */ /* * Source file containing the implementation of MBOX * and related helper functions */ #include <oce_impl.h> static ddi_dma_attr_t oce_sgl_dma_attr = { DMA_ATTR_V0, /* version number */ 0x0000000000000000ull, /* low address */ 0xFFFFFFFFFFFFFFFFull, /* high address */ 0x0000000000010000ull, /* dma counter max */ --- 17,42 ---- * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ ! /* ! * Copyright (c) 2009-2012 Emulex. All rights reserved. ! * Use is subject to license terms. ! */ + /* * Source file containing the implementation of MBOX * and related helper functions */ #include <oce_impl.h> + extern int pow10[]; + static ddi_dma_attr_t oce_sgl_dma_attr = { DMA_ATTR_V0, /* version number */ 0x0000000000000000ull, /* low address */ 0xFFFFFFFFFFFFFFFFull, /* high address */ 0x0000000000010000ull, /* dma counter max */
*** 42,56 **** MAX_MBX_SGE, /* scatter/gather list length */ 0x00000001, /* granularity */ 0 /* DMA flags */ }; ! static ddi_device_acc_attr_t oce_sgl_buf_accattr = { ! DDI_DEVICE_ATTR_V0, ! DDI_NEVERSWAP_ACC, ! DDI_STRICTORDER_ACC, ! }; /* * common inline function to fill an ioctl request header * * hdr - pointer to a buffer where the header will be initialized --- 48,64 ---- MAX_MBX_SGE, /* scatter/gather list length */ 0x00000001, /* granularity */ 0 /* DMA flags */ }; ! static int oce_mbox_issue_bootstrap(struct oce_dev *dev, struct oce_mbx *mbx, ! uint32_t tmo_sec); ! static uint32_t oce_enqueue_mq_mbox(struct oce_dev *dev, struct oce_mbx *mbx, ! uint32_t tmo_sec); ! static struct oce_mbx_ctx *oce_init_mq_ctx(struct oce_dev *dev, ! struct oce_mbx *mbx); ! static void oce_destroy_mq_ctx(struct oce_mbx_ctx *mbctx); /* * common inline function to fill an ioctl request header * * hdr - pointer to a buffer where the header will be initialized
*** 64,74 **** */ void mbx_common_req_hdr_init(struct mbx_hdr *hdr, uint8_t dom, uint8_t port, uint8_t subsys, uint8_t opcode, ! uint32_t timeout, uint32_t pyld_len) { ASSERT(hdr != NULL); hdr->u0.req.opcode = opcode; hdr->u0.req.subsystem = subsys; --- 72,82 ---- */ void mbx_common_req_hdr_init(struct mbx_hdr *hdr, uint8_t dom, uint8_t port, uint8_t subsys, uint8_t opcode, ! uint32_t timeout, uint32_t pyld_len, uint8_t version) { ASSERT(hdr != NULL); hdr->u0.req.opcode = opcode; hdr->u0.req.subsystem = subsys;
*** 75,85 **** hdr->u0.req.port_number = port; hdr->u0.req.domain = dom; hdr->u0.req.timeout = timeout; hdr->u0.req.request_length = pyld_len - sizeof (struct mbx_hdr); ! hdr->u0.req.rsvd0 = 0; } /* mbx_common_req_hdr_init */ /* * function to initialize the hw with host endian information * --- 83,93 ---- hdr->u0.req.port_number = port; hdr->u0.req.domain = dom; hdr->u0.req.timeout = timeout; hdr->u0.req.request_length = pyld_len - sizeof (struct mbx_hdr); ! hdr->u0.req.version = version; } /* mbx_common_req_hdr_init */ /* * function to initialize the hw with host endian information *
*** 98,126 **** mbx = (struct oce_bmbx *)DBUF_VA(dev->bmbx); ptr = (uint8_t *)&mbx->mbx; /* Endian Signature */ ! *ptr++ = 0xff; *ptr++ = 0x12; *ptr++ = 0x34; ! *ptr++ = 0xff; ! *ptr++ = 0xff; *ptr++ = 0x56; *ptr++ = 0x78; ! *ptr = 0xff; ret = oce_mbox_dispatch(dev, 0); - if (ret != 0) oce_log(dev, CE_NOTE, MOD_CONFIG, ! "Failed to set endian %d", ret); return (ret); } /* oce_mbox_init */ /* * function to wait till we get a mbox ready after writing to the * mbox doorbell * * dev - software handle to the device * --- 106,170 ---- mbx = (struct oce_bmbx *)DBUF_VA(dev->bmbx); ptr = (uint8_t *)&mbx->mbx; /* Endian Signature */ ! *ptr++ = 0xFF; *ptr++ = 0x12; *ptr++ = 0x34; ! *ptr++ = 0xFF; ! *ptr++ = 0xFF; *ptr++ = 0x56; *ptr++ = 0x78; ! *ptr = 0xFF; ret = oce_mbox_dispatch(dev, 0); if (ret != 0) oce_log(dev, CE_NOTE, MOD_CONFIG, ! "Failed to set endianess %d", ret); return (ret); } /* oce_mbox_init */ /* + * function to reset the hw with host endian information + * + * dev - software handle to the device + * + * return 0 on success, ETIMEDOUT on failure + */ + int + oce_mbox_fini(struct oce_dev *dev) + { + struct oce_bmbx *mbx; + uint8_t *ptr; + int ret = 0; + + ASSERT(dev != NULL); + + mbx = (struct oce_bmbx *)DBUF_VA(dev->bmbx); + ptr = (uint8_t *)&mbx->mbx; + + /* Endian Signature */ + *ptr++ = 0xFF; + *ptr++ = 0xAA; + *ptr++ = 0xBB; + *ptr++ = 0xFF; + *ptr++ = 0xFF; + *ptr++ = 0xCC; + *ptr++ = 0xDD; + *ptr = 0xFF; + + ret = oce_mbox_dispatch(dev, 0); + if (ret != 0) + oce_log(dev, CE_NOTE, MOD_CONFIG, + "Failed to reset endianess %d", ret); + + return (ret); + } /* oce_mbox_fini */ + + /* * function to wait till we get a mbox ready after writing to the * mbox doorbell * * dev - software handle to the device *
*** 149,158 **** --- 193,203 ---- mbox_db.dw0 = OCE_DB_READ32(dev, PD_MPU_MBOX_DB); if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); oce_fm_ereport(dev, DDI_FM_DEVICE_INVAL_STATE); + return (EIO); } if (mbox_db.bits.ready) { return (0); }
*** 175,185 **** pd_mpu_mbox_db_t mbox_db; uint32_t pa; int ret; /* sync the bmbx */ ! (void) DBUF_SYNC(dev->bmbx, DDI_DMA_SYNC_FORDEV); /* write 30 bits of address hi dword */ pa = (uint32_t)(DBUF_PA(dev->bmbx) >> 34); bzero(&mbox_db, sizeof (pd_mpu_mbox_db_t)); mbox_db.bits.ready = 0; --- 220,230 ---- pd_mpu_mbox_db_t mbox_db; uint32_t pa; int ret; /* sync the bmbx */ ! DBUF_SYNC(dev->bmbx, 0, 0, DDI_DMA_SYNC_FORDEV); /* write 30 bits of address hi dword */ pa = (uint32_t)(DBUF_PA(dev->bmbx) >> 34); bzero(&mbox_db, sizeof (pd_mpu_mbox_db_t)); mbox_db.bits.ready = 0;
*** 195,204 **** --- 240,250 ---- /* ring the doorbell */ OCE_DB_WRITE32(dev, PD_MPU_MBOX_DB, mbox_db.dw0); if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); + return (EIO); } /* wait for mbox ready */ ret = oce_mbox_wait(dev, tmo_sec); if (ret != 0) {
*** 218,269 **** /* ring the doorbell */ OCE_DB_WRITE32(dev, PD_MPU_MBOX_DB, mbox_db.dw0); if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); } /* wait for mbox ready */ ret = oce_mbox_wait(dev, tmo_sec); /* sync */ ! (void) ddi_dma_sync(DBUF_DHDL(dev->bmbx), 0, 0, ! DDI_DMA_SYNC_FORKERNEL); if (oce_fm_check_dma_handle(dev, DBUF_DHDL(dev->bmbx)) != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); return (EIO); } return (ret); } /* oce_mbox_dispatch */ /* ! * function to post a MBX to the mbox * * dev - software handle to the device * mbx - pointer to the MBX to send ! * mbxctx - pointer to the mbx context structure * * return 0 on success, ETIMEDOUT on failure */ int ! oce_mbox_post(struct oce_dev *dev, struct oce_mbx *mbx, ! struct oce_mbx_ctx *mbxctx) { struct oce_mbx *mb_mbx = NULL; struct oce_mq_cqe *mb_cqe = NULL; struct oce_bmbx *mb = NULL; int ret = 0; ! uint32_t tmo = 0; mutex_enter(&dev->bmbx_lock); - mb = (struct oce_bmbx *)DBUF_VA(dev->bmbx); mb_mbx = &mb->mbx; - /* get the tmo */ - tmo = mbx->tag[0]; - mbx->tag[0] = 0; - /* copy mbx into mbox */ bcopy(mbx, mb_mbx, sizeof (struct oce_mbx)); /* now dispatch */ ret = oce_mbox_dispatch(dev, tmo); --- 264,317 ---- /* ring the doorbell */ OCE_DB_WRITE32(dev, PD_MPU_MBOX_DB, mbox_db.dw0); if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); + return (EIO); } /* wait for mbox ready */ ret = oce_mbox_wait(dev, tmo_sec); + + if (ret != 0) { + oce_log(dev, CE_NOTE, MOD_CONFIG, + "BMBX TIMED OUT PROGRAMMING LO ADDR: %d", ret); + return (ret); + } + /* sync */ ! DBUF_SYNC(dev->bmbx, 0, 0, DDI_DMA_SYNC_FORKERNEL); if (oce_fm_check_dma_handle(dev, DBUF_DHDL(dev->bmbx)) != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); return (EIO); } return (ret); } /* oce_mbox_dispatch */ /* ! * function to post a MBX to the bootstrap mbox * * dev - software handle to the device * mbx - pointer to the MBX to send ! * tmo - timeout in seconds * * return 0 on success, ETIMEDOUT on failure */ int ! oce_mbox_issue_bootstrap(struct oce_dev *dev, struct oce_mbx *mbx, ! uint32_t tmo) { struct oce_mbx *mb_mbx = NULL; struct oce_mq_cqe *mb_cqe = NULL; struct oce_bmbx *mb = NULL; int ret = 0; ! uint32_t status = 0; mutex_enter(&dev->bmbx_lock); mb = (struct oce_bmbx *)DBUF_VA(dev->bmbx); mb_mbx = &mb->mbx; /* copy mbx into mbox */ bcopy(mbx, mb_mbx, sizeof (struct oce_mbx)); /* now dispatch */ ret = oce_mbox_dispatch(dev, tmo);
*** 271,283 **** mutex_exit(&dev->bmbx_lock); return (ret); } /* sync */ ! ! (void) ddi_dma_sync(DBUF_DHDL(dev->bmbx), 0, 0, ! DDI_DMA_SYNC_FORKERNEL); ret = oce_fm_check_dma_handle(dev, DBUF_DHDL(dev->bmbx)); if (ret != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); mutex_exit(&dev->bmbx_lock); return (EIO); --- 319,329 ---- mutex_exit(&dev->bmbx_lock); return (ret); } /* sync */ ! DBUF_SYNC(dev->bmbx, 0, 0, DDI_DMA_SYNC_FORKERNEL); ret = oce_fm_check_dma_handle(dev, DBUF_DHDL(dev->bmbx)); if (ret != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); mutex_exit(&dev->bmbx_lock); return (EIO);
*** 292,335 **** /* copy mbox mbx back */ bcopy(mb_mbx, mbx, sizeof (struct oce_mbx)); /* check mbox status */ ! if (mb_cqe->u0.s.completion_status != 0) { ! oce_log(dev, CE_WARN, MOD_CONFIG, ! "MBOX Command Failed with Status: %d %d", ! mb_cqe->u0.s.completion_status, ! mb_cqe->u0.s.extended_status); mutex_exit(&dev->bmbx_lock); ! return (EIO); ! } - /* - * store the mbx context in the cqe tag section so that - * the upper layer handling the cqe can associate the mbx - * with the response - */ - if (mbxctx) { - /* save context */ - mbxctx->mbx = mb_mbx; - bcopy(&mbxctx, mb_cqe->u0.s.mq_tag, - sizeof (struct oce_mbx_ctx *)); - } - - mutex_exit(&dev->bmbx_lock); - return (0); - } /* oce_mbox_post */ - /* * function to get the firmware version * * dev - software handle to the device * * return 0 on success, EIO on failure */ int ! oce_get_fw_version(struct oce_dev *dev) { struct oce_mbx mbx; struct mbx_get_common_fw_version *fwcmd; int ret = 0; --- 338,362 ---- /* copy mbox mbx back */ bcopy(mb_mbx, mbx, sizeof (struct oce_mbx)); /* check mbox status */ ! status = mb_cqe->u0.s.completion_status << 16 | ! mb_cqe->u0.s.extended_status; mutex_exit(&dev->bmbx_lock); ! return (status); ! } /* oce_mbox_issue_bootstrap */ /* * function to get the firmware version * * dev - software handle to the device * * return 0 on success, EIO on failure */ int ! oce_get_fw_version(struct oce_dev *dev, uint32_t mode) { struct oce_mbx mbx; struct mbx_get_common_fw_version *fwcmd; int ret = 0;
*** 339,361 **** fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_GET_COMMON_FW_VERSION, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_get_common_fw_version)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_get_common_fw_version); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); ! if (ret != 0) { return (ret); } bcopy(fwcmd->params.rsp.fw_ver_str, dev->fw_version, 32); oce_log(dev, CE_NOTE, MOD_CONFIG, "%s %s", fwcmd->params.rsp.fw_ver_str, fwcmd->params.rsp.fw_on_flash_ver_str); --- 366,388 ---- fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_GET_COMMON_FW_VERSION, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_get_common_fw_version), 0); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_get_common_fw_version); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { return (ret); } + bcopy(fwcmd->params.rsp.fw_ver_str, dev->fw_version, 32); oce_log(dev, CE_NOTE, MOD_CONFIG, "%s %s", fwcmd->params.rsp.fw_ver_str, fwcmd->params.rsp.fw_on_flash_ver_str);
*** 386,396 **** fwcmd = (struct ioctl_common_function_reset *)&mbx->payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_FUNCTION_RESET, MBX_TIMEOUT_SEC, ! sizeof (struct ioctl_common_function_reset)); /* fill rest of mbx */ mbx->u0.s.embedded = 1; mbx->payload_length = sizeof (struct ioctl_common_function_reset); DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ); --- 413,423 ---- fwcmd = (struct ioctl_common_function_reset *)&mbx->payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_FUNCTION_RESET, MBX_TIMEOUT_SEC, ! sizeof (struct ioctl_common_function_reset), 0); /* fill rest of mbx */ mbx->u0.s.embedded = 1; mbx->payload_length = sizeof (struct ioctl_common_function_reset); DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
*** 411,421 **** * * return 0 on success, EIO on failure */ int oce_read_mac_addr(struct oce_dev *dev, uint32_t if_id, uint8_t perm, ! uint8_t type, struct mac_address_format *mac) { struct oce_mbx mbx; struct mbx_query_common_iface_mac *fwcmd; int ret = 0; --- 438,448 ---- * * return 0 on success, EIO on failure */ int oce_read_mac_addr(struct oce_dev *dev, uint32_t if_id, uint8_t perm, ! uint8_t type, struct mac_address_format *mac, uint32_t mode) { struct oce_mbx mbx; struct mbx_query_common_iface_mac *fwcmd; int ret = 0;
*** 424,434 **** fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_QUERY_COMMON_IFACE_MAC, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_query_common_iface_mac)); /* fill the command */ fwcmd->params.req.permanent = perm; if (perm) fwcmd->params.req.if_id = (uint16_t)if_id; --- 451,461 ---- fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_QUERY_COMMON_IFACE_MAC, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_query_common_iface_mac), 0); /* fill the command */ fwcmd->params.req.permanent = perm; if (perm) fwcmd->params.req.if_id = (uint16_t)if_id;
*** 440,450 **** mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_query_common_iface_mac); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != 0) { return (ret); } /* get the response */ --- 467,477 ---- mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_query_common_iface_mac); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { return (ret); } /* get the response */
*** 483,493 **** * return 0 on success, EIO on failure */ int oce_if_create(struct oce_dev *dev, uint32_t cap_flags, uint32_t en_flags, uint16_t vlan_tag, uint8_t *mac_addr, ! uint32_t *if_id) { struct oce_mbx mbx; struct mbx_create_common_iface *fwcmd; int ret = 0; --- 510,520 ---- * return 0 on success, EIO on failure */ int oce_if_create(struct oce_dev *dev, uint32_t cap_flags, uint32_t en_flags, uint16_t vlan_tag, uint8_t *mac_addr, ! uint32_t *if_id, uint32_t mode) { struct oce_mbx mbx; struct mbx_create_common_iface *fwcmd; int ret = 0;
*** 497,507 **** fwcmd = (struct mbx_create_common_iface *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_CREATE_COMMON_IFACE, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_common_iface)); DW_SWAP(u32ptr(&fwcmd->hdr), sizeof (struct mbx_hdr)); /* fill the command */ fwcmd->params.req.version = 0; fwcmd->params.req.cap_flags = LE_32(cap_flags); --- 524,534 ---- fwcmd = (struct mbx_create_common_iface *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_CREATE_COMMON_IFACE, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_common_iface), 0); DW_SWAP(u32ptr(&fwcmd->hdr), sizeof (struct mbx_hdr)); /* fill the command */ fwcmd->params.req.version = 0; fwcmd->params.req.cap_flags = LE_32(cap_flags);
*** 519,535 **** mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_common_iface); DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != 0) { return (ret); } - - /* get response */ *if_id = LE_32(fwcmd->params.rsp.if_id); oce_log(dev, CE_NOTE, MOD_CONFIG, "IF_ID = 0x%x", *if_id); --- 546,560 ---- mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_common_iface); DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { return (ret); } /* get response */ *if_id = LE_32(fwcmd->params.rsp.if_id); oce_log(dev, CE_NOTE, MOD_CONFIG, "IF_ID = 0x%x", *if_id);
*** 549,559 **** * if_id - ID of the interface to delete * * return 0 on success, EIO on failure */ int ! oce_if_del(struct oce_dev *dev, uint32_t if_id) { struct oce_mbx mbx; struct mbx_destroy_common_iface *fwcmd; int ret = 0; --- 574,584 ---- * if_id - ID of the interface to delete * * return 0 on success, EIO on failure */ int ! oce_if_del(struct oce_dev *dev, uint32_t if_id, uint32_t mode) { struct oce_mbx mbx; struct mbx_destroy_common_iface *fwcmd; int ret = 0;
*** 562,572 **** fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_DESTROY_COMMON_IFACE, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_destroy_common_iface)); /* fill the command */ fwcmd->params.req.if_id = if_id; /* fill rest of mbx */ --- 587,597 ---- fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_DESTROY_COMMON_IFACE, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_destroy_common_iface), 0); /* fill the command */ fwcmd->params.req.if_id = if_id; /* fill rest of mbx */
*** 573,583 **** mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_destroy_common_iface); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* oce_if_del */ /* * function to query the link status from the hardware --- 598,608 ---- mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_destroy_common_iface); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); return (ret); } /* oce_if_del */ /* * function to query the link status from the hardware
*** 586,596 **** * link_status - [OUT] pointer to the structure returning the link attributes * * return 0 on success, EIO on failure */ int ! oce_get_link_status(struct oce_dev *dev, struct link_status *link) { struct oce_mbx mbx; struct mbx_query_common_link_status *fwcmd; int ret = 0; --- 611,622 ---- * link_status - [OUT] pointer to the structure returning the link attributes * * return 0 on success, EIO on failure */ int ! oce_get_link_status(struct oce_dev *dev, link_state_t *link_status, ! int32_t *link_speed, uint8_t *link_duplex, uint8_t cmd_ver, uint32_t mode) { struct oce_mbx mbx; struct mbx_query_common_link_status *fwcmd; int ret = 0;
*** 600,627 **** fwcmd = (struct mbx_query_common_link_status *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_QUERY_COMMON_LINK_STATUS, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_query_common_link_status)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_query_common_link_status); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); ! if (ret != 0) { return (ret); } /* interpret response */ ! bcopy(&fwcmd->params.rsp, link, sizeof (struct link_status)); ! link->logical_link_status = LE_32(link->logical_link_status); ! link->qos_link_speed = LE_16(link->qos_link_speed); return (0); } /* oce_get_link_status */ /* --- 626,657 ---- fwcmd = (struct mbx_query_common_link_status *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_QUERY_COMMON_LINK_STATUS, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_query_common_link_status), cmd_ver); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_query_common_link_status); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { + oce_log(dev, CE_NOTE, MOD_CONFIG, + "Failed to query link status: 0x%x", ret); return (ret); } /* interpret response */ ! *link_status = (LE_32(fwcmd->params.rsp.logical_link_status) == ! NTWK_LOGICAL_LINK_UP) ? LINK_STATE_UP : LINK_STATE_DOWN; ! *link_speed = (fwcmd->params.rsp.qos_link_speed != 0) ? ! LE_16(fwcmd->params.rsp.qos_link_speed) * 10: ! pow10[fwcmd->params.rsp.mac_speed]; ! *link_duplex = fwcmd->params.rsp.mac_duplex; return (0); } /* oce_get_link_status */ /*
*** 632,642 **** * * return 0 on success, EIO on failure */ int oce_set_rx_filter(struct oce_dev *dev, ! struct mbx_set_common_ntwk_rx_filter *filter) { struct oce_mbx mbx; struct mbx_set_common_ntwk_rx_filter *fwcmd; int ret; --- 662,672 ---- * * return 0 on success, EIO on failure */ int oce_set_rx_filter(struct oce_dev *dev, ! struct mbx_set_common_ntwk_rx_filter *filter, uint32_t mode) { struct oce_mbx mbx; struct mbx_set_common_ntwk_rx_filter *fwcmd; int ret;
*** 648,666 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_NTWK_RX_FILTER, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_set_common_ntwk_rx_filter)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_set_common_ntwk_rx_filter); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* oce_set_rx_filter */ /* --- 678,700 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_NTWK_RX_FILTER, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_set_common_ntwk_rx_filter), 0); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_set_common_ntwk_rx_filter); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); ! if (ret != 0) { ! oce_log(dev, CE_NOTE, MOD_CONFIG, ! "Set RX filter failed: 0x%x", ret); ! } return (ret); } /* oce_set_rx_filter */ /*
*** 673,683 **** * * return 0 on success, EIO on failure */ int oce_set_multicast_table(struct oce_dev *dev, uint32_t if_id, ! struct ether_addr *mca_table, uint16_t mca_cnt, boolean_t promisc) { struct oce_mbx mbx; struct mbx_set_common_iface_multicast *fwcmd; int ret; --- 707,718 ---- * * return 0 on success, EIO on failure */ int oce_set_multicast_table(struct oce_dev *dev, uint32_t if_id, ! struct ether_addr *mca_table, uint16_t mca_cnt, boolean_t promisc, ! uint32_t mode) { struct oce_mbx mbx; struct mbx_set_common_iface_multicast *fwcmd; int ret;
*** 687,697 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_SET_COMMON_IFACE_MULTICAST, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_set_common_iface_multicast)); /* fill the command */ fwcmd->params.req.if_id = (uint8_t)if_id; if (mca_table != NULL) { bcopy(mca_table, &fwcmd->params.req.mac[0], --- 722,732 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_SET_COMMON_IFACE_MULTICAST, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_set_common_iface_multicast), 0); /* fill the command */ fwcmd->params.req.if_id = (uint8_t)if_id; if (mca_table != NULL) { bcopy(mca_table, &fwcmd->params.req.mac[0],
*** 705,715 **** mbx.payload_length = sizeof (struct mbx_set_common_iface_multicast); /* Swap only MBX header + BOOTSTRAP HDR */ DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ)); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* oce_set_multicast_table */ /* --- 740,750 ---- mbx.payload_length = sizeof (struct mbx_set_common_iface_multicast); /* Swap only MBX header + BOOTSTRAP HDR */ DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ)); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); return (ret); } /* oce_set_multicast_table */ /*
*** 718,751 **** * dev - software handle to the device * * return 0 on success, EIO on failure */ int ! oce_get_fw_config(struct oce_dev *dev) { struct oce_mbx mbx; struct mbx_common_query_fw_config *fwcmd; int ret = 0; bzero(&mbx, sizeof (struct oce_mbx)); /* initialize the ioctl header */ fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_QUERY_COMMON_FIRMWARE_CONFIG, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_query_fw_config)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_common_query_fw_config); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != 0) { return (ret); } /* swap and copy into buffer */ DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_common_query_fw_config)); --- 753,789 ---- * dev - software handle to the device * * return 0 on success, EIO on failure */ int ! oce_get_fw_config(struct oce_dev *dev, uint32_t mode) { struct oce_mbx mbx; struct mbx_common_query_fw_config *fwcmd; + struct mbx_common_set_drvfn_capab *capab; int ret = 0; bzero(&mbx, sizeof (struct oce_mbx)); /* initialize the ioctl header */ fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_QUERY_COMMON_FIRMWARE_CONFIG, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_query_fw_config), 0); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_common_query_fw_config); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { + oce_log(dev, CE_WARN, MOD_CONFIG, + "Failed to query fw config: 0x%x", ret); return (ret); } /* swap and copy into buffer */ DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_common_query_fw_config));
*** 762,771 **** --- 800,862 ---- } else { dev->max_tx_rings = fwcmd->params.rsp.ulp[1].wq_count; dev->max_rx_rings = fwcmd->params.rsp.ulp[1].rq_count; } dev->function_caps = fwcmd->params.rsp.function_caps; + + if (!LANCER_CHIP(dev)) { + bzero(&mbx, sizeof (struct oce_mbx)); + /* initialize the ioctl header */ + capab = (struct mbx_common_set_drvfn_capab *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_DRIVER_FUNCTION_CAPABILITIES, + MBX_TIMEOUT_SEC, + sizeof (struct mbx_common_set_drvfn_capab), 0); + + /* fill rest of mbx */ + mbx.u0.s.embedded = 1; + mbx.payload_length = + sizeof (struct mbx_common_set_drvfn_capab); + + capab->params.request.valid_capability_flags = + DRVFN_CAPAB_BE3_NATIVE; + capab->params.request.capability_flags = DRVFN_CAPAB_BE3_NATIVE; + + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + /* now post the command */ + ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); + + if (ret != 0) { + if ((OCE_MBX_STATUS(fwcmd) == + MGMT_STATUS_ILLEGAL_REQUEST) && + OCE_MBX_ADDL_STATUS(fwcmd) == + MGMT_ADDI_STATUS_INVALID_OPCODE) { + /* + * run in legacy mode + */ + dev->rx_rings_per_group = + min(dev->rx_rings_per_group, + MAX_RING_PER_GROUP_LEGACY); + } else { + return (ret); + } + } else { + /* swap and copy into buffer */ + dev->drvfn_caps = + LE_32(capab->params.response.capability_flags); + } + + if (!(dev->drvfn_caps & DRVFN_CAPAB_BE3_NATIVE)) + dev->rx_rings_per_group = min(dev->rx_rings_per_group, + MAX_RING_PER_GROUP_LEGACY); + } + oce_log(dev, CE_NOTE, MOD_CONFIG, + "drvfn_caps = 0x%x, function_caps = 0x%x", + dev->drvfn_caps, dev->function_caps); + return (0); } /* oce_get_fw_config */ /* * function to retrieve statistic counters from the hardware
*** 773,795 **** * dev - software handle to the device * * return 0 on success, EIO on failure */ int ! oce_get_hw_stats(struct oce_dev *dev) { struct oce_mbx mbx; ! struct mbx_get_nic_stats *fwcmd = dev->hw_stats; int ret = 0; bzero(&mbx, sizeof (struct oce_mbx)); /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, OPCODE_GET_NIC_STATS, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_get_nic_stats)); DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_get_nic_stats)); /* fill rest of mbx */ mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(DBUF_PA(dev->stats_dbuf)); mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(DBUF_PA(dev->stats_dbuf)); --- 864,892 ---- * dev - software handle to the device * * return 0 on success, EIO on failure */ int ! oce_get_hw_stats(struct oce_dev *dev, uint32_t mode) { struct oce_mbx mbx; ! struct mbx_get_nic_stats *fwcmd = ! (struct mbx_get_nic_stats *)DBUF_VA(dev->stats_dbuf); int ret = 0; bzero(&mbx, sizeof (struct oce_mbx)); + bzero(fwcmd, sizeof (struct mbx_get_nic_stats)); + /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, OPCODE_GET_NIC_STATS, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_get_nic_stats), 0); ! ! if (dev->chip_rev == OC_CNA_GEN3) ! fwcmd->hdr.u0.req.version = 1; DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_get_nic_stats)); /* fill rest of mbx */ mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(DBUF_PA(dev->stats_dbuf)); mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(DBUF_PA(dev->stats_dbuf));
*** 799,837 **** mbx.u0.s.embedded = 0; mbx.u0.s.sge_count = 1; DW_SWAP(u32ptr(&mbx), sizeof (struct oce_mq_sge) + OCE_BMBX_RHDR_SZ); - bzero(&dev->hw_stats->params, sizeof (dev->hw_stats->params)); - /* sync for device */ ! (void) DBUF_SYNC(dev->stats_dbuf, DDI_DMA_SYNC_FORDEV); /* now post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); /* sync the stats */ ! (void) DBUF_SYNC(dev->stats_dbuf, DDI_DMA_SYNC_FORKERNEL); /* Check the mailbox status and command completion status */ if (ret != 0) { return (ret); } ! DW_SWAP(u32ptr(dev->hw_stats), sizeof (struct mbx_get_nic_stats)); return (0); } /* oce_get_hw_stats */ /* * function to set the number of vectors with the cev * * dev - software handle to the device * num_vectors - number of MSI messages * * return 0 on success, EIO on failure */ int ! oce_num_intr_vectors_set(struct oce_dev *dev, uint32_t num_vectors) { struct oce_mbx mbx; struct mbx_common_cev_modify_msi_messages *fwcmd; int ret = 0; --- 896,993 ---- mbx.u0.s.embedded = 0; mbx.u0.s.sge_count = 1; DW_SWAP(u32ptr(&mbx), sizeof (struct oce_mq_sge) + OCE_BMBX_RHDR_SZ); /* sync for device */ ! DBUF_SYNC(dev->stats_dbuf, 0, 0, DDI_DMA_SYNC_FORDEV); /* now post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); /* sync the stats */ ! DBUF_SYNC(dev->stats_dbuf, 0, 0, DDI_DMA_SYNC_FORKERNEL); /* Check the mailbox status and command completion status */ if (ret != 0) { + oce_log(dev, CE_WARN, MOD_CONFIG, + "Failed to get stats: 0x%x", ret); return (ret); } ! DW_SWAP(u32ptr(&fwcmd->params.rsp), sizeof (struct mbx_get_nic_stats)); return (0); } /* oce_get_hw_stats */ /* + * function to retrieve statistic counters from Lancer hardware + * + * dev - software handle to the device + * + * return 0 on success, EIO on failure + */ + int + oce_get_pport_stats(struct oce_dev *dev, uint32_t mode) + { + struct oce_mbx mbx; + struct mbx_get_pport_stats *fwcmd; + int ret = 0; + + bzero(&mbx, sizeof (struct oce_mbx)); + /* initialize the ioctl header */ + + fwcmd = (struct mbx_get_pport_stats *)DBUF_VA(dev->stats_dbuf); + + bzero(&fwcmd->params, sizeof (fwcmd->params)); + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_NIC, + OPCODE_NIC_GET_PPORT_STATS, + MBX_TIMEOUT_SEC, + sizeof (struct mbx_get_nic_stats), 0); + fwcmd->params.req.arg.pport_num = dev->port_id; + DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_get_pport_stats)); + + /* fill rest of mbx */ + mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(DBUF_PA(dev->stats_dbuf)); + mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(DBUF_PA(dev->stats_dbuf)); + mbx.payload.u0.u1.sgl[0].length = sizeof (struct mbx_get_nic_stats); + mbx.payload_length = sizeof (struct mbx_get_pport_stats); + + mbx.u0.s.embedded = 0; + mbx.u0.s.sge_count = 1; + + DW_SWAP(u32ptr(&mbx), sizeof (struct oce_mq_sge) + OCE_BMBX_RHDR_SZ); + + + /* sync for device */ + DBUF_SYNC(dev->stats_dbuf, 0, 0, DDI_DMA_SYNC_FORDEV); + + /* now post the command */ + ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); + /* sync the stats */ + DBUF_SYNC(dev->stats_dbuf, 0, 0, DDI_DMA_SYNC_FORKERNEL); + + /* Check the mailbox status and command completion status */ + if (ret != 0) { + return (ret); + } + + DW_SWAP(u32ptr(&fwcmd->params.rsp), sizeof (struct mbx_get_nic_stats)); + return (0); + } /* oce_get_pport_stats */ + + /* * function to set the number of vectors with the cev * * dev - software handle to the device * num_vectors - number of MSI messages * * return 0 on success, EIO on failure */ int ! oce_num_intr_vectors_set(struct oce_dev *dev, uint32_t num_vectors, ! uint32_t mode) { struct oce_mbx mbx; struct mbx_common_cev_modify_msi_messages *fwcmd; int ret = 0;
*** 840,850 **** fwcmd = (struct mbx_common_cev_modify_msi_messages *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_CEV_MODIFY_MSI_MESSAGES, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_cev_modify_msi_messages)); /* fill the command */ fwcmd->params.req.num_msi_msgs = LE_32(num_vectors); /* fill rest of mbx */ --- 996,1006 ---- fwcmd = (struct mbx_common_cev_modify_msi_messages *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_CEV_MODIFY_MSI_MESSAGES, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_cev_modify_msi_messages), 0); /* fill the command */ fwcmd->params.req.num_msi_msgs = LE_32(num_vectors); /* fill rest of mbx */
*** 852,862 **** mbx.payload_length = sizeof (struct mbx_common_cev_modify_msi_messages); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* oce_num_intr_vectors_set */ /* --- 1008,1018 ---- mbx.payload_length = sizeof (struct mbx_common_cev_modify_msi_messages); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); return (ret); } /* oce_num_intr_vectors_set */ /*
*** 866,876 **** * flow_control - flow control flags to set * * return 0 on success, EIO on failure */ int ! oce_set_flow_control(struct oce_dev *dev, uint32_t flow_control) { struct oce_mbx mbx; struct mbx_common_get_set_flow_control *fwcmd = (struct mbx_common_get_set_flow_control *)&mbx.payload; int ret; --- 1022,1032 ---- * flow_control - flow control flags to set * * return 0 on success, EIO on failure */ int ! oce_set_flow_control(struct oce_dev *dev, uint32_t flow_control, uint32_t mode) { struct oce_mbx mbx; struct mbx_common_get_set_flow_control *fwcmd = (struct mbx_common_get_set_flow_control *)&mbx.payload; int ret;
*** 879,889 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_SET_COMMON_FLOW_CONTROL, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_get_set_flow_control)); /* fill command */ if (flow_control & OCE_FC_TX) fwcmd->tx_flow_control = 1; --- 1035,1045 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_SET_COMMON_FLOW_CONTROL, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_get_set_flow_control), 0); /* fill command */ if (flow_control & OCE_FC_TX) fwcmd->tx_flow_control = 1;
*** 894,904 **** mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_common_get_set_flow_control); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* oce_set_flow_control */ /* --- 1050,1064 ---- mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_common_get_set_flow_control); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); ! if (ret != 0) { ! oce_log(dev, CE_NOTE, MOD_CONFIG, ! "Set flow control failed: 0x%x", ret); ! } return (ret); } /* oce_set_flow_control */ /*
*** 909,919 **** * is returned * * return 0 on success, EIO on failure */ int ! oce_get_flow_control(struct oce_dev *dev, uint32_t *flow_control) { struct oce_mbx mbx; struct mbx_common_get_set_flow_control *fwcmd; int ret; --- 1069,1079 ---- * is returned * * return 0 on success, EIO on failure */ int ! oce_get_flow_control(struct oce_dev *dev, uint32_t *flow_control, uint32_t mode) { struct oce_mbx mbx; struct mbx_common_get_set_flow_control *fwcmd; int ret;
*** 930,948 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_GET_COMMON_FLOW_CONTROL, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_get_set_flow_control)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_common_get_set_flow_control); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != 0) { return (ret); } --- 1090,1108 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_GET_COMMON_FLOW_CONTROL, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_get_set_flow_control), 0); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_common_get_set_flow_control); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { return (ret); }
*** 966,1005 **** * enable - enable/disable flag * * return 0 on success, EIO on failure */ int ! oce_set_promiscuous(struct oce_dev *dev, boolean_t enable) { struct oce_mbx mbx; ! struct mbx_config_nic_promiscuous *fwcmd; ! int ret; bzero(&mbx, sizeof (struct oce_mbx)); ! fwcmd = (struct mbx_config_nic_promiscuous *)&mbx.payload; - if (dev->port_id == 0) { - fwcmd->params.req.port0_promisc = (uint8_t)enable; - - } else { - fwcmd->params.req.port1_promisc = (uint8_t)enable; - } - /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, ! MBX_SUBSYSTEM_NIC, ! OPCODE_CONFIG_NIC_PROMISCUOUS, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_config_nic_promiscuous)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; ! mbx.payload_length = sizeof (struct mbx_config_nic_promiscuous); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* --- 1126,1168 ---- * enable - enable/disable flag * * return 0 on success, EIO on failure */ int ! oce_set_promiscuous(struct oce_dev *dev, boolean_t enable, uint32_t mode) { struct oce_mbx mbx; ! struct mbx_set_common_iface_rx_filter *fwcmd; ! int ret = 0; bzero(&mbx, sizeof (struct oce_mbx)); ! fwcmd = (struct mbx_set_common_iface_rx_filter *)&mbx.payload; /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, ! MBX_SUBSYSTEM_COMMON, ! OPCODE_COMMON_NTWK_RX_FILTER, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_set_common_iface_rx_filter), 0); /* fill rest of mbx */ mbx.u0.s.embedded = 1; ! mbx.payload_length = sizeof (struct mbx_set_common_iface_rx_filter); ! ! fwcmd->params.req.if_id = dev->if_id; ! /* ! * Not setting VLAN promiscuous as the ! * interface is always in VLAN VLAN prmoiscuous ! */ ! fwcmd->params.req.if_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS; ! if (enable) ! fwcmd->params.req.if_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS; ! DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); return (ret); } /*
*** 1010,1020 **** * * return 0 on success, EIO on failure */ int oce_add_mac(struct oce_dev *dev, uint32_t if_id, ! const uint8_t *mac, uint32_t *pmac_id) { struct oce_mbx mbx; struct mbx_add_common_iface_mac *fwcmd; int ret; --- 1173,1183 ---- * * return 0 on success, EIO on failure */ int oce_add_mac(struct oce_dev *dev, uint32_t if_id, ! const uint8_t *mac, uint32_t *pmac_id, uint32_t mode) { struct oce_mbx mbx; struct mbx_add_common_iface_mac *fwcmd; int ret;
*** 1026,1044 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_ADD_COMMON_IFACE_MAC, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_add_common_iface_mac)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_add_common_iface_mac); DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != 0) { return (ret); } --- 1189,1207 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_ADD_COMMON_IFACE_MAC, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_add_common_iface_mac), 0); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_add_common_iface_mac); DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { return (ret); }
*** 1053,1063 **** * pmac_id - handle to the address added using ace_add_mac * * return 0 on success, EIO on failure */ int ! oce_del_mac(struct oce_dev *dev, uint32_t if_id, uint32_t *pmac_id) { struct oce_mbx mbx; struct mbx_del_common_iface_mac *fwcmd; int ret; --- 1216,1227 ---- * pmac_id - handle to the address added using ace_add_mac * * return 0 on success, EIO on failure */ int ! oce_del_mac(struct oce_dev *dev, uint32_t if_id, uint32_t *pmac_id, ! uint32_t mode) { struct oce_mbx mbx; struct mbx_del_common_iface_mac *fwcmd; int ret;
*** 1069,1087 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_DEL_COMMON_IFACE_MAC, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_add_common_iface_mac)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_del_common_iface_mac); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } --- 1233,1251 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_DEL_COMMON_IFACE_MAC, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_add_common_iface_mac), 0); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_del_common_iface_mac); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); return (ret); }
*** 1097,1107 **** * return 0 on success, EIO on failure */ int oce_config_vlan(struct oce_dev *dev, uint32_t if_id, struct normal_vlan *vtag_arr, uint8_t vtag_cnt, ! boolean_t untagged, boolean_t enable_promisc) { struct oce_mbx mbx; struct mbx_common_config_vlan *fwcmd; int ret; --- 1261,1271 ---- * return 0 on success, EIO on failure */ int oce_config_vlan(struct oce_dev *dev, uint32_t if_id, struct normal_vlan *vtag_arr, uint8_t vtag_cnt, ! boolean_t untagged, boolean_t enable_promisc, uint32_t mode) { struct oce_mbx mbx; struct mbx_common_config_vlan *fwcmd; int ret;
*** 1109,1121 **** fwcmd = (struct mbx_common_config_vlan *)&mbx.payload; /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, ! OPCODE_CONFIG_COMMON_IFACE_VLAN, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_config_vlan)); fwcmd->params.req.if_id = (uint8_t)if_id; fwcmd->params.req.promisc = (uint8_t)enable_promisc; fwcmd->params.req.untagged = (uint8_t)untagged; fwcmd->params.req.num_vlans = vtag_cnt; --- 1273,1285 ---- fwcmd = (struct mbx_common_config_vlan *)&mbx.payload; /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, ! OPCODE_COMMON_NTWK_VLAN_CONFIG, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_config_vlan), 0); fwcmd->params.req.if_id = (uint8_t)if_id; fwcmd->params.req.promisc = (uint8_t)enable_promisc; fwcmd->params.req.untagged = (uint8_t)untagged; fwcmd->params.req.num_vlans = vtag_cnt;
*** 1130,1140 **** mbx.u0.s.embedded = B_TRUE; mbx.payload_length = sizeof (struct mbx_common_config_vlan); DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length)); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* oce_config_vlan */ --- 1294,1304 ---- mbx.u0.s.embedded = B_TRUE; mbx.payload_length = sizeof (struct mbx_common_config_vlan); DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length)); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); return (ret); } /* oce_config_vlan */
*** 1147,1157 **** * enable_promisc - flag to enable/disable mcast-promiscuous mode * * return 0 on success, EIO on failure */ int ! oce_config_link(struct oce_dev *dev, boolean_t enable) { struct oce_mbx mbx; struct mbx_common_func_link_cfg *fwcmd; int ret; --- 1311,1321 ---- * enable_promisc - flag to enable/disable mcast-promiscuous mode * * return 0 on success, EIO on failure */ int ! oce_config_link(struct oce_dev *dev, boolean_t enable, uint32_t mode) { struct oce_mbx mbx; struct mbx_common_func_link_cfg *fwcmd; int ret;
*** 1161,1188 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_FUNCTION_LINK_CONFIG, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_config_vlan)); fwcmd->params.req.enable = enable; /* fill rest of mbx */ mbx.u0.s.embedded = B_TRUE; mbx.payload_length = sizeof (struct mbx_common_func_link_cfg); DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length)); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* oce_config_link */ int oce_config_rss(struct oce_dev *dev, uint16_t if_id, char *hkey, char *itbl, ! int tbl_sz, uint16_t rss_type, uint8_t flush) { struct oce_mbx mbx; struct mbx_config_nic_rss *fwcmd; int i; int ret = 0; --- 1325,1352 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_FUNCTION_LINK_CONFIG, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_common_func_link_cfg), 0); fwcmd->params.req.enable = enable; /* fill rest of mbx */ mbx.u0.s.embedded = B_TRUE; mbx.payload_length = sizeof (struct mbx_common_func_link_cfg); DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length)); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); return (ret); } /* oce_config_link */ int oce_config_rss(struct oce_dev *dev, uint16_t if_id, char *hkey, char *itbl, ! int tbl_sz, uint16_t rss_type, uint8_t flush, uint32_t mode) { struct oce_mbx mbx; struct mbx_config_nic_rss *fwcmd; int i; int ret = 0;
*** 1193,1203 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, OPCODE_CONFIG_NIC_RSS, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_config_nic_rss)); fwcmd->params.req.enable_rss = LE_16(rss_type); fwcmd->params.req.flush = flush; fwcmd->params.req.if_id = LE_32(if_id); if (hkey != NULL) { --- 1357,1367 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, OPCODE_CONFIG_NIC_RSS, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_config_nic_rss), 0); fwcmd->params.req.enable_rss = LE_16(rss_type); fwcmd->params.req.flush = flush; fwcmd->params.req.if_id = LE_32(if_id); if (hkey != NULL) {
*** 1216,1458 **** mbx.u0.s.embedded = B_TRUE; mbx.payload_length = sizeof (struct mbx_config_nic_rss); DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ)); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); return (ret); } /* * function called from the gld ioctl entry point to send a mbx to fw * * dev - software handle to the device * mp - mblk_t containing the user data * payload_len = [OUT] pointer to return the length of the payload written * * return 0 on Success */ int ! oce_issue_mbox(struct oce_dev *dev, queue_t *wq, mblk_t *mp, ! uint32_t *payload_len) { ! int ret; struct oce_mbx mbx; ! struct mbx_hdr hdr; ! ddi_dma_handle_t dma_handle; boolean_t is_embedded = B_FALSE; ! uint32_t payload_length; ! int num_buf = 0; ! int alloc_len; ! caddr_t sg_va; ! ddi_acc_handle_t acc_handle; ! size_t actual_len; _NOTE(ARGUNUSED(wq)); bzero(&mbx, sizeof (struct oce_mbx)); bcopy(mp->b_cont->b_rptr, &hdr, sizeof (struct mbx_hdr)); DW_SWAP(u32ptr(&hdr), sizeof (struct mbx_hdr)); payload_length = hdr.u0.req.request_length + sizeof (struct mbx_hdr); - is_embedded = (payload_length <= sizeof (struct oce_mbx_payload)); - alloc_len = msgdsize(mp->b_cont); - - oce_log(dev, CE_NOTE, MOD_CONFIG, "Mailbox: " - "DW[0] 0x%x DW[1] 0x%x DW[2]0x%x DW[3]0x%x," - "MBLKL(%lu) ALLOCLEN(%d)", - hdr.u0.dw[0], hdr.u0.dw[1], - hdr.u0.dw[2], hdr.u0.dw[3], - MBLKL(mp->b_cont), alloc_len); - /* get the timeout from the command header */ ! mbx.tag[0] = hdr.u0.req.timeout; ! if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) { ! struct mbx_common_read_write_flashrom *fwcmd = ! (struct mbx_common_read_write_flashrom *) ! mp->b_cont->b_rptr; - if (dev->cookie != 0 && dev->cookie != hdr.u0.req.rsvd0) - return (EINVAL); - - if (dev->cookie == 0) - dev->cookie = hdr.u0.req.rsvd0; - hdr.u0.req.rsvd0 = 0; - - oce_log(dev, CE_NOTE, MOD_CONFIG, "Mailbox params:" - "OPCODE(%d) OPTYPE = %d SIZE = %d OFFSET = %d", - fwcmd->flash_op_code, fwcmd->flash_op_type, - fwcmd->data_buffer_size, fwcmd->data_offset); - } - if (!is_embedded) { - mblk_t *tmp = NULL; ddi_dma_cookie_t cookie; ! uint32_t count = 0; ! int offset = 0; ! /* allocate dma handle */ ! ret = ddi_dma_alloc_handle(dev->dip, ! &oce_sgl_dma_attr, DDI_DMA_DONTWAIT, NULL, ! &dma_handle); ! if (ret != DDI_SUCCESS) { ! oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", ! "Failed to alloc DMA handle"); ! ret = ENOMEM; ! goto fail; ! } ! /* allocate the DMA-able memory */ ! ret = ddi_dma_mem_alloc(dma_handle, alloc_len, ! &oce_sgl_buf_accattr, ! DDI_DMA_RDWR | DDI_DMA_CONSISTENT, ! DDI_DMA_DONTWAIT, ! NULL, &sg_va, &actual_len, &acc_handle); if (ret != DDI_SUCCESS) { ! oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", ! "Failed to alloc DMA memory"); ! ret = ENOMEM; ! goto dma_alloc_fail; } for (tmp = mp->b_cont; tmp != NULL; tmp = tmp->b_cont) { ! bcopy((caddr_t)tmp->b_rptr, sg_va + offset, MBLKL(tmp)); offset += MBLKL(tmp); } ! /* bind mblk mem to handle */ ! ret = ddi_dma_addr_bind_handle( ! dma_handle, ! (struct as *)0, sg_va, ! alloc_len, ! DDI_DMA_RDWR | DDI_DMA_CONSISTENT, ! DDI_DMA_DONTWAIT, NULL, &cookie, &count); ! if (ret != DDI_DMA_MAPPED) { ! ret = ENOMEM; ! oce_log(dev, CE_NOTE, MOD_CONFIG, ! "Failed to bind DMA handle ret code: %d", ! ret); ! goto dma_bind_fail; ! } ! ! for (num_buf = 0; num_buf < count; num_buf++) { /* fill the mbx sglist */ mbx.payload.u0.u1.sgl[num_buf].pa_lo = ! ADDR_LO(cookie.dmac_laddress); mbx.payload.u0.u1.sgl[num_buf].pa_hi = ! ADDR_HI(cookie.dmac_laddress); mbx.payload.u0.u1.sgl[num_buf].length = ! (uint32_t)cookie.dmac_size; ! mbx.payload_length += ! mbx.payload.u0.u1.sgl[num_buf].length; ! mbx.u0.s.sge_count++; ! if (count > 1) ! (void) ddi_dma_nextcookie(dma_handle, &cookie); } mbx.u0.s.embedded = 0; - DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ + - (sizeof (struct oce_mq_sge) * count)); } else { /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = payload_length; bcopy(mp->b_cont->b_rptr, &mbx.payload, payload_length); - - DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ); } /* now post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); - bcopy(mp->b_cont->b_rptr, &hdr, sizeof (struct mbx_hdr)); - DW_SWAP(u32ptr(&hdr), sizeof (struct mbx_hdr)); - if (ret != DDI_SUCCESS) { - oce_log(dev, CE_WARN, MOD_CONFIG, - "Failed to post the mailbox: %d", ret); - - *payload_len = hdr.u0.rsp.rsp_length + - sizeof (struct mbx_hdr); - if (is_embedded) { - bcopy(&mbx.payload, mp->b_cont->b_rptr, - MBLKL(mp->b_cont)); goto fail; - } else { - (void) ddi_dma_sync(dma_handle, 0, 0, - DDI_DMA_SYNC_FORKERNEL); - - if (oce_fm_check_dma_handle(dev, dma_handle) != - DDI_FM_OK) { - ddi_fm_service_impact(dev->dip, - DDI_SERVICE_DEGRADED); } - bcopy(sg_va, mp->b_cont->b_rptr, - sizeof (struct mbx_hdr)); - goto post_fail; - } - } - if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) { - struct mbx_common_read_write_flashrom *fwcmd = - (struct mbx_common_read_write_flashrom *) - mp->b_cont->b_rptr; - - if (LE_32(fwcmd->flash_op_code) == MGMT_FLASHROM_OPCODE_FLASH) - dev->cookie = 0; - } - - payload_length = hdr.u0.rsp.rsp_length + sizeof (struct mbx_hdr); - /* Copy the response back only if this is an embedded mbx cmd */ if (is_embedded) { ! bcopy(&mbx.payload, mp->b_cont->b_rptr, ! min(payload_length, MBLKL(mp->b_cont))); } else { - mblk_t *tmp = NULL; - int offset = 0; /* sync */ ! (void) ddi_dma_sync(dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); ! if (oce_fm_check_dma_handle(dev, dma_handle) != DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); } ! /* copy back from kernel allocated buffer to user buffer */ ! for (tmp = mp->b_cont; tmp != NULL; tmp = tmp->b_cont) { ! bcopy(sg_va + offset, tmp->b_rptr, MBLKL(tmp)); ! offset += MBLKL(tmp); } ! /* unbind and free dma handles */ ! (void) ddi_dma_unbind_handle(dma_handle); ! ddi_dma_mem_free(&acc_handle); ! ddi_dma_free_handle(&dma_handle); ! } ! *payload_len = payload_length; ! ! return (0); ! ! post_fail: ! (void) ddi_dma_unbind_handle(dma_handle); ! ! dma_bind_fail: ! ddi_dma_mem_free(&acc_handle); ! ! dma_alloc_fail: ! ddi_dma_free_handle(&dma_handle); ! ! fail: ! alloc_err: ! if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) { ! dev->cookie = 0; } return (ret); } --- 1380,1626 ---- mbx.u0.s.embedded = B_TRUE; mbx.payload_length = sizeof (struct mbx_config_nic_rss); DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ)); /* post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); return (ret); } /* + * function to post a MBX to the mbox + * + * dev - software handle to the device + * mbx - pointer to the MBX to send + * + * return 0 on success, error value on failure + */ + int + oce_issue_mbox_cmd(struct oce_dev *dev, struct oce_mbx *mbx, + uint32_t tmo_sec, uint32_t flag) + { + + struct oce_mq *mq; + if (dev == NULL) { + oce_log(dev, CE_WARN, MOD_CONFIG, + "dev is null 0x%p", (void *)dev); + return (EINVAL); + } + mq = dev->mq; + + if ((dev->mq == NULL) || (mq->qstate != QCREATED) || + !(dev->state & STATE_INTR_ENABLED)) { + /* Force bootstrap mode if MQ is not created or intr disabled */ + if (flag == MBX_ASYNC_MQ) { + oce_log(dev, CE_NOTE, MOD_CONFIG, + "Forcing bootstrap mode DEV STATE %x\n", + dev->state); + flag = MBX_BOOTSTRAP; + + } + } + /* invoke appropriate functions depending on flag */ + switch (flag) { + case MBX_BOOTSTRAP: + return (oce_mbox_issue_bootstrap(dev, mbx, tmo_sec)); + case MBX_ASYNC_MQ: + return (oce_enqueue_mq_mbox(dev, mbx, tmo_sec)); + default: + return (EINVAL); + } + + } + + static struct oce_mbx_ctx * + oce_init_mq_ctx(struct oce_dev *dev, struct oce_mbx *mbx) + { + struct oce_mbx_ctx *mbctx; + mbctx = kmem_zalloc(sizeof (struct oce_mbx_ctx), KM_SLEEP); + + mbctx->mbx = mbx; + cv_init(&mbctx->cond_var, NULL, CV_DRIVER, NULL); + mutex_init(&mbctx->cv_lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(dev->intr_pri)); + mbx->tag[0] = ADDR_LO((uintptr_t)mbctx); + mbx->tag[1] = ADDR_HI((uint64_t)(uintptr_t)mbctx); + return (mbctx); + } + + static void + oce_destroy_mq_ctx(struct oce_mbx_ctx *mbctx) + { + cv_destroy(&mbctx->cond_var); + mutex_destroy(&mbctx->cv_lock); + kmem_free(mbctx, sizeof (struct oce_mbx_ctx)); + } + + static uint32_t + oce_enqueue_mq_mbox(struct oce_dev *dev, struct oce_mbx *mbx, uint32_t tmo_sec) + { + struct oce_mbx_ctx *mbctx; + uint32_t status; + + _NOTE(ARGUNUSED(tmo_sec)); + + mbctx = oce_init_mq_ctx(dev, mbx); + + if (mbctx == NULL) { + return (EIO); + } + mutex_enter(&mbctx->cv_lock); + mbctx->mbx_status = MBX_BUSY; + if (oce_issue_mq_mbox(dev, mbx) != MBX_SUCCESS) { + mutex_exit(&mbctx->cv_lock); + oce_destroy_mq_ctx(mbctx); + return (EIO); + } + while (mbctx->mbx_status & MBX_BUSY) { + cv_wait(&mbctx->cond_var, &mbctx->cv_lock); + } + status = mbctx->compl_status; + mutex_exit(&mbctx->cv_lock); + oce_destroy_mq_ctx(mbctx); + return (status); + } + + /* * function called from the gld ioctl entry point to send a mbx to fw * * dev - software handle to the device * mp - mblk_t containing the user data * payload_len = [OUT] pointer to return the length of the payload written * * return 0 on Success */ int ! oce_issue_mbox_passthru(struct oce_dev *dev, queue_t *wq, mblk_t *mp, ! uint32_t *rsp_len) { ! int ret = 0; struct oce_mbx mbx; ! struct mbx_hdr hdr = {0}; ! struct mbx_hdr *rsp_hdr = NULL; boolean_t is_embedded = B_FALSE; ! int32_t payload_length = 0; ! int offset = 0; ! mblk_t *tmp = NULL; ! uint32_t tmo; ! oce_dma_buf_t dbuf = {0}; _NOTE(ARGUNUSED(wq)); bzero(&mbx, sizeof (struct oce_mbx)); + /* initialize the response len */ + *rsp_len = 0; + + /* copy and swap the request header */ bcopy(mp->b_cont->b_rptr, &hdr, sizeof (struct mbx_hdr)); DW_SWAP(u32ptr(&hdr), sizeof (struct mbx_hdr)); payload_length = hdr.u0.req.request_length + sizeof (struct mbx_hdr); is_embedded = (payload_length <= sizeof (struct oce_mbx_payload)); /* get the timeout from the command header */ ! tmo = hdr.u0.req.timeout; ! oce_log(dev, CE_NOTE, MOD_CONFIG, ! "Mailbox command: opcode=%d, subsystem=%d, timeout=%d", ! hdr.u0.req.opcode, hdr.u0.req.subsystem, tmo); if (!is_embedded) { ddi_dma_cookie_t cookie; ! int alloc_len = 0; ! int num_buf = 0; ! /* Calculate memory size to alloc */ ! alloc_len = msgdsize(mp->b_cont); ! /* allocate the DMA memory */ ! ret = oce_alloc_dma_buffer(dev, &dbuf, alloc_len, ! &oce_sgl_dma_attr, DDI_DMA_CONSISTENT|DDI_DMA_RDWR); if (ret != DDI_SUCCESS) { ! return (ENOMEM); } for (tmp = mp->b_cont; tmp != NULL; tmp = tmp->b_cont) { ! bcopy((caddr_t)tmp->b_rptr, DBUF_VA(dbuf) + offset, ! MBLKL(tmp)); offset += MBLKL(tmp); } ! cookie = dbuf.cookie; ! for (num_buf = 0; num_buf < dbuf.ncookies; num_buf++) { /* fill the mbx sglist */ mbx.payload.u0.u1.sgl[num_buf].pa_lo = ! LE_32(ADDR_LO(cookie.dmac_laddress)); mbx.payload.u0.u1.sgl[num_buf].pa_hi = ! LE_32(ADDR_HI(cookie.dmac_laddress)); mbx.payload.u0.u1.sgl[num_buf].length = ! LE_32((uint32_t)cookie.dmac_size); ! if (dbuf.ncookies > 1) { ! (void) ddi_dma_nextcookie(DBUF_DHDL(dbuf), ! &cookie); } + } mbx.u0.s.embedded = 0; + mbx.payload_length = alloc_len; + mbx.u0.s.sge_count = dbuf.ncookies; + oce_log(dev, CE_NOTE, MOD_CONFIG, + "sg count %d, payload_length = %d", + dbuf.ncookies, alloc_len); } else { /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = payload_length; bcopy(mp->b_cont->b_rptr, &mbx.payload, payload_length); } + /* swap the bootstrap header only */ + OCE_DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ); + /* now post the command */ ! ret = oce_issue_mbox_cmd(dev, &mbx, tmo, MBX_ASYNC_MQ); if (ret != DDI_SUCCESS) { goto fail; } /* Copy the response back only if this is an embedded mbx cmd */ if (is_embedded) { ! rsp_hdr = (struct mbx_hdr *)&mbx.payload; } else { /* sync */ ! (void) ddi_dma_sync(DBUF_DHDL(dbuf), 0, 0, DDI_DMA_SYNC_FORKERNEL); ! if (oce_fm_check_dma_handle(dev, DBUF_DHDL(dbuf)) != ! DDI_FM_OK) { ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); + ret = EIO; + goto fail; } ! /* Get the mailbox header from SG list */ ! rsp_hdr = (struct mbx_hdr *)DBUF_VA(dbuf); } + payload_length = LE_32(rsp_hdr->u0.rsp.actual_rsp_length) + + sizeof (struct mbx_hdr); + *rsp_len = payload_length; ! oce_log(dev, CE_NOTE, MOD_CONFIG, ! "Response Len %d status=0x%x, addnl_status=0x%x", payload_length, ! rsp_hdr->u0.rsp.status, rsp_hdr->u0.rsp.additional_status); ! for (tmp = mp->b_cont, offset = 0; tmp != NULL && payload_length > 0; ! tmp = tmp->b_cont) { ! bcopy((caddr_t)rsp_hdr + offset, tmp->b_rptr, MBLKL(tmp)); ! offset += MBLKL(tmp); ! payload_length -= MBLKL(tmp); } + fail: + oce_free_dma_buffer(dev, &dbuf); return (ret); }