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

*** 17,114 **** * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ ! /* Copyright © 2003-2011 Emulex. All rights reserved. */ /* * Source file containing Queue handling functions * */ #include <oce_impl.h> - extern struct oce_dev *oce_dev_list[]; int oce_destroy_q(struct oce_dev *oce, struct oce_mbx *mbx, size_t req_size, ! enum qtype qtype); /* MAil box Queue functions */ struct oce_mq * oce_mq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len); /* event queue handling */ ! struct oce_eq * ! oce_eq_create(struct oce_dev *dev, uint32_t q_len, uint32_t item_size, ! uint32_t eq_delay); /* completion queue handling */ struct oce_cq * oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, ! boolean_t nodelay, uint32_t ncoalesce); /* Tx WQ functions */ ! static struct oce_wq *oce_wq_init(struct oce_dev *dev, uint32_t q_len, int wq_type); static void oce_wq_fini(struct oce_dev *dev, struct oce_wq *wq); ! static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq); ! static void oce_wq_del(struct oce_dev *dev, struct oce_wq *wq); /* Rx Queue functions */ ! static struct oce_rq *oce_rq_init(struct oce_dev *dev, uint32_t q_len, ! uint32_t frag_size, uint32_t mtu, ! boolean_t rss); ! static void oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq); ! static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq); ! static void oce_rq_del(struct oce_dev *dev, struct oce_rq *rq); /* * function to create an event queue * * dev - software handle to the device * eqcfg - pointer to a config structure containg the eq parameters * * return pointer to EQ; NULL on failure */ ! struct oce_eq * ! oce_eq_create(struct oce_dev *dev, uint32_t q_len, uint32_t item_size, ! uint32_t eq_delay) { - struct oce_eq *eq; struct oce_mbx mbx; struct mbx_create_common_eq *fwcmd; int ret = 0; - /* allocate an eq */ - eq = kmem_zalloc(sizeof (struct oce_eq), KM_NOSLEEP); - if (eq == NULL) { ! return (NULL); } ! bzero(&mbx, sizeof (struct oce_mbx)); /* allocate mbx */ fwcmd = (struct mbx_create_common_eq *)&mbx.payload; ! eq->ring = create_ring_buffer(dev, q_len, ! item_size, DDI_DMA_CONSISTENT); if (eq->ring == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "EQ ring alloc failed:0x%p", (void *)eq->ring); ! kmem_free(eq, sizeof (struct oce_eq)); ! return (NULL); } mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_CREATE_COMMON_EQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_common_eq)); ! fwcmd->params.req.num_pages = eq->ring->dbuf->num_pages; ! oce_page_list(eq->ring->dbuf, &fwcmd->params.req.pages[0], ! eq->ring->dbuf->num_pages); /* dw 0 */ fwcmd->params.req.eq_ctx.size = (item_size == 4) ? 0 : 1; fwcmd->params.req.eq_ctx.valid = 1; /* dw 1 */ --- 17,122 ---- * 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 Queue handling functions * */ #include <oce_impl.h> int oce_destroy_q(struct oce_dev *oce, struct oce_mbx *mbx, size_t req_size, ! enum qtype qtype, uint32_t mode); /* MAil box Queue functions */ struct oce_mq * + oce_mq_create_ext_v0(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len); + struct oce_mq * + oce_mq_create_ext_v1(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len); + struct oce_mq * oce_mq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len); /* event queue handling */ ! int ! oce_eq_create(struct oce_dev *dev, struct oce_eq *, uint32_t q_len, ! uint32_t item_size, uint32_t eq_delay, uint32_t mode); /* completion queue handling */ struct oce_cq * oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, ! boolean_t nodelay, uint32_t ncoalesce, boolean_t armed, uint32_t mode); + struct oce_cq * + oce_cq_create_v0(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, + uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, + boolean_t nodelay, uint32_t ncoalesce, boolean_t armed, uint32_t mode); + struct oce_cq * + oce_cq_create_v2(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, + uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, + boolean_t nodelay, uint32_t ncoalesce, boolean_t armed, uint32_t mode); + /* Tx WQ functions */ ! int oce_wq_init(struct oce_dev *dev, struct oce_wq *, uint32_t q_len, int wq_type); static void oce_wq_fini(struct oce_dev *dev, struct oce_wq *wq); ! static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq, uint32_t mode); ! static void oce_wq_del(struct oce_dev *dev, struct oce_wq *wq, uint32_t mode); /* Rx Queue functions */ ! static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq, ! uint32_t mode); ! static void oce_rq_del(struct oce_dev *dev, struct oce_rq *rq, uint32_t mode); /* * function to create an event queue * * dev - software handle to the device * eqcfg - pointer to a config structure containg the eq parameters * * return pointer to EQ; NULL on failure */ ! int oce_eq_create(struct oce_dev *dev, struct oce_eq *eq, ! uint32_t q_len, uint32_t item_size, uint32_t eq_delay, uint32_t mode) { struct oce_mbx mbx; struct mbx_create_common_eq *fwcmd; int ret = 0; if (eq == NULL) { ! return (DDI_FAILURE); } ! mutex_enter(&eq->lock); bzero(&mbx, sizeof (struct oce_mbx)); /* allocate mbx */ fwcmd = (struct mbx_create_common_eq *)&mbx.payload; ! eq->ring = oce_create_ring_buffer(dev, q_len, ! item_size, DDI_DMA_CONSISTENT|DDI_DMA_RDWR); if (eq->ring == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "EQ ring alloc failed:0x%p", (void *)eq->ring); ! return (DDI_FAILURE); } mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_CREATE_COMMON_EQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_common_eq), 0); ! fwcmd->params.req.num_pages = eq->ring->dbuf.num_pages; ! oce_page_list(&eq->ring->dbuf, &fwcmd->params.req.pages[0], ! eq->ring->dbuf.num_pages); /* dw 0 */ fwcmd->params.req.eq_ctx.size = (item_size == 4) ? 0 : 1; fwcmd->params.req.eq_ctx.valid = 1; /* dw 1 */
*** 115,125 **** fwcmd->params.req.eq_ctx.armed = 0; fwcmd->params.req.eq_ctx.pd = 0; fwcmd->params.req.eq_ctx.count = OCE_LOG2(q_len/256); /* dw 2 */ - fwcmd->params.req.eq_ctx.function = dev->fn; fwcmd->params.req.eq_ctx.nodelay = 0; fwcmd->params.req.eq_ctx.phase = 0; /* todo: calculate multiplier from max min and cur */ fwcmd->params.req.eq_ctx.delay_mult = eq_delay; --- 123,132 ----
*** 127,156 **** mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_common_eq); 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) { ! oce_log(dev, CE_WARN, MOD_CONFIG, "EQ create failed: %d", ret); destroy_ring_buffer(dev, eq->ring); ! kmem_free(eq, sizeof (struct oce_eq)); ! return (NULL); } /* interpret the response */ eq->eq_id = LE_16(fwcmd->params.rsp.eq_id); - eq->eq_cfg.q_len = q_len; - eq->eq_cfg.item_size = item_size; - eq->eq_cfg.cur_eqd = (uint8_t)eq_delay; eq->parent = (void *)dev; atomic_inc_32(&dev->neqs); oce_log(dev, CE_NOTE, MOD_CONFIG, "EQ created, eq=0x%p eq_id=0x%x", (void *)eq, eq->eq_id); /* Save the eq pointer */ ! return (eq); } /* oce_eq_create */ /* * function to delete an event queue * --- 134,162 ---- mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_common_eq); 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, ! "EQ create failed: 0x%x", ret); destroy_ring_buffer(dev, eq->ring); ! return (DDI_FAILURE); } /* interpret the response */ eq->eq_id = LE_16(fwcmd->params.rsp.eq_id); eq->parent = (void *)dev; atomic_inc_32(&dev->neqs); + eq->qstate = QCREATED; + mutex_exit(&eq->lock); oce_log(dev, CE_NOTE, MOD_CONFIG, "EQ created, eq=0x%p eq_id=0x%x", (void *)eq, eq->eq_id); /* Save the eq pointer */ ! return (DDI_SUCCESS); } /* oce_eq_create */ /* * function to delete an event queue *
*** 158,172 **** * eq - handle to the eq to be deleted * * return 0=>success, failure otherwise */ void ! oce_eq_del(struct oce_dev *dev, struct oce_eq *eq) { struct oce_mbx mbx; struct mbx_destroy_common_eq *fwcmd; /* drain the residual events */ oce_drain_eq(eq); /* destroy the ring */ destroy_ring_buffer(dev, eq->ring); --- 164,182 ---- * eq - handle to the eq to be deleted * * return 0=>success, failure otherwise */ void ! oce_eq_del(struct oce_dev *dev, struct oce_eq *eq, uint32_t mode) { struct oce_mbx mbx; struct mbx_destroy_common_eq *fwcmd; + mutex_enter(&eq->lock); + eq->qstate = QDELETED; + bzero(&mbx, sizeof (struct oce_mbx)); + /* drain the residual events */ oce_drain_eq(eq); /* destroy the ring */ destroy_ring_buffer(dev, eq->ring);
*** 175,235 **** /* send a command to delete the EQ */ fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload; fwcmd->params.req.id = eq->eq_id; (void) oce_destroy_q(dev, &mbx, sizeof (struct mbx_destroy_common_eq), ! QTYPE_EQ); ! kmem_free(eq, sizeof (struct oce_eq)); atomic_dec_32(&dev->neqs); } /* ! * function to create a completion queue * * dev - software handle to the device * eq - optional eq to be associated with to the cq * cqcfg - configuration for this queue * * return pointer to the cq created. NULL on failure */ struct oce_cq * ! oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, ! boolean_t nodelay, uint32_t ncoalesce) { struct oce_cq *cq = NULL; struct oce_mbx mbx; ! struct mbx_create_common_cq *fwcmd; int ret = 0; /* create cq */ cq = kmem_zalloc(sizeof (struct oce_cq), KM_NOSLEEP); if (cq == NULL) { ! oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", "CQ allocation failed"); return (NULL); } /* create the ring buffer for this queue */ ! cq->ring = create_ring_buffer(dev, q_len, ! item_size, DDI_DMA_CONSISTENT); if (cq->ring == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "CQ ring alloc failed:0x%p", (void *)cq->ring); kmem_free(cq, sizeof (struct oce_cq)); return (NULL); } /* initialize mailbox */ bzero(&mbx, sizeof (struct oce_mbx)); ! fwcmd = (struct mbx_create_common_cq *)&mbx.payload; /* fill the command header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_CREATE_COMMON_CQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_common_cq)); /* fill command context */ /* dw0 */ fwcmd->params.req.cq_ctx.eventable = is_eventable; fwcmd->params.req.cq_ctx.sol_event = sol_event; --- 185,245 ---- /* send a command to delete the EQ */ fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload; fwcmd->params.req.id = eq->eq_id; (void) oce_destroy_q(dev, &mbx, sizeof (struct mbx_destroy_common_eq), ! QTYPE_EQ, mode); atomic_dec_32(&dev->neqs); + mutex_exit(&eq->lock); } /* ! * function to create a V0 completion queue * * dev - software handle to the device * eq - optional eq to be associated with to the cq * cqcfg - configuration for this queue * * return pointer to the cq created. NULL on failure */ struct oce_cq * ! oce_cq_create_v0(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, ! boolean_t nodelay, uint32_t ncoalesce, boolean_t armed, uint32_t mode) { struct oce_cq *cq = NULL; struct oce_mbx mbx; ! struct mbx_create_common_cq_v0 *fwcmd; int ret = 0; /* create cq */ cq = kmem_zalloc(sizeof (struct oce_cq), KM_NOSLEEP); if (cq == NULL) { ! oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "CQ allocation failed"); return (NULL); } /* create the ring buffer for this queue */ ! cq->ring = oce_create_ring_buffer(dev, q_len, ! item_size, DDI_DMA_CONSISTENT|DDI_DMA_RDWR); if (cq->ring == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "CQ ring alloc failed:0x%p", (void *)cq->ring); kmem_free(cq, sizeof (struct oce_cq)); return (NULL); } /* initialize mailbox */ bzero(&mbx, sizeof (struct oce_mbx)); ! fwcmd = (struct mbx_create_common_cq_v0 *)&mbx.payload; /* fill the command header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_CREATE_COMMON_CQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_common_cq_v0), 0); /* fill command context */ /* dw0 */ fwcmd->params.req.cq_ctx.eventable = is_eventable; fwcmd->params.req.cq_ctx.sol_event = sol_event;
*** 237,264 **** fwcmd->params.req.cq_ctx.count = OCE_LOG2(q_len/256); fwcmd->params.req.cq_ctx.nodelay = nodelay; fwcmd->params.req.cq_ctx.coalesce_wm = ncoalesce; /* dw1 */ ! fwcmd->params.req.cq_ctx.armed = B_FALSE; fwcmd->params.req.cq_ctx.eq_id = eq->eq_id; fwcmd->params.req.cq_ctx.pd = 0; - /* dw2 */ - fwcmd->params.req.cq_ctx.function = dev->fn; /* fill the rest of the command */ ! fwcmd->params.req.num_pages = cq->ring->dbuf->num_pages; ! oce_page_list(cq->ring->dbuf, &fwcmd->params.req.pages[0], ! cq->ring->dbuf->num_pages); /* fill rest of mbx */ mbx.u0.s.embedded = 1; ! mbx.payload_length = sizeof (struct mbx_create_common_cq); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now send the mail box */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != 0) { oce_log(dev, CE_WARN, MOD_CONFIG, "CQ create failed: 0x%x", ret); destroy_ring_buffer(dev, cq->ring); --- 247,272 ---- fwcmd->params.req.cq_ctx.count = OCE_LOG2(q_len/256); fwcmd->params.req.cq_ctx.nodelay = nodelay; fwcmd->params.req.cq_ctx.coalesce_wm = ncoalesce; /* dw1 */ ! fwcmd->params.req.cq_ctx.armed = armed; fwcmd->params.req.cq_ctx.eq_id = eq->eq_id; fwcmd->params.req.cq_ctx.pd = 0; /* fill the rest of the command */ ! fwcmd->params.req.num_pages = cq->ring->dbuf.num_pages; ! oce_page_list(&cq->ring->dbuf, &fwcmd->params.req.pages[0], ! cq->ring->dbuf.num_pages); /* fill rest of mbx */ mbx.u0.s.embedded = 1; ! mbx.payload_length = sizeof (struct mbx_create_common_cq_v0); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now send the mail box */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { oce_log(dev, CE_WARN, MOD_CONFIG, "CQ create failed: 0x%x", ret); destroy_ring_buffer(dev, cq->ring);
*** 267,296 **** } cq->parent = dev; cq->eq = eq; /* eq array index */ cq->cq_cfg.q_len = q_len; ! cq->cq_cfg.item_size = item_size; ! cq->cq_cfg.sol_eventable = (uint8_t)sol_event; ! cq->cq_cfg.nodelay = (uint8_t)nodelay; /* interpret the response */ cq->cq_id = LE_16(fwcmd->params.rsp.cq_id); dev->cq[cq->cq_id % OCE_MAX_CQ] = cq; atomic_inc_32(&eq->ref_count); return (cq); ! } /* oce_cq_create */ /* * function to delete a completion queue * * dev - software handle to the device * cq - handle to the CQ to delete * * return none */ static void ! oce_cq_del(struct oce_dev *dev, struct oce_cq *cq) { struct oce_mbx mbx; struct mbx_destroy_common_cq *fwcmd; /* destroy the ring */ --- 275,423 ---- } cq->parent = dev; cq->eq = eq; /* eq array index */ cq->cq_cfg.q_len = q_len; ! /* interpret the response */ cq->cq_id = LE_16(fwcmd->params.rsp.cq_id); dev->cq[cq->cq_id % OCE_MAX_CQ] = cq; + cq->qstate = QCREATED; atomic_inc_32(&eq->ref_count); return (cq); ! } /* oce_cq_create_v0 */ /* + * function to create a V2 completion queue + * + * dev - software handle to the device + * eq - optional eq to be associated with to the cq + * cqcfg - configuration for this queue + * + * return pointer to the cq created. NULL on failure + */ + struct oce_cq * + oce_cq_create_v2(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, + uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, + boolean_t nodelay, uint32_t ncoalesce, boolean_t armed, uint32_t mode) + { + struct oce_cq *cq = NULL; + struct oce_mbx mbx; + struct mbx_create_common_cq_v2 *fwcmd; + int ret = 0; + + _NOTE(ARGUNUSED(sol_event)); + _NOTE(ARGUNUSED(ncoalesce)); + /* create cq */ + cq = kmem_zalloc(sizeof (struct oce_cq), KM_NOSLEEP); + if (cq == NULL) { + oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", + "CQ allocation failed"); + return (NULL); + } + + /* create the ring buffer for this queue */ + cq->ring = oce_create_ring_buffer(dev, q_len, + item_size, DDI_DMA_CONSISTENT | DDI_DMA_RDWR); + if (cq->ring == NULL) { + oce_log(dev, CE_WARN, MOD_CONFIG, + "CQ ring alloc failed:0x%p", + (void *)cq->ring); + kmem_free(cq, sizeof (struct oce_cq)); + return (NULL); + } + /* initialize mailbox */ + bzero(&mbx, sizeof (struct oce_mbx)); + fwcmd = (struct mbx_create_common_cq_v2 *)&mbx.payload; + + /* fill the command header */ + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_CREATE_COMMON_CQ, MBX_TIMEOUT_SEC, + sizeof (struct mbx_create_common_cq_v2), 2); + + /* fill command context */ + /* dw0 */ + fwcmd->params.req.cq_ctx.eventable = is_eventable; + fwcmd->params.req.cq_ctx.valid = 1; + fwcmd->params.req.cq_ctx.count = 3; + fwcmd->params.req.cq_ctx.nodelay = nodelay; + fwcmd->params.req.cq_ctx.coalesce_wm = 0; + + /* dw1 */ + fwcmd->params.req.cq_ctx.armed = armed; + fwcmd->params.req.cq_ctx.eq_id = eq->eq_id; + fwcmd->params.req.cq_ctx.cqe_count = q_len; + + fwcmd->params.req.page_size = 1; + /* fill the rest of the command */ + fwcmd->params.req.num_pages = cq->ring->dbuf.num_pages; + oce_page_list(&cq->ring->dbuf, &fwcmd->params.req.pages[0], + cq->ring->dbuf.num_pages); + + /* fill rest of mbx */ + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof (struct mbx_create_common_cq_v2); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + /* now send the mail box */ + ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, mode); + + if (ret != 0) { + oce_log(dev, CE_WARN, MOD_CONFIG, + "CQ create failed: 0x%x", ret); + destroy_ring_buffer(dev, cq->ring); + kmem_free(cq, sizeof (struct oce_cq)); + return (NULL); + } + + cq->parent = dev; + cq->eq = eq; /* eq array index */ + cq->cq_cfg.q_len = q_len; + + /* interpret the response */ + cq->cq_id = LE_16(fwcmd->params.rsp.cq_id); + dev->cq[cq->cq_id % OCE_MAX_CQ] = cq; + cq->qstate = QCREATED; + atomic_inc_32(&eq->ref_count); + return (cq); + } /* oce_cq_create_v2 */ + + /* + * function to create a completion queue + * + * dev - software handle to the device + * eq - optional eq to be associated with to the cq + * cqcfg - configuration for this queue + * + * return pointer to the cq created. NULL on failure + */ + struct oce_cq * + oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, + uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, + boolean_t nodelay, uint32_t ncoalesce, boolean_t armed, uint32_t mode) + { + struct oce_cq *cq = NULL; + if (LANCER_CHIP(dev)) + cq = oce_cq_create_v2(dev, eq, q_len, item_size, sol_event, + is_eventable, nodelay, ncoalesce, armed, mode); + else + cq = oce_cq_create_v0(dev, eq, q_len, item_size, sol_event, + is_eventable, nodelay, ncoalesce, armed, mode); + return (cq); + } + + /* * function to delete a completion queue * * dev - software handle to the device * cq - handle to the CQ to delete * * return none */ static void ! oce_cq_del(struct oce_dev *dev, struct oce_cq *cq, uint32_t mode) { struct oce_mbx mbx; struct mbx_destroy_common_cq *fwcmd; /* destroy the ring */
*** 301,317 **** /* send a command to delete the CQ */ fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload; fwcmd->params.req.id = cq->cq_id; (void) oce_destroy_q(dev, &mbx, sizeof (struct mbx_destroy_common_cq), ! QTYPE_CQ); /* Reset the handler */ cq->cq_handler = NULL; dev->cq[cq->cq_id % OCE_MAX_CQ] = NULL; atomic_dec_32(&cq->eq->ref_count); - mutex_destroy(&cq->lock); /* release the eq */ kmem_free(cq, sizeof (struct oce_cq)); } /* oce_cq_del */ --- 428,444 ---- /* send a command to delete the CQ */ fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload; fwcmd->params.req.id = cq->cq_id; (void) oce_destroy_q(dev, &mbx, sizeof (struct mbx_destroy_common_cq), ! QTYPE_CQ, mode); /* Reset the handler */ cq->cq_handler = NULL; + cq->qstate = QDELETED; dev->cq[cq->cq_id % OCE_MAX_CQ] = NULL; atomic_dec_32(&cq->eq->ref_count); /* release the eq */ kmem_free(cq, sizeof (struct oce_cq)); } /* oce_cq_del */
*** 332,344 **** struct oce_mq *mq = NULL; int ret = 0; struct oce_cq *cq; /* Create the Completion Q */ ! cq = oce_cq_create(dev, eq, CQ_LEN_256, sizeof (struct oce_mq_cqe), ! B_FALSE, B_TRUE, B_TRUE, 0); if (cq == NULL) { return (NULL); } --- 459,471 ---- struct oce_mq *mq = NULL; int ret = 0; struct oce_cq *cq; /* Create the Completion Q */ ! cq = oce_cq_create(dev, eq, MCC_CQ_LEN, sizeof (struct oce_mq_cqe), ! B_FALSE, B_TRUE, B_TRUE, 0, B_FALSE, MBX_BOOTSTRAP); if (cq == NULL) { return (NULL); }
*** 352,378 **** bzero(&mbx, sizeof (struct oce_mbx)); /* allocate mbx */ fwcmd = (struct mbx_create_common_mq *)&mbx.payload; /* create the ring buffer for this queue */ ! mq->ring = create_ring_buffer(dev, q_len, sizeof (struct oce_mbx), DDI_DMA_CONSISTENT | DDI_DMA_RDWR); if (mq->ring == NULL) { ! oce_log(dev, CE_WARN, MOD_CONFIG, ! "MQ ring alloc failed:0x%p", ! (void *)mq->ring); goto mq_ring_alloc; } mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_CREATE_COMMON_MQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_common_mq)); ! fwcmd->params.req.num_pages = mq->ring->dbuf->num_pages; ! oce_page_list(mq->ring->dbuf, fwcmd->params.req.pages, ! mq->ring->dbuf->num_pages); fwcmd->params.req.context.u0.s.cq_id = cq->cq_id; fwcmd->params.req.context.u0.s.ring_size = OCE_LOG2(q_len) + 1; fwcmd->params.req.context.u0.s.valid = 1; fwcmd->params.req.context.u0.s.fid = dev->fn; --- 479,504 ---- bzero(&mbx, sizeof (struct oce_mbx)); /* allocate mbx */ fwcmd = (struct mbx_create_common_mq *)&mbx.payload; /* create the ring buffer for this queue */ ! mq->ring = oce_create_ring_buffer(dev, q_len, sizeof (struct oce_mbx), DDI_DMA_CONSISTENT | DDI_DMA_RDWR); if (mq->ring == NULL) { ! oce_log(dev, CE_WARN, MOD_CONFIG, "%s", ! "Legacy MQ ring alloc failed"); goto mq_ring_alloc; } mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_CREATE_COMMON_MQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_common_mq), 0); ! fwcmd->params.req.num_pages = (uint16_t)mq->ring->dbuf.num_pages; ! oce_page_list(&mq->ring->dbuf, fwcmd->params.req.pages, ! mq->ring->dbuf.num_pages); fwcmd->params.req.context.u0.s.cq_id = cq->cq_id; fwcmd->params.req.context.u0.s.ring_size = OCE_LOG2(q_len) + 1; fwcmd->params.req.context.u0.s.valid = 1; fwcmd->params.req.context.u0.s.fid = dev->fn;
*** 381,394 **** mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_common_mq); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now send the mail box */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != DDI_SUCCESS) { oce_log(dev, CE_WARN, MOD_CONFIG, ! "MQ create failed: 0x%x", ret); goto mq_fail; } /* interpret the response */ mq->mq_id = LE_16(fwcmd->params.rsp.mq_id); --- 507,520 ---- mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_common_mq); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now send the mail box */ ! ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, MBX_BOOTSTRAP); if (ret != DDI_SUCCESS) { oce_log(dev, CE_WARN, MOD_CONFIG, ! "Legacy MQ create failed: 0x%x", ret); goto mq_fail; } /* interpret the response */ mq->mq_id = LE_16(fwcmd->params.rsp.mq_id);
*** 402,423 **** /* set the MQCQ handlers */ cq->cq_handler = oce_drain_mq_cq; cq->cb_arg = (void *)mq; mutex_init(&mq->lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(dev->intr_pri)); return (mq); mq_fail: destroy_ring_buffer(dev, mq->ring); mq_ring_alloc: kmem_free(mq, sizeof (struct oce_mq)); mq_alloc_fail: ! oce_cq_del(dev, cq); return (NULL); } /* oce_mq_create */ /* * function to delete an MQ * * dev - software handle to the device * mq - pointer to the MQ to delete * --- 528,781 ---- /* set the MQCQ handlers */ cq->cq_handler = oce_drain_mq_cq; cq->cb_arg = (void *)mq; mutex_init(&mq->lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(dev->intr_pri)); + oce_log(dev, CE_NOTE, MOD_CONFIG, + "Legacy MQ CREATED SUCCESSFULLY MQID:%d\n", + mq->mq_id); return (mq); mq_fail: destroy_ring_buffer(dev, mq->ring); mq_ring_alloc: kmem_free(mq, sizeof (struct oce_mq)); mq_alloc_fail: ! oce_cq_del(dev, cq, MBX_BOOTSTRAP); return (NULL); } /* oce_mq_create */ /* + * function to create an extended V0 MQ + * + * dev - software handle to the device + * eq - the EQ to associate with the MQ for event notification + * q_len - the number of entries to create in the MQ + * + * return pointer to the created MQ, failure otherwise + */ + struct oce_mq * + oce_mq_create_ext_v0(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len) + { + struct oce_mbx mbx; + struct mbx_create_common_mq_ext_v0 *fwcmd; + struct oce_mq *mq = NULL; + int ret = 0; + struct oce_cq *cq; + + /* Create the Completion Q */ + cq = oce_cq_create(dev, eq, MCC_CQ_LEN, + sizeof (struct oce_mq_cqe), + B_FALSE, B_TRUE, B_TRUE, 0, B_FALSE, MBX_BOOTSTRAP); + if (cq == NULL) { + return (NULL); + } + + + /* allocate the mq */ + mq = kmem_zalloc(sizeof (struct oce_mq), KM_NOSLEEP); + + if (mq == NULL) { + goto mq_alloc_fail; + } + + bzero(&mbx, sizeof (struct oce_mbx)); + /* allocate mbx */ + fwcmd = (struct mbx_create_common_mq_ext_v0 *)&mbx.payload; + + /* create the ring buffer for this queue */ + mq->ring = oce_create_ring_buffer(dev, q_len, + sizeof (struct oce_mbx), DDI_DMA_CONSISTENT | DDI_DMA_RDWR); + if (mq->ring == NULL) { + oce_log(dev, CE_WARN, MOD_CONFIG, "%s", + "MQ EXT ring alloc failed"); + goto mq_ring_alloc; + } + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_CREATE_COMMON_MQ_EXT, MBX_TIMEOUT_SEC, + sizeof (struct mbx_create_common_mq_ext_v0), 0); + + fwcmd->params.req.num_pages = mq->ring->dbuf.num_pages; + oce_page_list(&mq->ring->dbuf, fwcmd->params.req.pages, + mq->ring->dbuf.num_pages); + fwcmd->params.req.context.u0.s.cq_id = cq->cq_id; + fwcmd->params.req.context.u0.s.ring_size = + OCE_LOG2(q_len) + 1; + fwcmd->params.req.context.u0.s.valid = 1; + fwcmd->params.req.context.u0.s.fid = dev->fn; + + /* Register to Link State(bit 1) and Group 5 Events(bit 5) */ + fwcmd->params.req.async_event_bitmap[0] = + (1 << ASYNC_EVENT_CODE_LINK_STATE) | + (1 << ASYNC_EVENT_CODE_GRP_5) | + (1 << ASYNC_EVENT_CODE_DEBUG); + + /* fill rest of mbx */ + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof (struct mbx_create_common_mq_ext_v0); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + /* now send the mail box */ + ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, MBX_BOOTSTRAP); + if (ret != DDI_SUCCESS) { + oce_log(dev, CE_WARN, MOD_CONFIG, + "Extended MQ create failed: 0x%x", ret); + goto mq_fail; + } + + /* interpret the response */ + mq->mq_id = LE_16(fwcmd->params.rsp.mq_id); + mq->cq = cq; + mq->cfg.q_len = (uint8_t)q_len; + mq->cfg.eqd = 0; + + /* fill rest of the mq */ + mq->parent = dev; + mq->qstate = QCREATED; + mq->mq_free = mq->cfg.q_len; + + /* reset indicies */ + mq->ring->cidx = 0; + mq->ring->pidx = 0; + + /* set the MQCQ handlers */ + cq->cq_handler = oce_drain_mq_cq; + cq->cb_arg = (void *)mq; + mutex_init(&mq->lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(dev->intr_pri)); + oce_log(dev, CE_NOTE, MOD_CONFIG, + "Ext MQ CREATED SUCCESSFULLY MQID:%d\n", mq->mq_id); + return (mq); + + mq_fail: + destroy_ring_buffer(dev, mq->ring); + mq_ring_alloc: + kmem_free(mq, sizeof (struct oce_mq)); + mq_alloc_fail: + oce_cq_del(dev, cq, MBX_BOOTSTRAP); + return (NULL); + } /* oce_mq_create_ext_v0 */ + + /* + * function to create an extended V1 MQ + * + * dev - software handle to the device + * eq - the EQ to associate with the MQ for event notification + * q_len - the number of entries to create in the MQ + * + * return pointer to the created MQ, failure otherwise + */ + struct oce_mq * + oce_mq_create_ext_v1(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len) + { + struct oce_mbx mbx; + struct mbx_create_common_mq_ext_v1 *fwcmd; + struct oce_mq *mq = NULL; + int ret = 0; + struct oce_cq *cq; + + /* Create the Completion Q */ + cq = oce_cq_create(dev, eq, MCC_CQ_LEN, + sizeof (struct oce_mq_cqe), + B_FALSE, B_TRUE, B_TRUE, 0, B_FALSE, MBX_BOOTSTRAP); + if (cq == NULL) { + return (NULL); + } + + + /* allocate the mq */ + mq = kmem_zalloc(sizeof (struct oce_mq), KM_NOSLEEP); + + if (mq == NULL) { + goto mq_alloc_fail; + } + + bzero(&mbx, sizeof (struct oce_mbx)); + /* allocate mbx */ + fwcmd = (struct mbx_create_common_mq_ext_v1 *)&mbx.payload; + + /* create the ring buffer for this queue */ + mq->ring = oce_create_ring_buffer(dev, q_len, + sizeof (struct oce_mbx), DDI_DMA_CONSISTENT | DDI_DMA_RDWR); + if (mq->ring == NULL) { + oce_log(dev, CE_WARN, MOD_CONFIG, "%s", + "MQ EXT ring alloc failed"); + goto mq_ring_alloc; + } + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_CREATE_COMMON_MQ_EXT, MBX_TIMEOUT_SEC, + sizeof (struct mbx_create_common_mq_ext_v1), 1); + + fwcmd->params.req.cq_id = cq->cq_id; + + fwcmd->params.req.context.u0.s.ring_size = + OCE_LOG2(q_len) + 1; + fwcmd->params.req.context.u0.s.valid = 1; + fwcmd->params.req.context.u0.s.async_cq_id = cq->cq_id; + fwcmd->params.req.context.u0.s.async_cq_valid = 1; + + fwcmd->params.req.num_pages = mq->ring->dbuf.num_pages; + oce_page_list(&mq->ring->dbuf, fwcmd->params.req.pages, + mq->ring->dbuf.num_pages); + + /* Register to Link State(bit 1) and Group 5 Events(bit 5) */ + fwcmd->params.req.async_event_bitmap[0] = + (1 << ASYNC_EVENT_CODE_LINK_STATE) | + (1 << ASYNC_EVENT_CODE_GRP_5) | + (1 << ASYNC_EVENT_CODE_DEBUG); + + /* fill rest of mbx */ + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof (struct mbx_create_common_mq_ext_v1); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + /* now send the mail box */ + ret = oce_issue_mbox_cmd(dev, &mbx, MBX_TIMEOUT_SEC, MBX_BOOTSTRAP); + if (ret != DDI_SUCCESS) { + oce_log(dev, CE_WARN, MOD_CONFIG, + "Extended MQ create failed: 0x%x", ret); + goto mq_fail; + } + + /* interpret the response */ + mq->mq_id = LE_16(fwcmd->params.rsp.mq_id); + mq->cq = cq; + mq->cfg.q_len = (uint8_t)q_len; + mq->cfg.eqd = 0; + + /* fill rest of the mq */ + mq->parent = dev; + mq->qstate = QCREATED; + mq->mq_free = mq->cfg.q_len; + + /* reset indicies */ + mq->ring->cidx = 0; + mq->ring->pidx = 0; + + /* set the MQCQ handlers */ + cq->cq_handler = oce_drain_mq_cq; + cq->cb_arg = (void *)mq; + mutex_init(&mq->lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(dev->intr_pri)); + oce_log(dev, CE_NOTE, MOD_CONFIG, + "Ext MQ CREATED SUCCESSFULLY MQID:%d\n", mq->mq_id); + return (mq); + + mq_fail: + destroy_ring_buffer(dev, mq->ring); + mq_ring_alloc: + kmem_free(mq, sizeof (struct oce_mq)); + mq_alloc_fail: + oce_cq_del(dev, cq, MBX_BOOTSTRAP); + return (NULL); + } /* oce_mq_create_ext_v0 */ + + /* * function to delete an MQ * * dev - software handle to the device * mq - pointer to the MQ to delete *
*** 435,447 **** bzero(&mbx, sizeof (struct oce_mbx)); fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload; fwcmd->params.req.id = mq->mq_id; (void) oce_destroy_q(dev, &mbx, sizeof (struct mbx_destroy_common_mq), ! QTYPE_MQ); ! oce_cq_del(dev, mq->cq); mq->cq = NULL; mutex_destroy(&mq->lock); kmem_free(mq, sizeof (struct oce_mq)); } /* oce_mq_del */ /* --- 793,806 ---- bzero(&mbx, sizeof (struct oce_mbx)); fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload; fwcmd->params.req.id = mq->mq_id; (void) oce_destroy_q(dev, &mbx, sizeof (struct mbx_destroy_common_mq), ! QTYPE_MQ, MBX_BOOTSTRAP); ! oce_cq_del(dev, mq->cq, MBX_BOOTSTRAP); mq->cq = NULL; + mq->qstate = QDELETED; mutex_destroy(&mq->lock); kmem_free(mq, sizeof (struct oce_mq)); } /* oce_mq_del */ /*
*** 450,501 **** * dev - software handle to the device * wqcfg - configuration structure providing WQ config parameters * * return pointer to the WQ created. NULL on failure */ ! static struct oce_wq * ! oce_wq_init(struct oce_dev *dev, uint32_t q_len, int wq_type) { - struct oce_wq *wq; char str[MAX_POOL_NAME]; int ret; static int wq_id = 0; ASSERT(dev != NULL); /* q_len must be min 256 and max 2k */ if (q_len < 256 || q_len > 2048) { oce_log(dev, CE_WARN, MOD_CONFIG, "Invalid q length. Must be " "[256, 2000]: 0x%x", q_len); ! return (NULL); } - /* allocate wq */ - wq = kmem_zalloc(sizeof (struct oce_wq), KM_NOSLEEP); - if (wq == NULL) { - oce_log(dev, CE_WARN, MOD_CONFIG, "%s", - "WQ allocation failed"); - return (NULL); - } - /* Set the wq config */ wq->cfg.q_len = q_len; wq->cfg.wq_type = (uint8_t)wq_type; wq->cfg.eqd = OCE_DEFAULT_WQ_EQD; wq->cfg.nbufs = 2 * wq->cfg.q_len; wq->cfg.nhdl = 2 * wq->cfg.q_len; - wq->cfg.buf_size = dev->tx_bcopy_limit; ! /* assign parent */ ! wq->parent = (void *)dev; /* Create the WQ Buffer pool */ ret = oce_wqb_cache_create(wq, wq->cfg.buf_size); if (ret != DDI_SUCCESS) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "WQ Buffer Pool create failed "); ! goto wqb_fail; } /* Create a pool of memory handles */ ret = oce_wqm_cache_create(wq); if (ret != DDI_SUCCESS) { --- 809,856 ---- * dev - software handle to the device * wqcfg - configuration structure providing WQ config parameters * * return pointer to the WQ created. NULL on failure */ ! int oce_wq_init(struct oce_dev *dev, struct oce_wq *wq, uint32_t q_len, ! int wq_type) { char str[MAX_POOL_NAME]; int ret; static int wq_id = 0; + int buf_size; ASSERT(dev != NULL); /* q_len must be min 256 and max 2k */ if (q_len < 256 || q_len > 2048) { oce_log(dev, CE_WARN, MOD_CONFIG, "Invalid q length. Must be " "[256, 2000]: 0x%x", q_len); ! return (DDI_FAILURE); } /* Set the wq config */ wq->cfg.q_len = q_len; wq->cfg.wq_type = (uint8_t)wq_type; wq->cfg.eqd = OCE_DEFAULT_WQ_EQD; wq->cfg.nbufs = 2 * wq->cfg.q_len; wq->cfg.nhdl = 2 * wq->cfg.q_len; ! buf_size = ((dev->tx_bcopy_limit >> 10) + ! ((dev->tx_bcopy_limit & (((uint32_t)1 << 10) - 1)) > 0 ? 1 : ! 0)) << 10; ! wq->cfg.buf_size = (uint16_t)buf_size; + /* initialize ring statistics */ + wq->stat_bytes = wq->stat_pkts = 0; + /* Create the WQ Buffer pool */ ret = oce_wqb_cache_create(wq, wq->cfg.buf_size); if (ret != DDI_SUCCESS) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "WQ Buffer Pool create failed "); ! return (DDI_FAILURE); } /* Create a pool of memory handles */ ret = oce_wqm_cache_create(wq); if (ret != DDI_SUCCESS) {
*** 513,523 **** "WQ Packet Desc Pool create failed "); goto wqed_fail; } /* create the ring buffer */ ! wq->ring = create_ring_buffer(dev, q_len, NIC_WQE_SIZE, DDI_DMA_CONSISTENT | DDI_DMA_RDWR); if (wq->ring == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "Failed to create WQ ring "); goto wq_ringfail; --- 868,878 ---- "WQ Packet Desc Pool create failed "); goto wqed_fail; } /* create the ring buffer */ ! wq->ring = oce_create_ring_buffer(dev, q_len, NIC_WQE_SIZE, DDI_DMA_CONSISTENT | DDI_DMA_RDWR); if (wq->ring == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "Failed to create WQ ring "); goto wq_ringfail;
*** 529,552 **** /* Initialize WQ lock */ mutex_init(&wq->txc_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(dev->intr_pri)); atomic_inc_32(&dev->nwqs); ! OCE_LIST_CREATE(&wq->wqe_desc_list, DDI_INTR_PRI(dev->intr_pri)); ! return (wq); wqcq_fail: destroy_ring_buffer(dev, wq->ring); wq_ringfail: kmem_cache_destroy(wq->wqed_cache); wqed_fail: oce_wqm_cache_destroy(wq); wqm_fail: oce_wqb_cache_destroy(wq); ! wqb_fail: ! kmem_free(wq, sizeof (struct oce_wq)); ! return (NULL); } /* oce_wq_create */ /* * function to delete a WQ * --- 884,909 ---- /* Initialize WQ lock */ mutex_init(&wq->txc_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(dev->intr_pri)); atomic_inc_32(&dev->nwqs); ! mutex_init(&wq->wqed_list_lock, NULL, MUTEX_DRIVER, ! DDI_INTR_PRI(dev->intr_pri)); + list_create(&wq->wqe_desc_list, sizeof (oce_wqe_desc_t), + offsetof(oce_wqe_desc_t, link)); + return (DDI_SUCCESS); + wqcq_fail: destroy_ring_buffer(dev, wq->ring); wq_ringfail: kmem_cache_destroy(wq->wqed_cache); wqed_fail: oce_wqm_cache_destroy(wq); wqm_fail: oce_wqb_cache_destroy(wq); ! return (DDI_FAILURE); } /* oce_wq_create */ /* * function to delete a WQ *
*** 562,584 **** oce_wqb_cache_destroy(wq); oce_wqm_cache_destroy(wq); kmem_cache_destroy(wq->wqed_cache); /* Free the packet descriptor list */ ! OCE_LIST_DESTROY(&wq->wqe_desc_list); destroy_ring_buffer(dev, wq->ring); wq->ring = NULL; /* Destroy the Mutex */ mutex_destroy(&wq->tx_lock); mutex_destroy(&wq->txc_lock); - kmem_free(wq, sizeof (struct oce_wq)); atomic_dec_32(&dev->nwqs); } /* oce_wq_del */ static int ! oce_wq_create(struct oce_wq *wq, struct oce_eq *eq) { struct oce_mbx mbx; struct mbx_create_nic_wq *fwcmd; struct oce_dev *dev = wq->parent; --- 919,941 ---- oce_wqb_cache_destroy(wq); oce_wqm_cache_destroy(wq); kmem_cache_destroy(wq->wqed_cache); /* Free the packet descriptor list */ ! list_destroy(&wq->wqe_desc_list); destroy_ring_buffer(dev, wq->ring); wq->ring = NULL; /* Destroy the Mutex */ + mutex_destroy(&wq->wqed_list_lock); mutex_destroy(&wq->tx_lock); mutex_destroy(&wq->txc_lock); atomic_dec_32(&dev->nwqs); } /* oce_wq_del */ static int ! oce_wq_create(struct oce_wq *wq, struct oce_eq *eq, uint32_t mode) { struct oce_mbx mbx; struct mbx_create_nic_wq *fwcmd; struct oce_dev *dev = wq->parent;
*** 586,637 **** int ret; /* create the CQ */ cq = oce_cq_create(dev, eq, CQ_LEN_1024, sizeof (struct oce_nic_tx_cqe), ! B_FALSE, B_TRUE, B_FALSE, 3); if (cq == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", ! "WCCQ create failed "); return (DDI_FAILURE); } /* now fill the command */ bzero(&mbx, sizeof (struct oce_mbx)); fwcmd = (struct mbx_create_nic_wq *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, OPCODE_CREATE_NIC_WQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_nic_wq)); ! fwcmd->params.req.nic_wq_type = (uint8_t)wq->cfg.wq_type; ! fwcmd->params.req.num_pages = wq->ring->dbuf->num_pages; oce_log(dev, CE_NOTE, MOD_CONFIG, "NUM_PAGES = 0x%d size = %lu", ! (uint32_t)wq->ring->dbuf->num_pages, ! wq->ring->dbuf->size); ! /* workaround: fill 0x01 for ulp_mask in rsvd0 */ ! fwcmd->params.req.rsvd0 = 0x01; ! fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1; ! fwcmd->params.req.valid = 1; ! fwcmd->params.req.pd_id = 0; ! fwcmd->params.req.pci_function_id = dev->fn; ! fwcmd->params.req.cq_id = cq->cq_id; ! oce_page_list(wq->ring->dbuf, fwcmd->params.req.pages, ! wq->ring->dbuf->num_pages); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_nic_wq); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* now post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != DDI_SUCCESS) { oce_log(dev, CE_WARN, MOD_CONFIG, ! "WQ create failed: %d", ret); ! oce_cq_del(dev, cq); return (ret); } /* interpret the response */ wq->wq_id = LE_16(fwcmd->params.rsp.wq_id); --- 943,1002 ---- int ret; /* create the CQ */ cq = oce_cq_create(dev, eq, CQ_LEN_1024, sizeof (struct oce_nic_tx_cqe), ! B_FALSE, B_TRUE, B_FALSE, 3, B_FALSE, mode); if (cq == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", ! "WQCQ create failed "); return (DDI_FAILURE); } /* now fill the command */ bzero(&mbx, sizeof (struct oce_mbx)); fwcmd = (struct mbx_create_nic_wq *)&mbx.payload; + if (LANCER_CHIP(dev)) { mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, OPCODE_CREATE_NIC_WQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_nic_wq), 1); ! fwcmd->params.req.ctx.if_id = dev->if_id; ! } else { ! mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, ! MBX_SUBSYSTEM_NIC, ! OPCODE_CREATE_NIC_WQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_nic_wq), 0); ! } ! fwcmd->params.req.type = (uint8_t)wq->cfg.wq_type; ! fwcmd->params.req.num_pages = wq->ring->dbuf.num_pages; ! fwcmd->params.req.ulp_num = BE_ULP1_NUM; oce_log(dev, CE_NOTE, MOD_CONFIG, "NUM_PAGES = 0x%d size = %lu", ! (uint32_t)wq->ring->dbuf.num_pages, ! wq->ring->dbuf.size); ! /* Context info */ ! fwcmd->params.req.ctx.wq_size = OCE_LOG2(wq->cfg.q_len) + 1; ! fwcmd->params.req.ctx.valid = 1; ! fwcmd->params.req.ctx.cofe = 1; ! fwcmd->params.req.ctx.no_rem_allowed = 1; ! fwcmd->params.req.ctx.cq_id = cq->cq_id; ! oce_page_list(&wq->ring->dbuf, fwcmd->params.req.pages, ! wq->ring->dbuf.num_pages); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_nic_wq); 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 != DDI_SUCCESS) { oce_log(dev, CE_WARN, MOD_CONFIG, ! "WQ create failed: 0x%x", ret); ! oce_cq_del(dev, cq, mode); return (ret); } /* interpret the response */ wq->wq_id = LE_16(fwcmd->params.rsp.wq_id);
*** 638,647 **** --- 1003,1013 ---- wq->qstate = QCREATED; wq->cq = cq; /* set the WQCQ handlers */ wq->cq->cq_handler = oce_drain_wq_cq; wq->cq->cb_arg = (void *)wq; + /* All are free to start with */ wq->wq_free = wq->cfg.q_len; /* reset indicies */ wq->ring->cidx = 0; wq->ring->pidx = 0;
*** 658,685 **** * wq - WQ to delete * * return none */ static void ! oce_wq_del(struct oce_dev *dev, struct oce_wq *wq) { struct oce_mbx mbx; struct mbx_delete_nic_wq *fwcmd; - ASSERT(dev != NULL); ASSERT(wq != NULL); if (wq->qstate == QCREATED) { bzero(&mbx, sizeof (struct oce_mbx)); /* now fill the command */ fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload; fwcmd->params.req.wq_id = wq->wq_id; (void) oce_destroy_q(dev, &mbx, sizeof (struct mbx_delete_nic_wq), ! QTYPE_WQ); wq->qstate = QDELETED; ! oce_cq_del(dev, wq->cq); wq->cq = NULL; } } /* oce_wq_del */ /* --- 1024,1050 ---- * wq - WQ to delete * * return none */ static void ! oce_wq_del(struct oce_dev *dev, struct oce_wq *wq, uint32_t mode) { struct oce_mbx mbx; struct mbx_delete_nic_wq *fwcmd; ASSERT(dev != NULL); ASSERT(wq != NULL); if (wq->qstate == QCREATED) { bzero(&mbx, sizeof (struct oce_mbx)); /* now fill the command */ fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload; fwcmd->params.req.wq_id = wq->wq_id; (void) oce_destroy_q(dev, &mbx, sizeof (struct mbx_delete_nic_wq), ! QTYPE_WQ, mode); wq->qstate = QDELETED; ! oce_cq_del(dev, wq->cq, mode); wq->cq = NULL; } } /* oce_wq_del */ /*
*** 688,736 **** * dev - software handle to the device * rqcfg - configuration structure providing RQ config parameters * * return pointer to the RQ created. NULL on failure */ ! static struct oce_rq * ! oce_rq_init(struct oce_dev *dev, uint32_t q_len, ! uint32_t frag_size, uint32_t mtu, ! boolean_t rss) { - - struct oce_rq *rq; int ret; /* validate q creation parameters */ if (!OCE_LOG2(frag_size)) return (NULL); if ((q_len == 0) || (q_len > 1024)) return (NULL); - /* allocate the rq */ - rq = kmem_zalloc(sizeof (struct oce_rq), KM_NOSLEEP); - if (rq == NULL) { - oce_log(dev, CE_WARN, MOD_CONFIG, "%s", - "RQ allocation failed"); - return (NULL); - } - rq->cfg.q_len = q_len; rq->cfg.frag_size = frag_size; rq->cfg.mtu = mtu; rq->cfg.eqd = 0; rq->cfg.nbufs = dev->rq_max_bufs; - rq->cfg.is_rss_queue = rss; ! /* assign parent */ ! rq->parent = (void *)dev; rq->rq_bdesc_array = kmem_zalloc((sizeof (oce_rq_bdesc_t) * rq->cfg.nbufs), KM_NOSLEEP); if (rq->rq_bdesc_array == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "RQ bdesc alloc failed"); ! goto rqbd_alloc_fail; } /* create the rq buffer descriptor ring */ rq->shadow_ring = kmem_zalloc((rq->cfg.q_len * sizeof (oce_rq_bdesc_t *)), KM_NOSLEEP); --- 1053,1088 ---- * dev - software handle to the device * rqcfg - configuration structure providing RQ config parameters * * return pointer to the RQ created. NULL on failure */ ! int oce_rq_init(struct oce_dev *dev, struct oce_rq *rq, uint32_t q_len, ! uint32_t frag_size, uint32_t mtu) { int ret; /* validate q creation parameters */ if (!OCE_LOG2(frag_size)) return (NULL); if ((q_len == 0) || (q_len > 1024)) return (NULL); rq->cfg.q_len = q_len; rq->cfg.frag_size = frag_size; rq->cfg.mtu = mtu; rq->cfg.eqd = 0; rq->cfg.nbufs = dev->rq_max_bufs; ! /* initialize ring statistics */ ! rq->stat_bytes = rq->stat_pkts = 0; rq->rq_bdesc_array = kmem_zalloc((sizeof (oce_rq_bdesc_t) * rq->cfg.nbufs), KM_NOSLEEP); if (rq->rq_bdesc_array == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "RQ bdesc alloc failed"); ! return (DDI_FAILURE); } /* create the rq buffer descriptor ring */ rq->shadow_ring = kmem_zalloc((rq->cfg.q_len * sizeof (oce_rq_bdesc_t *)), KM_NOSLEEP);
*** 745,762 **** kmem_zalloc(rq->cfg.nbufs * sizeof (oce_rq_bdesc_t *), KM_NOSLEEP); if (rq->rqb_freelist == NULL) { goto rqb_free_list_fail; } /* create the buffer pool */ ! ret = oce_rqb_cache_create(rq, dev->rq_frag_size + ! OCE_RQE_BUF_HEADROOM); if (ret != DDI_SUCCESS) { goto rqb_fail; } /* create the ring buffer */ ! rq->ring = create_ring_buffer(dev, q_len, sizeof (struct oce_nic_rqe), DDI_DMA_CONSISTENT | DDI_DMA_RDWR); if (rq->ring == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "RQ ring create failed "); goto rq_ringfail; --- 1097,1113 ---- kmem_zalloc(rq->cfg.nbufs * sizeof (oce_rq_bdesc_t *), KM_NOSLEEP); if (rq->rqb_freelist == NULL) { goto rqb_free_list_fail; } /* create the buffer pool */ ! ret = oce_rqb_cache_create(rq, rq->cfg.frag_size); if (ret != DDI_SUCCESS) { goto rqb_fail; } /* create the ring buffer */ ! rq->ring = oce_create_ring_buffer(dev, q_len, sizeof (struct oce_nic_rqe), DDI_DMA_CONSISTENT | DDI_DMA_RDWR); if (rq->ring == NULL) { oce_log(dev, CE_WARN, MOD_CONFIG, "%s", "RQ ring create failed "); goto rq_ringfail;
*** 767,777 **** DDI_INTR_PRI(dev->intr_pri)); /* Initialize the recharge lock */ mutex_init(&rq->rc_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(dev->intr_pri)); atomic_inc_32(&dev->nrqs); ! return (rq); rq_ringfail: oce_rqb_cache_destroy(rq); rqb_fail: kmem_free(rq->rqb_freelist, --- 1118,1128 ---- DDI_INTR_PRI(dev->intr_pri)); /* Initialize the recharge lock */ mutex_init(&rq->rc_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(dev->intr_pri)); atomic_inc_32(&dev->nrqs); ! return (DDI_SUCCESS); rq_ringfail: oce_rqb_cache_destroy(rq); rqb_fail: kmem_free(rq->rqb_freelist,
*** 781,807 **** kmem_free(rq->shadow_ring, (rq->cfg.q_len * sizeof (oce_rq_bdesc_t *))); rq_shdw_fail: kmem_free(rq->rq_bdesc_array, (sizeof (oce_rq_bdesc_t) * rq->cfg.nbufs)); ! rqbd_alloc_fail: ! kmem_free(rq, sizeof (struct oce_rq)); ! return (NULL); } /* oce_rq_create */ /* * function to delete an RQ * * dev - software handle to the device * rq - RQ to delete * * return none */ ! static void oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq) { /* Destroy buffer cache */ oce_rqb_cache_destroy(rq); destroy_ring_buffer(dev, rq->ring); rq->ring = NULL; kmem_free(rq->shadow_ring, sizeof (oce_rq_bdesc_t *) * rq->cfg.q_len); --- 1132,1158 ---- kmem_free(rq->shadow_ring, (rq->cfg.q_len * sizeof (oce_rq_bdesc_t *))); rq_shdw_fail: kmem_free(rq->rq_bdesc_array, (sizeof (oce_rq_bdesc_t) * rq->cfg.nbufs)); ! return (DDI_FAILURE); } /* oce_rq_create */ + /* * function to delete an RQ * * dev - software handle to the device * rq - RQ to delete * * return none */ ! void oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq) { /* Destroy buffer cache */ + rq->qstate = QFINI; oce_rqb_cache_destroy(rq); destroy_ring_buffer(dev, rq->ring); rq->ring = NULL; kmem_free(rq->shadow_ring, sizeof (oce_rq_bdesc_t *) * rq->cfg.q_len);
*** 812,838 **** kmem_free(rq->rqb_freelist, (rq->cfg.nbufs * sizeof (oce_rq_bdesc_t *))); rq->rqb_freelist = NULL; mutex_destroy(&rq->rx_lock); mutex_destroy(&rq->rc_lock); - kmem_free(rq, sizeof (struct oce_rq)); atomic_dec_32(&dev->nrqs); } /* oce_rq_del */ static int ! oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq) { struct oce_mbx mbx; struct mbx_create_nic_rq *fwcmd; struct oce_dev *dev = rq->parent; struct oce_cq *cq; int ret; ! cq = oce_cq_create(dev, eq, CQ_LEN_1024, sizeof (struct oce_nic_rx_cqe), ! B_FALSE, B_TRUE, B_FALSE, 3); if (cq == NULL) { return (DDI_FAILURE); } /* now fill the command */ --- 1163,1195 ---- kmem_free(rq->rqb_freelist, (rq->cfg.nbufs * sizeof (oce_rq_bdesc_t *))); rq->rqb_freelist = NULL; mutex_destroy(&rq->rx_lock); mutex_destroy(&rq->rc_lock); atomic_dec_32(&dev->nrqs); } /* oce_rq_del */ static int ! oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq, ! uint32_t mode) { struct oce_mbx mbx; struct mbx_create_nic_rq *fwcmd; struct oce_dev *dev = rq->parent; struct oce_cq *cq; + int cq_len; int ret; ! if (LANCER_CHIP(dev)) ! cq_len = CQ_LEN_2048; ! else ! cq_len = CQ_LEN_1024; + cq = oce_cq_create(dev, eq, cq_len, sizeof (struct oce_nic_rx_cqe), + B_FALSE, B_TRUE, B_FALSE, 3, B_FALSE, mode); + if (cq == NULL) { return (DDI_FAILURE); } /* now fill the command */
*** 839,855 **** bzero(&mbx, sizeof (struct oce_mbx)); fwcmd = (struct mbx_create_nic_rq *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, OPCODE_CREATE_NIC_RQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_nic_rq)); ! fwcmd->params.req.num_pages = rq->ring->dbuf->num_pages; fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size); fwcmd->params.req.cq_id = cq->cq_id; ! oce_page_list(rq->ring->dbuf, fwcmd->params.req.pages, ! rq->ring->dbuf->num_pages); fwcmd->params.req.if_id = if_id; fwcmd->params.req.max_frame_size = (uint16_t)rq->cfg.mtu; fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue; --- 1196,1212 ---- bzero(&mbx, sizeof (struct oce_mbx)); fwcmd = (struct mbx_create_nic_rq *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, OPCODE_CREATE_NIC_RQ, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_create_nic_rq), 0); ! fwcmd->params.req.num_pages = rq->ring->dbuf.num_pages; fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size); fwcmd->params.req.cq_id = cq->cq_id; ! oce_page_list(&rq->ring->dbuf, fwcmd->params.req.pages, ! rq->ring->dbuf.num_pages); fwcmd->params.req.if_id = if_id; fwcmd->params.req.max_frame_size = (uint16_t)rq->cfg.mtu; fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
*** 857,871 **** mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_nic_rq); 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) { oce_log(dev, CE_WARN, MOD_CONFIG, ! "RQ create failed: %d", ret); ! oce_cq_del(dev, cq); return (ret); } /* interpret the response */ rq->rq_id = LE_16(fwcmd->params.rsp.u0.s.rq_id); --- 1214,1228 ---- mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_create_nic_rq); 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, ! "RQ create failed: 0x%x", ret); ! oce_cq_del(dev, cq, MBX_BOOTSTRAP); return (ret); } /* interpret the response */ rq->rq_id = LE_16(fwcmd->params.rsp.u0.s.rq_id);
*** 875,889 **** rq->cq = cq; /* set the Completion Handler */ rq->cq->cq_handler = oce_drain_rq_cq; rq->cq->cb_arg = (void *)rq; /* reset the indicies */ rq->ring->cidx = 0; rq->ring->pidx = 0; rq->buf_avail = 0; ! oce_log(dev, CE_NOTE, MOD_CONFIG, "RQ created, RQID : %d", rq->rq_id); return (0); } /* --- 1232,1248 ---- rq->cq = cq; /* set the Completion Handler */ rq->cq->cq_handler = oce_drain_rq_cq; rq->cq->cb_arg = (void *)rq; + /* reset the indicies */ rq->ring->cidx = 0; rq->ring->pidx = 0; rq->buf_avail = 0; ! oce_log(dev, CE_NOTE, MOD_CONFIG, "RQ created, RQID : %d, cpu-id = %d", ! rq->rq_id, rq->rss_cpuid); return (0); } /*
*** 893,926 **** * rq - RQ to delete * * return none */ static void ! oce_rq_del(struct oce_dev *dev, struct oce_rq *rq) { struct oce_mbx mbx; struct mbx_delete_nic_rq *fwcmd; ASSERT(dev != NULL); ASSERT(rq != NULL); bzero(&mbx, sizeof (struct oce_mbx)); /* delete the Queue */ if (rq->qstate == QCREATED) { fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; fwcmd->params.req.rq_id = rq->rq_id; (void) oce_destroy_q(dev, &mbx, ! sizeof (struct mbx_delete_nic_rq), QTYPE_RQ); ! rq->qstate = QDELETED; oce_clean_rq(rq); /* Delete the associated CQ */ ! oce_cq_del(dev, rq->cq); rq->cq = NULL; /* free up the posted buffers */ oce_rq_discharge(rq); } } /* oce_rq_del */ /* * function to arm an EQ so that it can generate events * --- 1252,1287 ---- * rq - RQ to delete * * return none */ static void ! oce_rq_del(struct oce_dev *dev, struct oce_rq *rq, uint32_t mode) { struct oce_mbx mbx; struct mbx_delete_nic_rq *fwcmd; ASSERT(dev != NULL); ASSERT(rq != NULL); bzero(&mbx, sizeof (struct oce_mbx)); + mutex_enter(&rq->rx_lock); /* delete the Queue */ if (rq->qstate == QCREATED) { fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; fwcmd->params.req.rq_id = rq->rq_id; (void) oce_destroy_q(dev, &mbx, ! sizeof (struct mbx_delete_nic_rq), QTYPE_RQ, mode); oce_clean_rq(rq); /* Delete the associated CQ */ ! oce_cq_del(dev, rq->cq, mode); rq->cq = NULL; /* free up the posted buffers */ oce_rq_discharge(rq); + (void) atomic_swap_32(&rq->qstate, QDELETED); } + mutex_exit(&rq->rx_lock); } /* oce_rq_del */ /* * function to arm an EQ so that it can generate events *
*** 939,948 **** --- 1300,1312 ---- { eq_db_t eq_db = {0}; eq_db.bits.rearm = rearm; eq_db.bits.event = B_TRUE; + eq_db.bits.eq_cq_extid = + (((uint64_t)qid & (uint64_t)DB_EQ_RING_ID_EXT_MASK) << + (uint64_t)DB_EQ_RING_ID_EXT_MASK_SHIFT); eq_db.bits.num_popped = npopped; eq_db.bits.clrint = clearint; eq_db.bits.qid = qid; OCE_DB_WRITE32(dev, PD_EQ_DB, eq_db.dw0); }
*** 961,970 **** --- 1325,1337 ---- oce_arm_cq(struct oce_dev *dev, int16_t qid, int npopped, boolean_t rearm) { cq_db_t cq_db = {0}; cq_db.bits.rearm = rearm; + cq_db.bits.eq_cq_extid = + (((uint64_t)qid & (uint64_t)DB_CQ_RING_ID_EXT_MASK) << + (uint64_t)DB_CQ_RING_ID_EXT_MASK_SHIFT); cq_db.bits.num_popped = npopped; cq_db.bits.event = 0; cq_db.bits.qid = qid; OCE_DB_WRITE32(dev, PD_CQ_DB, cq_db.dw0); }
*** 981,991 **** * * return DDI_SUCCESS => success, failure otherwise */ int oce_destroy_q(struct oce_dev *dev, struct oce_mbx *mbx, size_t req_size, ! enum qtype qtype) { struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload; int opcode; int subsys; int ret; --- 1348,1358 ---- * * return DDI_SUCCESS => success, failure otherwise */ int oce_destroy_q(struct oce_dev *dev, struct oce_mbx *mbx, size_t req_size, ! enum qtype qtype, uint32_t mode) { struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload; int opcode; int subsys; int ret;
*** 1021,1044 **** break; } } mbx_common_req_hdr_init(hdr, 0, 0, subsys, ! opcode, MBX_TIMEOUT_SEC, req_size); /* fill rest of mbx */ mbx->u0.s.embedded = 1; mbx->payload_length = (uint32_t)req_size; DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ); /* send command */ ! ret = oce_mbox_post(dev, mbx, NULL); ! if (ret != 0) { ! oce_log(dev, CE_WARN, MOD_CONFIG, "%s", ! "Failed to del q "); } return (ret); } /* * function to set the delay parameter in the EQ for interrupt coalescing --- 1388,1411 ---- break; } } mbx_common_req_hdr_init(hdr, 0, 0, subsys, ! opcode, MBX_TIMEOUT_SEC, req_size, 0); /* fill rest of mbx */ mbx->u0.s.embedded = 1; mbx->payload_length = (uint32_t)req_size; DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ); /* send command */ ! ret = oce_issue_mbox_cmd(dev, mbx, MBX_TIMEOUT_SEC, mode); if (ret != 0) { ! oce_log(dev, CE_WARN, MOD_CONFIG, ! "Failed to del q: 0x%x", ret); } + return (ret); } /* * function to set the delay parameter in the EQ for interrupt coalescing
*** 1050,1060 **** * * return DDI_SUCCESS => success, failure otherwise */ int oce_set_eq_delay(struct oce_dev *dev, uint32_t *eq_arr, ! uint32_t eq_cnt, uint32_t eq_delay) { struct oce_mbx mbx; struct mbx_modify_common_eq_delay *fwcmd; int ret; int neq; --- 1417,1427 ---- * * return DDI_SUCCESS => success, failure otherwise */ int oce_set_eq_delay(struct oce_dev *dev, uint32_t *eq_arr, ! uint32_t eq_cnt, uint32_t eq_delay, uint32_t mode) { struct oce_mbx mbx; struct mbx_modify_common_eq_delay *fwcmd; int ret; int neq;
*** 1074,1095 **** /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_MODIFY_COMMON_EQ_DELAY, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_modify_common_eq_delay)); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_modify_common_eq_delay); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); /* post the command */ ! ret = oce_mbox_post(dev, &mbx, NULL); if (ret != 0) { oce_log(dev, CE_WARN, MOD_CONFIG, ! "Failed to set EQ delay %d", ret); } return (ret); } /* oce_set_eq_delay */ --- 1441,1462 ---- /* initialize the ioctl header */ mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_MODIFY_COMMON_EQ_DELAY, MBX_TIMEOUT_SEC, ! sizeof (struct mbx_modify_common_eq_delay), 0); /* fill rest of mbx */ mbx.u0.s.embedded = 1; mbx.payload_length = sizeof (struct mbx_modify_common_eq_delay); 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_WARN, MOD_CONFIG, ! "Failed to set EQ delay 0x%x", ret); } return (ret); } /* oce_set_eq_delay */
*** 1128,1289 **** } } /* oce_drain_eq */ int ! oce_init_txrx(struct oce_dev *dev) { int qid = 0; - /* enable RSS if rx queues > 1 */ - dev->rss_enable = (dev->rx_rings > 1) ? B_TRUE : B_FALSE; - for (qid = 0; qid < dev->tx_rings; qid++) { ! dev->wq[qid] = oce_wq_init(dev, dev->tx_ring_size, ! NIC_WQ_TYPE_STANDARD); ! if (dev->wq[qid] == NULL) { goto queue_fail; } } - /* Now create the Rx Queues */ - /* qid 0 is always default non rss queue for rss */ - dev->rq[0] = oce_rq_init(dev, dev->rx_ring_size, dev->rq_frag_size, - OCE_MAX_JUMBO_FRAME_SIZE, B_FALSE); - if (dev->rq[0] == NULL) { - goto queue_fail; - } - - for (qid = 1; qid < dev->rx_rings; qid++) { - dev->rq[qid] = oce_rq_init(dev, dev->rx_ring_size, - dev->rq_frag_size, OCE_MAX_JUMBO_FRAME_SIZE, - dev->rss_enable); - if (dev->rq[qid] == NULL) { - goto queue_fail; - } - } - return (DDI_SUCCESS); queue_fail: ! oce_fini_txrx(dev); return (DDI_FAILURE); } void ! oce_fini_txrx(struct oce_dev *dev) { int qid; int nqs; /* free all the tx rings */ /* nwqs is decremented in fini so copy count first */ nqs = dev->nwqs; for (qid = 0; qid < nqs; qid++) { ! if (dev->wq[qid] != NULL) { ! oce_wq_fini(dev, dev->wq[qid]); ! dev->wq[qid] = NULL; } - } - /* free all the rx rings */ - nqs = dev->nrqs; - for (qid = 0; qid < nqs; qid++) { - if (dev->rq[qid] != NULL) { - oce_rq_fini(dev, dev->rq[qid]); - dev->rq[qid] = NULL; - } - } } int oce_create_queues(struct oce_dev *dev) { ! int i; ! struct oce_eq *eq; ! struct oce_mq *mq; for (i = 0; i < dev->num_vectors; i++) { ! eq = oce_eq_create(dev, EQ_LEN_1024, EQE_SIZE_4, 0); ! if (eq == NULL) { goto rings_fail; } - dev->eq[i] = eq; } - for (i = 0; i < dev->nwqs; i++) { - if (oce_wq_create(dev->wq[i], dev->eq[0]) != 0) - goto rings_fail; - } ! for (i = 0; i < dev->nrqs; i++) { ! if (oce_rq_create(dev->rq[i], dev->if_id, ! dev->neqs > 1 ? dev->eq[1 + i] : dev->eq[0]) != 0) goto rings_fail; } ! mq = oce_mq_create(dev, dev->eq[0], 64); ! if (mq == NULL) goto rings_fail; ! dev->mq = mq; return (DDI_SUCCESS); rings_fail: oce_delete_queues(dev); return (DDI_FAILURE); } void ! oce_delete_queues(struct oce_dev *dev) { - int i; - int neqs = dev->neqs; if (dev->mq != NULL) { oce_mq_del(dev, dev->mq); dev->mq = NULL; } ! for (i = 0; i < dev->nrqs; i++) { ! oce_rq_del(dev, dev->rq[i]); ! } for (i = 0; i < dev->nwqs; i++) { ! oce_wq_del(dev, dev->wq[i]); } /* delete as many eqs as the number of vectors */ for (i = 0; i < neqs; i++) { ! oce_eq_del(dev, dev->eq[i]); ! dev->eq[i] = NULL; } } void ! oce_dev_rss_ready(struct oce_dev *dev) { ! uint8_t dev_index = 0; ! uint8_t adapter_rss = 0; ! /* Return if rx_rings <= 1 (No RSS) */ ! if (dev->rx_rings <= 1) { ! oce_log(dev, CE_NOTE, MOD_CONFIG, ! "Rx rings = %d, Not enabling RSS", dev->rx_rings); ! return; } ! /* ! * Count the number of PCI functions enabling RSS on this ! * adapter ! */ ! while (dev_index < MAX_DEVS) { ! if ((oce_dev_list[dev_index] != NULL) && ! (dev->pci_bus == oce_dev_list[dev_index]->pci_bus) && ! (dev->pci_device == oce_dev_list[dev_index]->pci_device) && ! (oce_dev_list[dev_index]->rss_enable)) { ! adapter_rss++; } ! dev_index++; } ! /* ! * If there are already MAX_RSS_PER_ADAPTER PCI functions using ! * RSS on this adapter, reduce the number of rx rings to 1 ! * (No RSS) ! */ ! if (adapter_rss >= MAX_RSS_PER_ADAPTER) { ! dev->rx_rings = 1; } } --- 1495,1790 ---- } } /* oce_drain_eq */ int ! oce_init_tx(struct oce_dev *dev) { int qid = 0; for (qid = 0; qid < dev->tx_rings; qid++) { ! if (oce_wq_init(dev, &dev->wq[qid], dev->tx_ring_size, ! NIC_WQ_TYPE_STANDARD) != DDI_SUCCESS) { goto queue_fail; } } return (DDI_SUCCESS); queue_fail: ! oce_fini_tx(dev); return (DDI_FAILURE); } + + void ! oce_fini_tx(struct oce_dev *dev) { int qid; int nqs; /* free all the tx rings */ /* nwqs is decremented in fini so copy count first */ nqs = dev->nwqs; for (qid = 0; qid < nqs; qid++) { ! oce_wq_fini(dev, &dev->wq[qid]); } } + int oce_create_queues(struct oce_dev *dev) { + int i, num_if; ! for (num_if = 0; num_if < dev->num_rx_groups; num_if++) { ! if (oce_create_nw_interface(dev, &dev->rx_group[num_if], ! MBX_BOOTSTRAP) != DDI_SUCCESS) { ! goto if_fail; ! } ! } + /* create resources that are common to an oce instance */ for (i = 0; i < dev->num_vectors; i++) { ! if (oce_eq_create(dev, &dev->eq[i], EQ_LEN_1024, EQE_SIZE_4, 0, ! MBX_BOOTSTRAP) != DDI_SUCCESS) { goto rings_fail; } } ! /* create tx rings */ ! if (dev->num_tx_groups == 1) { ! for (i = 0; i < dev->tx_rings; i++) { ! if (oce_wq_create(&dev->wq[i], &dev->eq[i], ! MBX_BOOTSTRAP) != 0) { ! dev->tx_rings = i; goto rings_fail; } ! oce_log(dev, CE_NOTE, MOD_CONFIG, ! "wq[%d] created on eq[%d]=%p wq=%p", ! i, i, (void *)&dev->eq[i], (void *)&dev->wq[i]); ! } ! } else { ! /* Tx groups not supported */ ! oce_log(dev, CE_WARN, MOD_CONFIG, ! "unsupported number of tx groups %d", dev->num_tx_groups); goto rings_fail; ! } ! return (DDI_SUCCESS); rings_fail: oce_delete_queues(dev); + if_fail: + for (i = 0; i < num_if; i++) { + oce_delete_nw_interface(dev, &dev->rx_group[i], MBX_BOOTSTRAP); + } return (DDI_FAILURE); + } + int + oce_create_mcc_queue(struct oce_dev *dev) + { + if (LANCER_CHIP(dev)) { + dev->mq = oce_mq_create_ext_v1(dev, &dev->eq[0], MCC_Q_LEN); + } else { + dev->mq = oce_mq_create_ext_v0(dev, &dev->eq[0], MCC_Q_LEN); + } + + if (dev->mq == NULL) { + oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", + "Extended MQ is not supported reverting to Legacy MQ mode"); + dev->mq = oce_mq_create(dev, &dev->eq[0], MCC_Q_LEN); + if (dev->mq == NULL) + return (DDI_FAILURE); + } + + return (DDI_SUCCESS); } + int + oce_create_group(struct oce_dev *dev, oce_group_t *grp, uint32_t mode) + { + int eqidx, ret, i; + char itbl[OCE_ITBL_SIZE]; + char hkey[OCE_HKEY_SIZE]; + + for (i = 0; i < grp->num_rings; i++) { + if (i != 0) { + grp->ring[i].rx->cfg.is_rss_queue = + grp->rss_enable; + eqidx = (grp->eq_idx + i - grp->rss_enable) % + dev->num_vectors; + } else { + grp->ring[i].rx->cfg.is_rss_queue = B_FALSE; + eqidx = grp->eq_idx % dev->num_vectors; + } + + ret = oce_rq_create(grp->ring[i].rx, + grp->if_id, &dev->eq[eqidx], mode); + + if (ret != 0) { + goto cleanup_group; + } + oce_log(dev, CE_NOTE, MOD_CONFIG, + "rq[%d][%d] created on eq[%d]=%p rq=%p, rss=%d", + grp->grp_num, i, eqidx, + (void *)&dev->eq[eqidx], + (void *)grp->ring[i].rx, + grp->ring[i].rx->cfg.is_rss_queue); + } + + if (grp->rss_enable) { + (void) oce_group_create_itbl(grp, itbl); + + (void) oce_gen_hkey(hkey, OCE_HKEY_SIZE); + ret = oce_config_rss(dev, grp->if_id, hkey, + itbl, OCE_ITBL_SIZE, OCE_DEFAULT_RSS_TYPE, B_FALSE, + mode); + if (ret != DDI_SUCCESS) { + oce_log(dev, CE_WARN, MOD_CONFIG, + "Failed to Configure RSS 0x%x", ret); + goto cleanup_group; + } + } + + return (DDI_SUCCESS); + cleanup_group: + oce_delete_group(dev, grp); + return (DDI_FAILURE); + } + void ! oce_delete_mcc_queue(struct oce_dev *dev) { if (dev->mq != NULL) { oce_mq_del(dev, dev->mq); dev->mq = NULL; } + } ! void ! oce_delete_queues(struct oce_dev *dev) ! { ! int i; ! int neqs = dev->neqs; ! for (i = 0; i < dev->nwqs; i++) { ! oce_wq_del(dev, &dev->wq[i], MBX_BOOTSTRAP); } + /* delete as many eqs as the number of vectors */ for (i = 0; i < neqs; i++) { ! oce_eq_del(dev, &dev->eq[i], MBX_BOOTSTRAP); } + + for (i = dev->num_rx_groups - 1; i >= 0; i--) { + oce_delete_nw_interface(dev, &dev->rx_group[i], MBX_BOOTSTRAP); + } } void ! oce_delete_group(struct oce_dev *dev, oce_group_t *grp) { ! int i; ! for (i = 0; i < grp->num_rings; i++) { ! oce_rq_del(dev, grp->ring[i].rx, MBX_BOOTSTRAP); } + } ! ! void ! oce_free_queues(struct oce_dev *dev) ! { ! int i = 0; ! ! for (i = 0; i < dev->rx_rings; i++) { ! mutex_destroy(&dev->rq[i].rq_fini_lock); } ! if (dev->rq != NULL) { ! kmem_free(dev->rq, ! sizeof (struct oce_rq) * dev->rx_rings); ! dev->rq = NULL; } + if (dev->wq != NULL) { + kmem_free(dev->wq, + sizeof (struct oce_wq) * dev->tx_rings); + dev->wq = NULL; + } + if (dev->cq != NULL) { + kmem_free(dev->cq, + sizeof (struct oce_cq *) * OCE_MAX_CQ); + dev->cq = NULL; + } + if (dev->eq != NULL) { + for (i = 0; i < OCE_MAX_EQ; i++) { + mutex_destroy(&dev->eq[i].lock); + } ! kmem_free(dev->eq, ! sizeof (struct oce_eq) * OCE_MAX_EQ); ! dev->eq = NULL; } + } + + int + oce_alloc_queues(struct oce_dev *dev) + { + int i, j, nrings = 0; + + /* Allocate space for RQ array */ + dev->rq = kmem_zalloc(sizeof (struct oce_rq) * dev->rx_rings, + KM_NOSLEEP); + + if (dev->rq == NULL) { + return (DDI_FAILURE); + } + for (i = 0; i < dev->rx_rings; i++) { + mutex_init(&dev->rq[i].rq_fini_lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(dev->intr_pri)); + } + + /* Allocate space for WQ array */ + dev->wq = kmem_zalloc(sizeof (struct oce_wq) * dev->tx_rings, + KM_NOSLEEP); + + if (dev->wq == NULL) { + goto alloc_fail; + } + + dev->cq = kmem_zalloc(sizeof (struct oce_cq *) * OCE_MAX_CQ, + KM_NOSLEEP); + + if (dev->cq == NULL) { + goto alloc_fail; + } + + dev->eq = kmem_zalloc(sizeof (struct oce_eq) * OCE_MAX_EQ, + KM_NOSLEEP); + if (dev->eq == NULL) { + goto alloc_fail; + } + + for (i = 0; i < OCE_MAX_EQ; i++) { + dev->eq[i].idx = i; + mutex_init(&dev->eq[i].lock, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(dev->intr_pri)); + } + + for (i = 0; i < dev->tx_rings; i++) { + dev->wq[i].parent = (void *)dev; + dev->default_tx_rings[i].tx = &dev->wq[i]; + } + + for (i = 0; i < dev->num_rx_groups; i++) { + for (j = 0; j < dev->rx_group[i].num_rings; j++) { + dev->rq[nrings].parent = (void *)dev; + dev->rx_group[i].ring[j].rx = &dev->rq[nrings]; + dev->rx_group[i].ring[j].rx->grp = &dev->rx_group[i]; + nrings++; + } + } + + return (DDI_SUCCESS); + alloc_fail: + oce_free_queues(dev); + return (DDI_FAILURE); }