/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
*/
/*
* Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright 2016 Joyent, Inc.
*/
/*
* For more information, please see the big theory statement in i40e_main.c.
*/
#include "i40e_sw.h"
char *i40e_priv_props[] = {
};
static int
{
if (I40E_IS_MULTICAST(mac_addr))
return (EINVAL);
goto done;
}
ETHERADDRL) == 0)
break;
}
goto done;
}
I40E_SUCCESS) {
"%2x:%2x:%2x:%2x:%2x:%2x from unicast filter: %d",
goto done;
}
if (i != last) {
}
/*
* Set the multicast bit in the last one to indicate to ourselves that
* it's invalid.
*/
ret = 0;
done:
return (ret);
}
static int
{
int i, ret;
if (I40E_IS_MULTICAST(mac_addr))
return (EINVAL);
goto done;
}
goto done;
}
ETHERADDRL) == 0) {
goto done;
}
}
/*
* Note, the general use of the i40e_vsi_id will have to be refactored
* when we have proper group support.
*/
NULL)) != I40E_SUCCESS) {
"%2x:%2x:%2x:%2x:%2x:%2x to unicast filter: %d",
goto done;
}
ret = 0;
done:
return (ret);
}
static int
{
int rc = 0;
goto done;
}
goto done;
}
done:
return (rc);
}
static void
{
goto done;
done:
}
/*
* Enable and disable promiscuous mode as requested. We have to toggle both
* unicast and multicast. Note that multicast may already be enabled due to the
* i40e_m_multicast may toggle it itself. See i40e_main.c for more information
* on this.
*/
static int
{
goto done;
}
if (ret != I40E_SUCCESS) {
ret);
goto done;
}
/*
* If we have a non-zero mcast_promisc_count, then it has already been
* enabled or we need to leave it that way and not touch it.
*/
if (i40e->i40e_mcast_promisc_count > 0) {
goto done;
}
if (ret != I40E_SUCCESS) {
ret);
/*
* Try our best to put us back into a state that MAC expects us
* to be in.
*/
if (ret != I40E_SUCCESS) {
"the default VSI after toggling multicast failed: "
}
goto done;
} else {
}
done:
return (err);
}
/*
* See the big theory statement in i40e_main.c for multicast address management.
*/
static int
{
int ret;
if (i40e->i40e_mcast_promisc_count == 0 &&
if (ret != I40E_SUCCESS) {
"promiscuous mode on VSI %d: %d",
return (EIO);
}
}
return (0);
}
NULL)) != I40E_SUCCESS) {
"%2x:%2x:%2x:%2x:%2x:%2x to multicast filter: %d",
ret);
return (EIO);
}
return (0);
}
/*
* See the big theory statement in i40e_main.c for multicast address management.
*/
static int
{
int i, ret;
int last;
ETHERADDRL) != 0) {
continue;
}
"%2x:%2x:%2x:%2x:%2x:%2x from multicast "
"filter: %d",
return (EIO);
}
if (i != last) {
sizeof (i40e_maddr_t));
}
return (0);
}
if (i40e->i40e_mcast_promisc_count > 0) {
if (ret != I40E_SUCCESS) {
"multicast promiscuous mode on VSI %d: %d",
return (EIO);
}
}
return (0);
}
return (ENOENT);
}
static int
{
int rc;
return (ECANCELED);
}
} else {
}
return (rc);
}
/* ARGSUSED */
static void
{
/*
* At this time, we don't support toggling i40e into loopback mode. It's
* questionable how much value this has when there's no clear way to
* toggle this behavior from a supported way in userland.
*/
}
static int
{
/*
* GLDv3 requires we keep track of a generation number, as it uses
* that number to keep track of whether or not a ring is active.
*/
return (0);
}
/* ARGSUSED */
static int
{
return (0);
}
/* ARGSUSED */
static int
{
return (0);
}
/* ARGSUSED */
static void
{
/*
* Note the group index here is expected to be -1 due to the fact that
* we're not actually grouping things tx-wise at this time.
*/
/*
* We only provide the handle in cases where we have MSI-X interrupts,
* to indicate that we'd actually support retargetting.
*/
}
}
/* ARGSUSED */
static void
{
/*
* We assert the group number and ring index to help sanity check
* ourselves and mark that we'll need to rework this when we have
* multiple groups.
*/
ASSERT3S(group_index, ==, 0);
/*
* We only provide the handle in cases where we have MSI-X interrupts,
* to indicate that we'd actually support retargetting.
*/
}
}
/* ARGSUSED */
static void
{
if (rtype != MAC_RING_TYPE_RX)
return;
/*
* Note, this is a simplified view of a group, given that we only have a
* single group and a single ring at the moment. We'll want to expand
* upon this as we leverage more hardware functionality.
*/
}
static boolean_t
{
switch (cap) {
case MAC_CAPAB_HCKSUM: {
*txflags = 0;
break;
}
case MAC_CAPAB_RINGS:
case MAC_RING_TYPE_TX:
/*
* Note, saying we have no rings, but some number of
* groups indicates to MAC that it should create
* psuedo-groups with one for each TX ring. This may not
* be the long term behavior we want, but it'll work for
* now.
*/
break;
case MAC_RING_TYPE_RX:
break;
default:
return (B_FALSE);
}
break;
default:
return (B_FALSE);
}
return (B_TRUE);
}
/* ARGSUSED */
static int
const void *pr_val)
{
int ret;
long val;
char *eptr;
*eptr != '\0') {
return (ret);
}
if (val < I40E_MIN_RX_DMA_THRESH ||
return (EINVAL);
}
return (0);
}
if (val < I40E_MIN_TX_DMA_THRESH ||
return (EINVAL);
}
return (0);
}
if (val < I40E_MIN_ITR ||
val > I40E_MAX_ITR) {
return (EINVAL);
}
return (0);
}
if (val < I40E_MIN_ITR ||
val > I40E_MAX_ITR) {
return (EINVAL);
}
return (0);
}
if (val < I40E_MIN_ITR ||
val > I40E_MAX_ITR) {
return (EINVAL);
}
return (0);
}
return (ENOTSUP);
}
static int
void *pr_val)
{
} else {
return (ENOTSUP);
}
return (ERANGE);
return (0);
}
/*
* Annoyingly for private properties MAC seems to ignore default values that
* aren't strings. That means that we have to translate all of these into
* uint32_t's and instead we size the buffer to be large enough to hold a
* uint32_t.
*/
/* ARGSUSED */
static void
{
} else {
return;
}
}
static int
{
int ret = 0;
return (ECANCELED);
}
switch (pr_num) {
/*
* These properties are always read-only across every device.
*/
case MAC_PROP_DUPLEX:
case MAC_PROP_SPEED:
case MAC_PROP_STATUS:
case MAC_PROP_ADV_100FDX_CAP:
case MAC_PROP_ADV_1000FDX_CAP:
case MAC_PROP_ADV_10GFDX_CAP:
case MAC_PROP_ADV_40GFDX_CAP:
break;
/*
* These are read-only at this time as we don't support configuring
* auto-negotiation. See the theory statement in i40e_main.c.
*/
case MAC_PROP_EN_100FDX_CAP:
case MAC_PROP_EN_1000FDX_CAP:
case MAC_PROP_EN_10GFDX_CAP:
case MAC_PROP_EN_40GFDX_CAP:
case MAC_PROP_AUTONEG:
case MAC_PROP_FLOWCTRL:
break;
case MAC_PROP_MTU:
break;
if (new_mtu < I40E_MIN_MTU ||
new_mtu > I40E_MAX_MTU) {
break;
}
break;
}
if (ret == 0) {
}
break;
case MAC_PROP_PRIVATE:
break;
default:
break;
}
return (ret);
}
static int
{
int ret = 0;
switch (pr_num) {
case MAC_PROP_DUPLEX:
if (pr_valsize < sizeof (link_duplex_t)) {
break;
}
break;
case MAC_PROP_SPEED:
if (pr_valsize < sizeof (uint64_t)) {
break;
}
break;
case MAC_PROP_STATUS:
if (pr_valsize < sizeof (link_state_t)) {
break;
}
break;
case MAC_PROP_AUTONEG:
if (pr_valsize < sizeof (uint8_t)) {
break;
}
*u8 = 1;
break;
case MAC_PROP_FLOWCTRL:
/*
* Because we don't currently support hardware flow control, we
* just hardcode this to be none.
*/
if (pr_valsize < sizeof (link_flowctrl_t)) {
break;
}
break;
case MAC_PROP_MTU:
if (pr_valsize < sizeof (uint32_t)) {
break;
}
break;
/*
* Because we don't let users control the speeds we may auto-negotiate
* to, the values of the ADV_ and EN_ will always be the same.
*/
case MAC_PROP_ADV_100FDX_CAP:
case MAC_PROP_EN_100FDX_CAP:
if (pr_valsize < sizeof (uint8_t)) {
break;
}
break;
case MAC_PROP_ADV_1000FDX_CAP:
case MAC_PROP_EN_1000FDX_CAP:
if (pr_valsize < sizeof (uint8_t)) {
break;
}
break;
case MAC_PROP_ADV_10GFDX_CAP:
case MAC_PROP_EN_10GFDX_CAP:
if (pr_valsize < sizeof (uint8_t)) {
break;
}
break;
case MAC_PROP_ADV_40GFDX_CAP:
case MAC_PROP_EN_40GFDX_CAP:
if (pr_valsize < sizeof (uint8_t)) {
break;
}
break;
case MAC_PROP_PRIVATE:
break;
default:
break;
}
return (ret);
}
static void
{
switch (pr_num) {
case MAC_PROP_DUPLEX:
case MAC_PROP_SPEED:
break;
case MAC_PROP_FLOWCTRL:
/*
* At the moment, the driver doesn't support flow control, hence
* why this is set to read-only and none.
*/
break;
case MAC_PROP_MTU:
break;
/*
* We set the defaults for these based upon the phy's ability to
* support the speeds. Note, auto-negotiation is required for fiber,
* hence it is read-only and always enabled. When we have access to
* copper phys we can revisit this.
*/
case MAC_PROP_AUTONEG:
break;
case MAC_PROP_ADV_100FDX_CAP:
break;
case MAC_PROP_EN_100FDX_CAP:
break;
case MAC_PROP_ADV_1000FDX_CAP:
break;
case MAC_PROP_EN_1000FDX_CAP:
break;
case MAC_PROP_ADV_10GFDX_CAP:
break;
case MAC_PROP_EN_10GFDX_CAP:
break;
case MAC_PROP_ADV_40GFDX_CAP:
break;
case MAC_PROP_EN_40GFDX_CAP:
break;
case MAC_PROP_PRIVATE:
break;
default:
break;
}
}
#define I40E_M_CALLBACK_FLAGS \
NULL,
NULL,
NULL,
NULL,
NULL,
};
{
int status;
return (B_FALSE);
if (status != 0)
return (status == 0);
}