/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* 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[];
/* MAil box Queue functions */
struct oce_mq *
/* event queue handling */
struct oce_eq *
/* completion queue handling */
struct oce_cq *
/* Tx WQ functions */
int wq_type);
/* Rx Queue functions */
/*
* 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 *
{
int ret = 0;
/* allocate an eq */
return (NULL);
}
/* allocate mbx */
return (NULL);
}
sizeof (struct mbx_create_common_eq));
/* dw 0 */
/* dw 1 */
/* dw 2 */
/* todo: calculate multiplier from max min and cur */
/* fill rest of mbx */
/* now post the command */
if (ret != 0) {
return (NULL);
}
/* interpret the response */
/* Save the eq pointer */
return (eq);
} /* oce_eq_create */
/*
* function to delete an event queue
*
* dev - software handle to the device
* eq - handle to the eq to be deleted
*
* return 0=>success, failure otherwise
*/
void
{
/* drain the residual events */
/* destroy the ring */
/* send a command to delete the EQ */
sizeof (struct mbx_destroy_common_eq),
QTYPE_EQ);
}
/*
* 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 *
{
int ret = 0;
/* create cq */
"CQ allocation failed");
return (NULL);
}
/* create the ring buffer for this queue */
"CQ ring alloc failed:0x%p",
return (NULL);
}
/* initialize mailbox */
/* fill the command header */
sizeof (struct mbx_create_common_cq));
/* fill command context */
/* dw0 */
/* dw1 */
/* dw2 */
/* fill the rest of the command */
/* fill rest of mbx */
/* now send the mail box */
if (ret != 0) {
"CQ create failed: 0x%x", ret);
return (NULL);
}
/* interpret the response */
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
{
/* destroy the ring */
/* send a command to delete the CQ */
sizeof (struct mbx_destroy_common_cq),
QTYPE_CQ);
/* Reset the handler */
/* release the eq */
} /* oce_cq_del */
/*
* function to create an 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 *
{
int ret = 0;
/* Create the Completion Q */
sizeof (struct oce_mq_cqe),
return (NULL);
}
/* allocate the mq */
goto mq_alloc_fail;
}
/* allocate mbx */
/* create the ring buffer for this queue */
"MQ ring alloc failed:0x%p",
goto mq_ring_alloc;
}
sizeof (struct mbx_create_common_mq));
/* fill rest of mbx */
/* now send the mail box */
if (ret != DDI_SUCCESS) {
"MQ create failed: 0x%x", ret);
goto mq_fail;
}
/* interpret the response */
/* fill rest of the mq */
/* set the MQCQ handlers */
return (mq);
return (NULL);
} /* oce_mq_create */
/*
* function to delete an MQ
*
* dev - software handle to the device
* mq - pointer to the MQ to delete
*
* return none
*/
static void
{
/* destroy the ring */
sizeof (struct mbx_destroy_common_mq),
QTYPE_MQ);
} /* oce_mq_del */
/*
* function to create a WQ for NIC Tx
*
* 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 *
{
int ret;
static int wq_id = 0;
/* q_len must be min 256 and max 2k */
"Invalid q length. Must be "
"[256, 2000]: 0x%x", q_len);
return (NULL);
}
/* allocate wq */
"WQ allocation failed");
return (NULL);
}
/* Set the wq config */
/* assign parent */
/* Create the WQ Buffer pool */
if (ret != DDI_SUCCESS) {
"WQ Buffer Pool create failed ");
goto wqb_fail;
}
/* Create a pool of memory handles */
if (ret != DDI_SUCCESS) {
"WQ MAP Handles Pool create failed ");
goto wqm_fail;
}
"WQ Packet Desc Pool create failed ");
goto wqed_fail;
}
/* create the ring buffer */
"Failed to create WQ ring ");
goto wq_ringfail;
}
/* Initialize WQ lock */
/* Initialize WQ lock */
return (wq);
return (NULL);
} /* oce_wq_create */
/*
* function to delete a WQ
*
* dev - software handle to the device
* wq - WQ to delete
*
* return 0 => success, failure otherwise
*/
static void
{
/* destroy cq */
/* Free the packet descriptor list */
/* Destroy the Mutex */
} /* oce_wq_del */
static int
{
int ret;
/* create the CQ */
sizeof (struct oce_nic_tx_cqe),
"WCCQ create failed ");
return (DDI_FAILURE);
}
/* now fill the command */
sizeof (struct mbx_create_nic_wq));
/* workaround: fill 0x01 for ulp_mask in rsvd0 */
/* fill rest of mbx */
/* now post the command */
if (ret != DDI_SUCCESS) {
"WQ create failed: %d", ret);
return (ret);
}
/* interpret the response */
/* set the WQCQ handlers */
/* All are free to start with */
/* reset indicies */
return (0);
}
/*
* function to delete a WQ
*
* dev - software handle to the device
* wq - WQ to delete
*
* return none
*/
static void
{
/* now fill the command */
sizeof (struct mbx_delete_nic_wq),
QTYPE_WQ);
}
} /* oce_wq_del */
/*
* function to allocate RQ resources
*
* 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 *
{
int ret;
/* validate q creation parameters */
return (NULL);
return (NULL);
/* allocate the rq */
"RQ allocation failed");
return (NULL);
}
/* assign parent */
rq->rq_bdesc_array =
"RQ bdesc alloc failed");
goto rqbd_alloc_fail;
}
/* create the rq buffer descriptor ring */
rq->shadow_ring =
"RQ shadow ring alloc failed ");
goto rq_shdw_fail;
}
/* allocate the free list array */
rq->rqb_freelist =
goto rqb_free_list_fail;
}
/* create the buffer pool */
if (ret != DDI_SUCCESS) {
goto rqb_fail;
}
/* create the ring buffer */
"RQ ring create failed ");
goto rq_ringfail;
}
/* Initialize the RQ lock */
/* Initialize the recharge lock */
return (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
{
/* Destroy buffer cache */
} /* oce_rq_del */
static int
{
int ret;
return (DDI_FAILURE);
}
/* now fill the command */
sizeof (struct mbx_create_nic_rq));
/* fill rest of mbx */
/* now post the command */
if (ret != 0) {
"RQ create failed: %d", ret);
return (ret);
}
/* interpret the response */
/* set the Completion Handler */
/* reset the indicies */
return (0);
}
/*
* function to delete an RQ
*
* dev - software handle to the device
* rq - RQ to delete
*
* return none
*/
static void
{
/* delete the Queue */
sizeof (struct mbx_delete_nic_rq), QTYPE_RQ);
/* Delete the associated CQ */
/* free up the posted buffers */
}
} /* oce_rq_del */
/*
* function to arm an EQ so that it can generate events
*
* dev - software handle to the device
* qid - id of the EQ returned by the fw at the time of creation
* npopped - number of EQEs to arm with
* rearm - rearm bit
* clearint - bit to clear the interrupt condition because of which
* EQEs are generated
*
* return none
*/
void
{
}
/*
* function to arm a CQ with CQEs
*
* dev - software handle to the device
* qid - the id of the CQ returned by the fw at the time of creation
* npopped - number of CQEs to arm with
*
* return none
*/
void
{
}
/*
* function to delete a EQ, CQ, MQ, WQ or RQ
*
* dev - sofware handle to the device
* mbx - mbox command to send to the fw to delete the queue
* mbx contains the queue information to delete
* req_size - the size of the mbx payload dependent on the qtype
* qtype - the type of queue i.e. EQ, CQ, MQ, WQ or RQ
*
* return DDI_SUCCESS => success, failure otherwise
*/
int
{
int opcode;
int subsys;
int ret;
switch (qtype) {
case QTYPE_EQ: {
break;
}
case QTYPE_CQ: {
break;
}
case QTYPE_MQ: {
break;
}
case QTYPE_WQ: {
break;
}
case QTYPE_RQ: {
break;
}
default: {
ASSERT(0);
break;
}
}
/* fill rest of mbx */
/* send command */
if (ret != 0) {
"Failed to del q ");
}
return (ret);
}
/*
* function to set the delay parameter in the EQ for interrupt coalescing
*
* dev - software handle to the device
* eq_arr - array of EQ ids to delete
* eq_cnt - number of elements in eq_arr
* eq_delay - delay parameter
*
* return DDI_SUCCESS => success, failure otherwise
*/
int
{
int ret;
int neq;
/* fill the command */
}
/* initialize the ioctl header */
sizeof (struct mbx_modify_common_eq_delay));
/* fill rest of mbx */
/* post the command */
if (ret != 0) {
"Failed to set EQ delay %d", ret);
}
return (ret);
} /* oce_set_eq_delay */
/*
* function to cleanup the eqs used during stop
*
* eq - pointer to event queue structure
*
* return none
*/
void
{
/* get the first item in eq to process */
/* clear valid bit */
/* process next eqe */
num_eqe++;
} /* for all EQEs */
if (num_eqe) {
}
} /* oce_drain_eq */
int
{
int qid = 0;
/* enable RSS if rx queues > 1 */
goto queue_fail;
}
}
/* Now create the Rx Queues */
/* qid 0 is always default non rss queue for rss */
goto queue_fail;
}
dev->rss_enable);
goto queue_fail;
}
}
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
void
{
int qid;
int nqs;
/* free all the tx rings */
/* nwqs is decremented in fini so copy count first */
}
}
/* free all the rx rings */
}
}
}
int
{
int i;
for (i = 0; i < dev->num_vectors; i++) {
goto rings_fail;
}
}
goto rings_fail;
}
goto rings_fail;
}
goto rings_fail;
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
void
{
int i;
}
}
}
/* delete as many eqs as the number of vectors */
for (i = 0; i < neqs; i++) {
}
}
void
{
/* Return if rx_rings <= 1 (No RSS) */
return;
}
/*
* Count the number of PCI functions enabling RSS on this
* adapter
*/
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) {
}
}