eib_rsrc.c revision b494511a9cf72b1fc4eb13a0e593f55c624ab829
/*
* 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
*/
/*
*/
/*
* Declarations private to this file
*/
static int eib_rsrc_setup_txbufs(eib_t *, int *);
static int eib_rsrc_setup_rxbufs(eib_t *, int *);
static int eib_rsrc_setup_lsobufs(eib_t *, int *);
ib_memlen_t, int);
uint_t *, int);
uint_t);
/*
* Definitions private to this file
*/
int
{
return (EIB_E_FAILURE);
return (EIB_E_FAILURE);
}
}
return (EIB_E_FAILURE);
}
return (EIB_E_SUCCESS);
}
int
int pri)
{
int ret;
int i;
if (ret != EIB_E_SUCCESS)
return (EIB_E_FAILURE);
/*
* See note for eib_rsrc_grab_swqe()
*/
for (i = 0; i < (*actual); i++) {
}
return (EIB_E_SUCCESS);
}
int
int pri)
{
}
int
{
int i;
/*
* Determine how many bufs we'd need for the size requested
*/
num_needed++;
return (EIB_E_FAILURE);
/*
* If we don't have enough lso bufs, return failure
*/
return (EIB_E_FAILURE);
}
/*
* Pick the first "num_needed" bufs from the free list
*/
for (i = 0; i < num_needed; i++) {
}
/*
* If the requested size is not a multiple of EIB_LSO_BUFSZ, we need
* to adjust the last sgl entry's length. Since we know we need atleast
* one, the i-1 use below is ok.
*/
if (frag_sz) {
}
/*
* Update nfree count and return
*/
*nds = num_needed;
return (EIB_E_SUCCESS);
}
{
/*
* Let's reset the swqe basic wr parameters to default. We need
* to do this because this swqe could've previously been used
* for a checksum offload (when the flags would've been set)
* or for an LSO send (in which case the opcode would've been set
* to a different value), or been iov mapped (in which case the
* it easy and initialize it here, so simple transactions can
* go through without any special effort by the caller.
*
* Note that even though the wqe structure is common for both
* send and recv, they're in two independent pools and the wqe
* type remains the same throughout its lifetime. So we don't
* have to worry about resetting any other field.
*/
if (wqe) {
}
return (wqe);
}
{
return (wqe);
}
void
{
if (chan) {
}
}
void
{
if (chan) {
}
}
void
{
int i;
/*
* Nowhere to return the buffers to ??
*/
return;
for (i = 0; i < nds; i++) {
/*
* Figure out the buflist element this sgl buffer corresponds
* to and put it back at the head
*/
}
/*
* If the number of available lso buffers just crossed the
* threshold, wakeup anyone who may be sleeping on the event.
*/
}
}
/*ARGSUSED*/
void
{
chan->ch_tx_posted--;
}
}
void
{
/*
* Decrement the ch_rx_posted count. If we are tearing this channel
* down, signal the waiter when the count reaches 0. If we aren't
* tearing the channel down, see if the count has gone below the low
* water mark. If it has, and if this channel isn't already being
* refilled, queue the channel up with the service thread for a
* rwqe refill.
*/
chan->ch_rx_posted--;
if (chan->ch_tear_down) {
if (chan->ch_rx_posted == 0)
}
}
if (queue_for_refill) {
break;
}
if (tail) {
} else {
}
}
}
void
{
}
}
void
{
"eib_rsrc_lsobufs_needed: "
"lso bufs seem to be needed even though "
"LSO support was not advertised");
return;
}
}
}
{
/*
* Set the EIB_RXWQE_SHORT flag when the number of free wqes
* in the rx pool falls below the low threshold for rwqes and
* clear it only when the number of free wqes gets back above
* the high water mark.
*/
}
return (ret);
}
void
{
}
static int
{
uint_t i;
int lso_enabled;
/*
* Try to allocate and initialize the tx wqe pool
*/
return (EIB_E_SUCCESS);
/*
* If we keep the tx buffers as mtu-sized, then potentially every
* LSO request that cannot be satisfactorily mapped, will use up
* the 8K large (default size) lso buffers. This may be inadvisable
* given that lso buffers are a scarce resource. Instead, we'll
* slightly raise the size of the copy buffers in the send wqes
* (say to EIB_TX_COPY_THRESH) so that requests that cannot be
* mapped could still avoid using the 8K LSO buffers if they're
* less than the copy threshold size.
*/
/*
* Register the TX memory region with IBTF for use
*/
if (ret != IBT_SUCCESS) {
"ibt_register_mr() failed for tx "
"region (0x%llx, 0x%llx) with ret=%d",
goto rsrc_setup_txbufs_fail;
}
/*
* Now setup the tx wqes
*/
/*
* Allocate a UD destination handle
*/
if (ret != IBT_SUCCESS) {
"eib_rsrc_setup_txbufs: "
"ibt_alloc_ud_dest(hca_hdl=0x%llx) "
goto rsrc_setup_txbufs_fail;
}
/*
* These parameters should remain fixed throughout the
* lifetime of this wqe.
*/
/*
* The qe_dest and qe_payload_hdr are specific to tx
* only, but remain unchanged throughout the lifetime
* of the wqe.
*
* The payload header is normally used when we have an
* LSO packet to send. Since the EoIB encapsulation
* header won't be part of the message we get from the
* network layer, we'll need to copy the lso header into
* a new buffer every time before we hand over the LSO
* send request to the hca driver.
*/
/*
* The encapsulation header is at the start of the
* payload header and is initialized to the default
* encapsulation header we use (no multiple segments,
* no FCS). This part of the header is not expected
* to change.
*/
/*
* The parameter set below are used in tx and rx paths.
* These parameters (except ds_key) are reset to these
* default values in eib_rsrc_return_wqes().
*/
/*
* These tx-specific parameters (except wr_id and
* wr_trans) are reset in eib_rsrc_grab_swqes() to make
* sure any freshly acquired swqe from the pool has
* these default settings for the caller.
*/
}
}
/*
* Before returning, create a kernel thread to monitor the status
* of wqes in the tx wqe pool. Note that this thread cannot be
* created from eib_state_init() during attach(), since the thread
* expects the wqe pool to be allocated and ready when it starts,
* and the tx bufs initialization only happens during eib_m_start().
*/
return (EIB_E_SUCCESS);
return (EIB_E_FAILURE);
}
static int
{
uint_t i;
/*
* Try to allocate and initialize the wqe pool. When this is called
* during a plumb via the mac m_start callback, we need to make
* sure there is a need to allocate a wqe pool afresh. If during a
* previous unplumb we didn't free the wqe pool because the nw layer
* was holding on to some rx buffers, we don't need to allocate new
* pool and set up the buffers again; we'll just start re-using the
* previous one.
*/
return (EIB_E_SUCCESS);
/*
* The receive buffer has to work for all channels, specifically the
* data qp of the vnics. This means that the buffer must be large
* enough to hold MTU sized IB payload (including the EoIB and ethernet
* headers) plus the GRH. In addition, because the ethernet header is
* either 14 or 18 bytes (tagless or vlan tagged), we should have the
* buffer filled in such a way that the IP header starts at atleast a
* 4-byte aligned address. In order to do this, we need to have some
* additional room.
*/
/*
* Register the RX memory region with IBTF for use
*/
if (ret != IBT_SUCCESS) {
"ibt_register_mr() failed for rx "
"region (0x%llx, 0x%llx) with ret=%d",
goto rsrc_setup_rxbufs_fail;
}
/*
* Now setup the rx wqes
*/
/*
* These parameters should remain fixed throughout the
* lifetime of this recv wqe. The qe_frp will only be
* used by the data channel of vnics and will remain
* unused by other channels.
*/
/*
* The parameter set below are used in tx and rx paths.
* These parameters (except ds_key) are reset to these
* default values in eib_rsrc_return_wqes().
*/
/*
* These rx-specific parameters are also reset to
* these default values in eib_rsrc_return_wqes().
*/
}
}
return (EIB_E_SUCCESS);
return (EIB_E_FAILURE);
}
static int
{
int i;
/*
* Allocate the lso bucket and space for buffers
*/
/*
* Register lso memory and save the lkey
*/
if (ret != IBT_SUCCESS) {
"ibt_register_mr() failed for LSO "
"region (0x%llx, 0x%llx) with ret=%d",
return (EIB_E_FAILURE);
}
/*
* Now allocate the buflist. Note that the elements in the buflist and
* the buffers in the lso memory have a permanent 1-1 relation, so we
* can always derive the address of a buflist entry from the address of
* an lso buffer.
*/
KM_SLEEP);
/*
* Set up the lso buf chain
*/
for (i = 0; i < eib_lso_num_bufs; i++) {
memp += EIB_LSO_BUFSZ;
elem++;
}
/*
* Set up the LSO buffer information in eib state
*/
/*
* Before returning, create a kernel thread to monitor the status
* of lso bufs
*/
return (EIB_E_SUCCESS);
}
static void
int wp_type)
{
int i;
/*
* Allocate the wqe pool, wqes and bufs
*/
KM_SLEEP);
/*
* Initialize the lock and bitmaps: everything is available at first,
* but note that if the number of blocks per pool is less than 64, we
* need to initialize those extra bits as "unavailable" - these will
* remain unavailable throughout.
*/
for (i = 0; i < EIB_BLKS_PER_POOL; i++)
wp->wp_free_wqes[i] = ~0;
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static boolean_t
{
int i;
/*
* See if we can release all memory allocated for buffers, wqes and
* the pool. Note that in the case of data channel rx buffers, some
* of the buffers may not be free if the nw layer is holding on to
* them still. If this is the case, we cannot free the wqe pool now
* or a subsequent access by the nw layer to the buffers will cause
* a panic.
*/
/*
* If force-free flag is set, we can always release the memory.
* Note that this flag is unused currently, and should be removed.
*/
return (B_TRUE);
/*
* If a whole block remains allocated, obviously we cannot free
* the pool
*/
return (B_FALSE);
}
/*
* If even a single wqe within any one block remains in-use, we
* cannot free the pool
*/
for (i = 0; i < EIB_BLKS_PER_POOL; i++) {
if (wp->wp_free_wqes[i] != (~0)) {
return (B_FALSE);
}
}
return (B_TRUE);
}
/*ARGSUSED*/
static int
{
int blk;
int ndx;
int wqe_ndx;
/*
* If this is a low priority request, adjust the number requested
* so we don't allocate beyond the low-water-mark
*/
if (pri == EIB_WPRI_LO) {
n_req = 0;
}
/*
* If the entire pool is unavailable, quit
*/
if (wp->wp_free_blks == 0)
break;
/*
* Find the first wqe that's available
*/
/*
* Mark the wqe as allocated
*/
/*
* If this was the last free wqe in this block, mark
* the block itself as unavailable
*/
/*
* Return this wqe to the caller
*/
}
if (n_allocd == 0)
return (EIB_E_FAILURE);
if (actual) {
}
return (EIB_E_SUCCESS);
}
/*ARGSUSED*/
static void
{
/*
* This wqe is being returned back to the pool, so clear
* any wqe flags and reset buffer address and size in the
* single segment sgl back to what they were initially.
* Also erase any mblk pointer and callback function ptrs.
*/
/*
* Mark the wqe free in its block
*/
/*
* This block now has atleast one wqe free, so mark
* the block itself as available and move on to the
* next wqe to free
*/
}
/*
* If the number of available wqes in the pool has just crossed
* the high-water-mark, wakeup anyone who may be sleeping on it.
*/
}
}
static void
{
int i;
return;
/*
* Check if it's ok to free the tx wqe pool (i.e. all buffers have
* been reclaimed) and if so, stop the txwqe monitor thread (and wait
* for it to die), release the UD destination handles, deregister
* memory and fini the wqe pool.
*/
for (i = 0; i < EIB_WQES_PER_POOL; i++) {
}
if (ret != IBT_SUCCESS) {
"eib_rb_rsrc_setup_txbufs: "
"ibt_free_ud_dest() failed, ret=%d",
ret);
}
}
}
"eib_rb_rsrc_setup_txbufs: "
"ibt_deregister_mr() failed, ret=%d", ret);
}
}
}
}
void
{
return;
/*
* Check if it's ok to free the rx wqe pool (i.e. all buffers have
* been reclaimed) and if so, deregister memory and fini the wqe pool.
*/
"eib_rb_rsrc_setup_rxbufs: "
"ibt_deregister_mr() failed, ret=%d", ret);
}
}
}
}
static void
{
/*
* Remove the lso bucket from the state
*/
return;
/*
* Try to stop the lso bufs monitor thread. If we fail, we simply
* return. We'll have another shot at it later from detach() with
* the force flag set.
*/
return;
/*
* Free the buflist
*/
}
/*
* Deregister LSO memory and free it
*/
"eib_rb_rsrc_setup_lsobufs: "
"ibt_deregister_mr() failed, ret=%d", ret);
}
}
}
/*
* Destroy the mutex and condvar
*/
/*
* Finally, free the lso bucket itself
*/
}