aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ixl/if_ixl.c
diff options
context:
space:
mode:
authorJack F Vogel <jfv@FreeBSD.org>2014-11-06 23:45:05 +0000
committerJack F Vogel <jfv@FreeBSD.org>2014-11-06 23:45:05 +0000
commite5100ee2787fc2d98602563e00a9b1ab0768b89a (patch)
treed315d8cbe8b8cfba2d12da3c06f171590e8eb8cd /sys/dev/ixl/if_ixl.c
parent2b293f6aa1b3b1fd7aa2ee1809952e3d366bce72 (diff)
downloadsrc-e5100ee2787fc2d98602563e00a9b1ab0768b89a.tar.gz
src-e5100ee2787fc2d98602563e00a9b1ab0768b89a.zip
Update the Intel i40e drivers, ixl version 1.2.8, ixlv version 1.1.18
-Improved VF stability, thanks to changes from Ryan Stone, and Juniper. - RSS fixes in the ixlv driver - link detection in the ixlv driver - New sysctl's added in ixl and ixlv - reset timeout increased for ixlv - stability fixes in detach - correct media reporting - Coverity warnings fixed - Many small bug fixes - VF Makefile modified - nvm shared code needed - remove unused sleep channels in ixlv_sc struct Submitted by: Eric Joyner (committed by jfv) MFC after: 1 week
Notes
Notes: svn path=/head/; revision=274205
Diffstat (limited to 'sys/dev/ixl/if_ixl.c')
-rwxr-xr-xsys/dev/ixl/if_ixl.c348
1 files changed, 264 insertions, 84 deletions
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index a1c14781c7e6..152425dfac95 100755
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -40,7 +40,7 @@
/*********************************************************************
* Driver version
*********************************************************************/
-char ixl_driver_version[] = "1.2.2";
+char ixl_driver_version[] = "1.2.8";
/*********************************************************************
* PCI Device ID Table
@@ -109,6 +109,7 @@ static bool ixl_config_link(struct i40e_hw *);
static void ixl_config_rss(struct ixl_vsi *);
static void ixl_set_queue_rx_itr(struct ixl_queue *);
static void ixl_set_queue_tx_itr(struct ixl_queue *);
+static int ixl_set_advertised_speeds(struct ixl_pf *, int);
static void ixl_enable_rings(struct ixl_vsi *);
static void ixl_disable_rings(struct ixl_vsi *);
@@ -155,6 +156,7 @@ static void ixl_do_adminq(void *, int);
static int ixl_set_flowcntl(SYSCTL_HANDLER_ARGS);
static int ixl_set_advertise(SYSCTL_HANDLER_ARGS);
static int ixl_current_speed(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS);
/* Statistics */
static void ixl_add_hw_stats(struct ixl_pf *);
@@ -176,7 +178,8 @@ static void ixl_stat_update32(struct i40e_hw *, u32, bool,
static int ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS);
static int ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS);
static int ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS);
-static int ixl_sysctl_hw_res_info(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS);
static int ixl_sysctl_dump_txd(SYSCTL_HANDLER_ARGS);
#endif
@@ -276,6 +279,7 @@ int ixl_atr_rate = 20;
TUNABLE_INT("hw.ixl.atr_rate", &ixl_atr_rate);
#endif
+
static char *ixl_fc_string[6] = {
"None",
"Rx",
@@ -398,6 +402,11 @@ ixl_attach(device_t dev)
OID_AUTO, "current_speed", CTLTYPE_STRING | CTLFLAG_RD,
pf, 0, ixl_current_speed, "A", "Current Port Speed");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "fw_version", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_show_fw, "A", "Firmware version");
+
SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
OID_AUTO, "rx_itr", CTLFLAG_RW,
@@ -436,8 +445,13 @@ ixl_attach(device_t dev)
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "hw_res_info", CTLTYPE_STRING | CTLFLAG_RD,
- pf, 0, ixl_sysctl_hw_res_info, "A", "HW Resource Allocation");
+ OID_AUTO, "hw_res_alloc", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_hw_res_alloc, "A", "HW Resource Allocation");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "switch_config", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_switch_config, "A", "HW Switch Configuration");
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
@@ -445,7 +459,7 @@ ixl_attach(device_t dev)
pf, 0, ixl_sysctl_dump_txd, "I", "Desc dump");
#endif
- /* Save off the information about this board */
+ /* Save off the PCI information */
hw->vendor_id = pci_get_vendor(dev);
hw->device_id = pci_get_device(dev);
hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
@@ -593,6 +607,7 @@ ixl_attach(device_t dev)
bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN);
i40e_get_port_mac_addr(hw, hw->mac.port_addr);
+ /* Set up VSI and queues */
if (ixl_setup_stations(pf) != 0) {
device_printf(dev, "setup stations failed!\n");
error = ENOMEM;
@@ -630,8 +645,11 @@ ixl_attach(device_t dev)
"an unqualified module was detected\n");
/* Setup OS specific network interface */
- if (ixl_setup_interface(dev, vsi) != 0)
+ if (ixl_setup_interface(dev, vsi) != 0) {
+ device_printf(dev, "interface setup failed!\n");
+ error = EIO;
goto err_late;
+ }
/* Get the bus configuration and set the shared code */
bus = ixl_get_bus_info(hw, dev);
@@ -642,25 +660,32 @@ ixl_attach(device_t dev)
ixl_update_stats_counters(pf);
ixl_add_hw_stats(pf);
+ /* Reset port's advertised speeds */
+ if (!i40e_is_40G_device(hw->device_id)) {
+ pf->advertised_speed = 0x7;
+ ixl_set_advertised_speeds(pf, 0x7);
+ }
+
/* Register for VLAN events */
vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST);
vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
+
INIT_DEBUGOUT("ixl_attach: end");
return (0);
err_late:
- ixl_free_vsi(vsi);
+ if (vsi->ifp != NULL)
+ if_free(vsi->ifp);
err_mac_hmc:
i40e_shutdown_lan_hmc(hw);
err_get_cap:
i40e_shutdown_adminq(hw);
err_out:
- if (vsi->ifp != NULL)
- if_free(vsi->ifp);
ixl_free_pci_resources(pf);
+ ixl_free_vsi(vsi);
IXL_PF_LOCK_DESTROY(pf);
return (error);
}
@@ -725,6 +750,7 @@ ixl_detach(device_t dev)
ether_ifdetach(vsi->ifp);
callout_drain(&pf->timer);
+
ixl_free_pci_resources(pf);
bus_generic_detach(dev);
if_free(vsi->ifp);
@@ -2246,6 +2272,34 @@ early:
return;
}
+static void
+ixl_add_ifmedia(struct ixl_vsi *vsi, u32 phy_type)
+{
+ /* Display supported media types */
+ if (phy_type & (1 << I40E_PHY_TYPE_100BASE_TX))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_100_TX, 0, NULL);
+
+ if (phy_type & (1 << I40E_PHY_TYPE_1000BASE_T))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_T, 0, NULL);
+
+ if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1_CU) ||
+ phy_type & (1 << I40E_PHY_TYPE_10GBASE_SFPP_CU))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
+ if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_SR))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
+ if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_LR))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
+ if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_T))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+
+ if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4_CU) ||
+ phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
+ if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_SR4))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
+ if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_LR4))
+ ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_LR4, 0, NULL);
+}
/*********************************************************************
*
@@ -2276,7 +2330,7 @@ ixl_setup_interface(device_t dev, struct ixl_vsi *vsi)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = ixl_ioctl;
-#if __FreeBSD_version >= 1100000
+#if __FreeBSD_version >= 1100036
if_setgetcounterfn(ifp, ixl_get_counter);
#endif
@@ -2286,8 +2340,6 @@ ixl_setup_interface(device_t dev, struct ixl_vsi *vsi)
ifp->if_snd.ifq_maxlen = que->num_desc - 2;
- ether_ifattach(ifp, hw->mac.addr);
-
vsi->max_frame_size =
ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
+ ETHER_VLAN_ENCAP_LEN;
@@ -2328,40 +2380,26 @@ ixl_setup_interface(device_t dev, struct ixl_vsi *vsi)
ixl_media_status);
aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, TRUE, &abilities_resp, NULL);
- if (aq_error) {
- printf("Error getting supported media types, AQ error %d\n", aq_error);
- return (EPERM);
- }
-
- /* Display supported media types */
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_100BASE_TX))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_100_TX, 0, NULL);
-
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_1000BASE_T))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_T, 0, NULL);
-
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1_CU) ||
- abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_SFPP_CU))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_SR))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_LR))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_T))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_T, 0, NULL);
-
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4_CU) ||
- abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_SR4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
- if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_LR4))
- ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_LR4, 0, NULL);
+ if (aq_error == I40E_ERR_UNKNOWN_PHY) {
+ /* Need delay to detect fiber correctly */
+ i40e_msec_delay(200);
+ aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, TRUE, &abilities_resp, NULL);
+ if (aq_error == I40E_ERR_UNKNOWN_PHY)
+ device_printf(dev, "Unknown PHY type detected!\n");
+ else
+ ixl_add_ifmedia(vsi, abilities_resp.phy_type);
+ } else if (aq_error) {
+ device_printf(dev, "Error getting supported media types, err %d,"
+ " AQ error %d\n", aq_error, hw->aq.asq_last_status);
+ } else
+ ixl_add_ifmedia(vsi, abilities_resp.phy_type);
/* Use autoselect media by default */
ifmedia_add(&vsi->media, IFM_ETHER | IFM_AUTO, 0, NULL);
ifmedia_set(&vsi->media, IFM_ETHER | IFM_AUTO);
+ ether_ifattach(ifp, hw->mac.addr);
+
return (0);
}
@@ -3728,10 +3766,6 @@ ixl_update_stats_counters(struct ixl_pf *pf)
pf->stat_offsets_loaded,
&osd->eth.rx_discards,
&nsd->eth.rx_discards);
- ixl_stat_update32(hw, I40E_GLPRT_TDPC(hw->port),
- pf->stat_offsets_loaded,
- &osd->eth.tx_discards,
- &nsd->eth.tx_discards);
ixl_stat_update48(hw, I40E_GLPRT_UPRCH(hw->port),
I40E_GLPRT_UPRCL(hw->port),
pf->stat_offsets_loaded,
@@ -3915,8 +3949,8 @@ ixl_do_adminq(void *context, int pending)
u32 reg, loop = 0;
u16 opcode, result;
- event.msg_len = IXL_AQ_BUF_SZ;
- event.msg_buf = malloc(event.msg_len,
+ event.buf_len = IXL_AQ_BUF_SZ;
+ event.msg_buf = malloc(event.buf_len,
M_DEVBUF, M_NOWAIT | M_ZERO);
if (!event.msg_buf) {
printf("Unable to allocate adminq memory\n");
@@ -4300,6 +4334,52 @@ ixl_current_speed(SYSCTL_HANDLER_ARGS)
return (error);
}
+static int
+ixl_set_advertised_speeds(struct ixl_pf *pf, int speeds)
+{
+ struct i40e_hw *hw = &pf->hw;
+ device_t dev = pf->dev;
+ struct i40e_aq_get_phy_abilities_resp abilities;
+ struct i40e_aq_set_phy_config config;
+ enum i40e_status_code aq_error = 0;
+
+ /* Get current capability information */
+ aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, FALSE, &abilities, NULL);
+ if (aq_error) {
+ device_printf(dev, "%s: Error getting phy capabilities %d,"
+ " aq error: %d\n", __func__, aq_error,
+ hw->aq.asq_last_status);
+ return (EAGAIN);
+ }
+
+ /* Prepare new config */
+ bzero(&config, sizeof(config));
+ config.phy_type = abilities.phy_type;
+ config.abilities = abilities.abilities
+ | I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+ config.eee_capability = abilities.eee_capability;
+ config.eeer = abilities.eeer_val;
+ config.low_power_ctrl = abilities.d3_lpan;
+ /* Translate into aq cmd link_speed */
+ if (speeds & 0x4)
+ config.link_speed |= I40E_LINK_SPEED_10GB;
+ if (speeds & 0x2)
+ config.link_speed |= I40E_LINK_SPEED_1GB;
+ if (speeds & 0x1)
+ config.link_speed |= I40E_LINK_SPEED_100MB;
+
+ /* Do aq command & restart link */
+ aq_error = i40e_aq_set_phy_config(hw, &config, NULL);
+ if (aq_error) {
+ device_printf(dev, "%s: Error setting new phy config %d,"
+ " aq error: %d\n", __func__, aq_error,
+ hw->aq.asq_last_status);
+ return (EAGAIN);
+ }
+
+ return (0);
+}
+
/*
** Control link advertise speed:
** Flags:
@@ -4315,10 +4395,7 @@ ixl_set_advertise(SYSCTL_HANDLER_ARGS)
struct ixl_pf *pf = (struct ixl_pf *)arg1;
struct i40e_hw *hw = &pf->hw;
device_t dev = pf->dev;
- struct i40e_aq_get_phy_abilities_resp abilities;
- struct i40e_aq_set_phy_config config;
int requested_ls = 0;
- enum i40e_status_code aq_error = 0;
int error = 0;
/*
@@ -4343,39 +4420,9 @@ ixl_set_advertise(SYSCTL_HANDLER_ARGS)
if (pf->advertised_speed == requested_ls)
return (0);
- /* Get current capability information */
- aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, FALSE, &abilities, NULL);
- if (aq_error) {
- device_printf(dev, "%s: Error getting phy capabilities %d,"
- " aq error: %d\n", __func__, aq_error,
- hw->aq.asq_last_status);
- return (EAGAIN);
- }
-
- /* Prepare new config */
- bzero(&config, sizeof(config));
- config.phy_type = abilities.phy_type;
- config.abilities = abilities.abilities
- | I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
- config.eee_capability = abilities.eee_capability;
- config.eeer = abilities.eeer_val;
- config.low_power_ctrl = abilities.d3_lpan;
- /* Translate into aq cmd link_speed */
- if (requested_ls & 0x4)
- config.link_speed |= I40E_LINK_SPEED_10GB;
- if (requested_ls & 0x2)
- config.link_speed |= I40E_LINK_SPEED_1GB;
- if (requested_ls & 0x1)
- config.link_speed |= I40E_LINK_SPEED_100MB;
-
- /* Do aq command & restart link */
- aq_error = i40e_aq_set_phy_config(hw, &config, NULL);
- if (aq_error) {
- device_printf(dev, "%s: Error setting new phy config %d,"
- " aq error: %d\n", __func__, aq_error,
- hw->aq.asq_last_status);
- return (EAGAIN);
- }
+ error = ixl_set_advertised_speeds(pf, requested_ls);
+ if (error)
+ return (error);
pf->advertised_speed = requested_ls;
ixl_update_link_status(pf);
@@ -4454,6 +4501,26 @@ ixl_get_bus_info(struct i40e_hw *hw, device_t dev)
return (link);
}
+static int
+ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS)
+{
+ struct ixl_pf *pf = (struct ixl_pf *)arg1;
+ struct i40e_hw *hw = &pf->hw;
+ char buf[32];
+
+ snprintf(buf, sizeof(buf),
+ "f%d.%d a%d.%d n%02x.%02x e%08x",
+ hw->aq.fw_maj_ver, hw->aq.fw_min_ver,
+ hw->aq.api_maj_ver, hw->aq.api_min_ver,
+ (hw->nvm.version & IXL_NVM_VERSION_HI_MASK) >>
+ IXL_NVM_VERSION_HI_SHIFT,
+ (hw->nvm.version & IXL_NVM_VERSION_LO_MASK) >>
+ IXL_NVM_VERSION_LO_SHIFT,
+ hw->nvm.eetrack);
+ return (sysctl_handle_string(oidp, buf, strlen(buf), req));
+}
+
+
#ifdef IXL_DEBUG
static int
ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS)
@@ -4563,7 +4630,7 @@ ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS)
#define IXL_SW_RES_SIZE 0x14
static int
-ixl_sysctl_hw_res_info(SYSCTL_HANDLER_ARGS)
+ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS)
{
struct ixl_pf *pf = (struct ixl_pf *)arg1;
struct i40e_hw *hw = &pf->hw;
@@ -4620,7 +4687,120 @@ ixl_sysctl_hw_res_info(SYSCTL_HANDLER_ARGS)
device_printf(dev, "sysctl error: %d\n", error);
sbuf_delete(buf);
return error;
+}
+
+/*
+** Caller must init and delete sbuf; this function will clear and
+** finish it for caller.
+*/
+static char *
+ixl_switch_element_string(struct sbuf *s, u16 seid, bool uplink)
+{
+ sbuf_clear(s);
+
+ if (seid == 0 && uplink)
+ sbuf_cat(s, "Network");
+ else if (seid == 0)
+ sbuf_cat(s, "Host");
+ else if (seid == 1)
+ sbuf_cat(s, "EMP");
+ else if (seid <= 5)
+ sbuf_printf(s, "MAC %d", seid - 2);
+ else if (seid <= 15)
+ sbuf_cat(s, "Reserved");
+ else if (seid <= 31)
+ sbuf_printf(s, "PF %d", seid - 16);
+ else if (seid <= 159)
+ sbuf_printf(s, "VF %d", seid - 32);
+ else if (seid <= 287)
+ sbuf_cat(s, "Reserved");
+ else if (seid <= 511)
+ sbuf_cat(s, "Other"); // for other structures
+ else if (seid <= 895)
+ sbuf_printf(s, "VSI %d", seid - 512);
+ else if (seid <= 1023)
+ sbuf_printf(s, "Reserved");
+ else
+ sbuf_cat(s, "Invalid");
+
+ sbuf_finish(s);
+ return sbuf_data(s);
+}
+static int
+ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS)
+{
+ struct ixl_pf *pf = (struct ixl_pf *)arg1;
+ struct i40e_hw *hw = &pf->hw;
+ device_t dev = pf->dev;
+ struct sbuf *buf;
+ struct sbuf *nmbuf;
+ int error = 0;
+ u8 aq_buf[I40E_AQ_LARGE_BUF];
+
+ u16 next = 0;
+ struct i40e_aqc_get_switch_config_resp *sw_config;
+ sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf;
+
+ buf = sbuf_new_for_sysctl(NULL, NULL, 0, req);
+ if (!buf) {
+ device_printf(dev, "Could not allocate sbuf for sysctl output.\n");
+ return (ENOMEM);
+ }
+
+ error = i40e_aq_get_switch_config(hw, sw_config,
+ sizeof(aq_buf), &next, NULL);
+ if (error) {
+ device_printf(dev, "%s: aq_get_switch_config() error %d, aq error %d\n",
+ __func__, error, hw->aq.asq_last_status);
+ sbuf_delete(buf);
+ return error;
+ }
+
+ nmbuf = sbuf_new_auto();
+ if (!nmbuf) {
+ device_printf(dev, "Could not allocate sbuf for name output.\n");
+ return (ENOMEM);
+ }
+
+ sbuf_cat(buf, "\n");
+ // Assuming <= 255 elements in switch
+ sbuf_printf(buf, "# of elements: %d\n", sw_config->header.num_reported);
+ /* Exclude:
+ ** Revision -- all elements are revision 1 for now
+ */
+ sbuf_printf(buf,
+ "SEID ( Name ) | Uplink | Downlink | Conn Type\n"
+ " | | | (uplink)\n");
+ for (int i = 0; i < sw_config->header.num_reported; i++) {
+ // "%4d (%8s) | %8s %8s %#8x",
+ sbuf_printf(buf, "%4d", sw_config->element[i].seid);
+ sbuf_cat(buf, " ");
+ sbuf_printf(buf, "(%8s)", ixl_switch_element_string(nmbuf, sw_config->element[i].seid, false));
+ sbuf_cat(buf, " | ");
+ sbuf_printf(buf, "%8s", ixl_switch_element_string(nmbuf, sw_config->element[i].uplink_seid, true));
+ sbuf_cat(buf, " ");
+ sbuf_printf(buf, "%8s", ixl_switch_element_string(nmbuf, sw_config->element[i].downlink_seid, false));
+ sbuf_cat(buf, " ");
+ sbuf_printf(buf, "%#8x", sw_config->element[i].connection_type);
+ if (i < sw_config->header.num_reported - 1)
+ sbuf_cat(buf, "\n");
+ }
+ sbuf_delete(nmbuf);
+
+ error = sbuf_finish(buf);
+ if (error) {
+ device_printf(dev, "Error finishing sbuf: %d\n", error);
+ sbuf_delete(buf);
+ return error;
+ }
+
+ error = sysctl_handle_string(oidp, sbuf_data(buf), sbuf_len(buf), req);
+ if (error)
+ device_printf(dev, "sysctl error: %d\n", error);
+ sbuf_delete(buf);
+
+ return (error);
}
/*