/*
* 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
*/
/*
*/
#include <sys/byteorder.h>
const char fip_vendor_mellanox[] = {
0x4d, 0x65, 0x6c, 0x6c, 0x61, 0x6e, 0x6f, 0x78
};
/*
*
* Verification of descriptor list length in the received packets is
* disabled, since experimentation shows that BX does not set the desc
* list length correctly.
*/
/*
* Static function declarations
*/
eibnx_gw_addr_t *);
static void eibnx_rb_fip_make_solicit_pkt(eibnx_wqe_t *);
/*
* Prepare and send a solicit multicast packet to the All-EoIB-GWs-GID
*/
int
{
int ret;
return (ENX_E_FAILURE);
if (ret != ENX_E_SUCCESS) {
return (ENX_E_FAILURE);
}
if (ret != ENX_E_SUCCESS) {
return (ENX_E_FAILURE);
}
return (ENX_E_SUCCESS);
}
/*
* Go through the list of already discovered gateways and send
* a unicast solicitation to each gateway. This is required by
* the EoIB specification ostensibly to receive updated
* advertisements.
*/
int
{
int ret;
/*
* We want to read the gwlist and send a unicast to each
* destination. Now, the only places where the gw list pointers
* are updated are when we're adding a new gw item to the list
* and when the list is being torn down and freed.
*
* Since new GWs are always inserted at the head of the list,
* we're guaranteed that any tail subchain of the list will
* not change by the addition of a new gw item coming into
* the list.
*
* Also, since the gw list is torn down only by the port-monitor
* thread (i.e. ourselves), we are also protected against the
* list itself going away while we're here.
*
* Given these two constraints, we can safely read the list
* of gateways without the gw list lock in this routine.
*/
if (eibnx_is_gw_dead(gw))
continue;
ENX_DPRINTF_DEBUG("eibnx_fip_solicit_ucast: "
"gw wqe type (0x%lx) indicates this is not an "
"swqe!, cannot send solicitation to gw",
continue;
ENX_DPRINTF_DEBUG("eibnx_fip_solicit_ucast: "
"gw swqe flags (0x%lx) indicate swqe is free!, "
continue;
ENX_DPRINTF_DEBUG("eibnx_fip_solicit_ucast: gw swqe "
"flags (0x%lx) indicate swqe is still with HCA!, "
continue;
}
/*
* EoIB spec requires that each host send solicitation
* to discovered gateways atleast every 4 * GW_ADV_PERIOD.
* We make sure we send a solicitation to all gateways
* every 4 * GW_ADV_PERIOD of the smallest value of
* GW_ADV_PERIOD that we have in our gw list.
*/
if (ret != ENX_E_SUCCESS)
continue;
if (ret != ENX_E_SUCCESS)
}
return (ENX_E_SUCCESS);
}
/*
* Given a send wqe and an eibnx_thr_info_t pointer, fill in the
* send buffer with a solicit packet in the network byte order.
*/
static int
{
if (pktsz < solicit_sz) {
ENX_DPRINTF_ERR("swqe bufsize too small for pkt, "
return (ENX_E_FAILURE);
}
/*
* Lint complains that there may be an alignment issue here,
* but we know that the "pkt" is atleast double-word aligned,
* so it's ok.
*/
/*
* Fill in the FIP protocol version
*/
/*
* Fill in the basic header
*/
/*
* Fill in the Infiniband Address descriptor
*/
iba->ia_sl_portid = 0;
/*
* Adjust the ds_len in the sgl to indicate the size of the
* solicit pkt before returning
*/
return (ENX_E_SUCCESS);
}
static int
{
/*
* If this a multicast send, we'll have the gateway address NULL,
* and we'll need to modify the UD destination to send to the
* solicit mcg.
*/
if (ret != IBT_SUCCESS) {
ENX_DPRINTF_ERR("ibt_modify_ud_dest() failed with "
"ret=%d, qkey=%x, qpn=%x", ret,
return (ENX_E_FAILURE);
}
return (ENX_E_SUCCESS);
}
/*
* If this is a unicast send, but we already have the gw address
* vector, the ud destination handle has already been set up for
* this gateway, so we can return.
*/
return (ENX_E_SUCCESS);
/*
* Get the reversible path information for this gateway
*/
ENX_DPRINTF_ERR("ibt_get_paths() failed with "
"ret=%d, gid_prefix=%llx, gid_guid=%llx", ret,
return (ENX_E_FAILURE);
}
/*
* And save the address vector
*/
sizeof (ibt_adds_vect_t));
/*
* Modify the UD destination handle on this swqe entry to address
* this gateway
*/
if (ret != IBT_SUCCESS) {
ENX_DPRINTF_ERR("ibt_modify_ud_dest() failed with "
return (ENX_E_FAILURE);
}
return (ENX_E_SUCCESS);
}
/*
* Send a solicit packet to the appropriate destination: if the
* destination gw addr is specified, send a unicast message to it;
* if not, send a multicast using the solicit mcg address.
*/
static int
{
return (ENX_E_FAILURE);
/*
* Note that if the post send fails, we don't really need to undo
* anything we did in setting up the ud destination; we can always
* use it for the next time.
*/
if (ret != IBT_SUCCESS) {
ENX_DPRINTF_ERR("ibt_post_send() failed for solicit, "
"ret=%d", ret);
return (ENX_E_FAILURE);
}
/*
* Set the 'posted' flag for the send wqe. If this is an unicast
* send, the wqe is attached to a specific gw entry and we should
* not release the wqe back to the pool on the send completion.
*/
}
return (ENX_E_SUCCESS);
}
/*
* Parse a received packet from the gateway into the
* eibnx_gw_msg_t argument. Note that at this point, this
* driver only expects to receive advertisements from the
* GW, nothing else.
*/
int
{
/*
* Lint complains about potential alignment problem here,
* but the fip_* structures are all packed and each of them
* is aligned on a word boundary, so we're ok.
*/
/*
* Verify that the opcode is EoIB
*/
ENX_DPRINTF_WARN("unsupported opcode (%x) found in "
"gw advertisement, ignoring", opcode);
return (ENX_E_FAILURE);
}
/*
* We only handle GW advertisements in the eibnx driver code. However,
* the BridgeX gateway software currently sends login acknowledgements
* to the one who did the solicitation instead of the one who actually
* made the login request, so we need to do something about this as
* well.
*/
switch (subcode) {
case FIP_SUBCODE_G_ADVERTISE:
break;
ret = ENX_E_SUCCESS;
break;
default:
ENX_DPRINTF_WARN("unsupported subcode (%x) found in "
"gw advertisement, ignoring", subcode);
ret = ENX_E_FAILURE;
break;
}
return (ret);
}
/*
* Parse and validate a packet known to be an advertisement from
* the GW.
*/
static int
{
/*
* Lint complains about potential alignment problem here,
* but we know that "pkt" is always atleast double-word
* aligned when it's passed to us, so we're ok.
*/
/*
* Verify if the descriptor list length in the received
* packet is valid. Currently disabled.
*
* Experimentation shows that BX doesn't set the desc list
* length correctly, so we also simply ignore it and move
* on. If and when BX fixes this problem, we'll need to
* enable the warning+failure below.
*/
if (!enx_wa_no_desc_list_len) {
if (pkt_data_sz < sizeof (fip_advertise_t)) {
ENX_DPRINTF_WARN("advertisement from gw too small; "
"expected %x, got %x", sizeof (fip_advertise_t),
return (ENX_E_FAILURE);
}
}
/*
* Validate all the header and descriptor types and lengths
*/
ENX_DPRINTF_WARN("invalid type/len in fip basic header; "
"expected (%x,%x), got (%x,%x)", FIP_DESC_TYPE_VENDOR_ID,
return (ENX_E_FAILURE);
}
ENX_DPRINTF_WARN("invalid type/len in fip iba desc; "
"expected (%x,%x), got (%x,%x)", FIP_DESC_TYPE_IBA,
return (ENX_E_FAILURE);
}
ENX_DPRINTF_WARN("invalid type/len in fip gwinfo desc; "
"expected (%x,%x), got (%x,%x)",
return (ENX_E_FAILURE);
}
ENX_DPRINTF_WARN("invalid type/len in fip gwid desc; "
"expected (%x,%x), got (%x,%x)",
return (ENX_E_FAILURE);
}
ENX_DPRINTF_WARN("invalid type/len in fip ka desc; "
"expected (%x,%x), got (%x,%x)",
return (ENX_E_FAILURE);
}
/*
* Record if the gw is available for login ('A' bit in the header)
*/
/*
* Record if this was in response to a solicit request (unicast
* advertisement) or not ('S' bit in the header)
*/
/*
* Record all info from the Infiniband Address descriptor
*/
/*
* Record all info from the EoIB GW Information descriptor
*/
else
gwi->gw_is_host_adm_vnics = 0;
/*
* Record all info from the Gateway Identifier descriptor
*/
/*
* Record all info from the Keep Alive descriptor
*/
return (ENX_E_SUCCESS);
}
/*
* Rollback whatever we did for making a solicit packet
*/
static void
{
}