svn commit: r274367 - in releng/10.1/sys: dev/ixl modules/ixlv

Jack F Vogel jfv at FreeBSD.org
Tue Nov 11 05:00:53 UTC 2014


Author: jfv
Date: Tue Nov 11 05:00:51 2014
New Revision: 274367
URL: https://svnweb.freebsd.org/changeset/base/274367

Log:
  Update the Intel ixl/ixlv drivers to fix a panic in the boot/install
  kernel if the system has a fiber-based Intel XL710 adapter installed.
  
  In addition ixl version 1.2.8 and ixlv version 1.1.18 give:
    - Improved VF stability (thanks to Ryan Stone for this)
    - RSS fixes
    - link detection in the ixlv driver
    - new sysctl's added
    - corrected media reporting
  
  Submitted by: jfv
  Approved by: re

Added:
  releng/10.1/sys/dev/ixl/ixlv_vc_mgr.h
     - copied unchanged from r274360, stable/10/sys/dev/ixl/ixlv_vc_mgr.h
Deleted:
  releng/10.1/sys/dev/ixl/i40e_register_x710_int.h
Modified:
  releng/10.1/sys/dev/ixl/i40e_osdep.c
  releng/10.1/sys/dev/ixl/i40e_osdep.h
  releng/10.1/sys/dev/ixl/if_ixl.c
  releng/10.1/sys/dev/ixl/if_ixlv.c
  releng/10.1/sys/dev/ixl/ixl.h
  releng/10.1/sys/dev/ixl/ixl_txrx.c
  releng/10.1/sys/dev/ixl/ixlv.h
  releng/10.1/sys/dev/ixl/ixlvc.c
  releng/10.1/sys/modules/ixlv/Makefile
Directory Properties:
  releng/10.1/   (props changed)

Modified: releng/10.1/sys/dev/ixl/i40e_osdep.c
==============================================================================
--- releng/10.1/sys/dev/ixl/i40e_osdep.c	Tue Nov 11 04:48:09 2014	(r274366)
+++ releng/10.1/sys/dev/ixl/i40e_osdep.c	Tue Nov 11 05:00:51 2014	(r274367)
@@ -107,6 +107,7 @@ i40e_allocate_dma_mem(struct i40e_hw *hw
 		    "error %u\n", err);
 		goto fail_2;
 	}
+	mem->nseg = 1;
 	mem->size = size;
 	bus_dmamap_sync(mem->tag, mem->map,
 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);

Modified: releng/10.1/sys/dev/ixl/i40e_osdep.h
==============================================================================
--- releng/10.1/sys/dev/ixl/i40e_osdep.h	Tue Nov 11 04:48:09 2014	(r274366)
+++ releng/10.1/sys/dev/ixl/i40e_osdep.h	Tue Nov 11 05:00:51 2014	(r274367)
@@ -147,11 +147,11 @@ void prefetch(void *x)
 #define	prefetch(x)
 #endif
 
-struct i40e_osdep
-{
+struct i40e_osdep {
 	bus_space_tag_t		mem_bus_space_tag;
 	bus_space_handle_t	mem_bus_space_handle;
 	bus_size_t		mem_bus_space_size;
+	uint32_t		flush_reg;
 	struct device		*dev;
 };
 
@@ -208,6 +208,13 @@ wr32_osdep(struct i40e_osdep *osdep, uin
 	    osdep->mem_bus_space_handle, reg, value);
 }
 
+static __inline void
+ixl_flush_osdep(struct i40e_osdep *osdep)
+{
+
+	rd32_osdep(osdep, osdep->flush_reg);
+}
+
 #define rd32(a, reg)		rd32_osdep((a)->back, (reg))
 #define wr32(a, reg, value)	wr32_osdep((a)->back, (reg), (value))
 
@@ -221,9 +228,6 @@ wr32_osdep(struct i40e_osdep *osdep, uin
                      ((struct i40e_osdep *)(a)->back)->mem_bus_space_handle, \
                      reg, value))
 
-#define ixl_flush(a) (\
-   bus_space_read_4( ((struct i40e_osdep *)(a)->back)->mem_bus_space_tag, \
-                     ((struct i40e_osdep *)(a)->back)->mem_bus_space_handle, \
-                     I40E_GLGEN_STAT))
+#define ixl_flush(a)		ixl_flush_osdep((a)->back)
 
 #endif /* _I40E_OSDEP_H_ */

Modified: releng/10.1/sys/dev/ixl/if_ixl.c
==============================================================================
--- releng/10.1/sys/dev/ixl/if_ixl.c	Tue Nov 11 04:48:09 2014	(r274366)
+++ releng/10.1/sys/dev/ixl/if_ixl.c	Tue Nov 11 05:00:51 2014	(r274367)
@@ -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_
 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 i40
 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", CTLTYPE_INT | 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);
@@ -2177,6 +2203,7 @@ ixl_allocate_pci_resources(struct ixl_pf
 	pf->osdep.mem_bus_space_handle =
 		rman_get_bushandle(pf->pci_mem);
 	pf->osdep.mem_bus_space_size = rman_get_size(pf->pci_mem);
+	pf->osdep.flush_reg = I40E_GLGEN_STAT;
 	pf->hw.hw_addr = (u8 *) &pf->osdep.mem_bus_space_handle;
 
 	pf->hw.back = &pf->osdep;
@@ -2245,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);
+}
 
 /*********************************************************************
  *
@@ -2275,14 +2330,16 @@ ixl_setup_interface(device_t dev, struct
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 	ifp->if_ioctl = ixl_ioctl;
 
+#if __FreeBSD_version >= 1100036
+	if_setgetcounterfn(ifp, ixl_get_counter);
+#endif
+
 	ifp->if_transmit = ixl_mq_start;
 
 	ifp->if_qflush = ixl_qflush;
 
 	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;
@@ -2323,40 +2380,26 @@ ixl_setup_interface(device_t dev, struct
 		     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);
 }
 
@@ -3700,7 +3743,6 @@ ixl_update_stats_counters(struct ixl_pf 
 {
 	struct i40e_hw	*hw = &pf->hw;
 	struct ixl_vsi *vsi = &pf->vsi;
-	struct ifnet	*ifp = vsi->ifp;
 
 	struct i40e_hw_port_stats *nsd = &pf->stats;
 	struct i40e_hw_port_stats *osd = &pf->stats_offsets;
@@ -3724,10 +3766,6 @@ ixl_update_stats_counters(struct ixl_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,
@@ -3893,7 +3931,7 @@ ixl_update_stats_counters(struct ixl_pf 
 
 	/* OS statistics */
 	// ERJ - these are per-port, update all vsis?
-	ifp->if_ierrors = nsd->crc_errors + nsd->illegal_bytes;
+	IXL_SET_IERRORS(vsi, nsd->crc_errors + nsd->illegal_bytes);
 }
 
 /*
@@ -3911,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");
@@ -4027,13 +4065,16 @@ void ixl_update_eth_stats(struct ixl_vsi
 {
 	struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
 	struct i40e_hw *hw = &pf->hw;
-	struct ifnet *ifp = vsi->ifp;
 	struct i40e_eth_stats *es;
 	struct i40e_eth_stats *oes;
+	int i;
+	uint64_t tx_discards;
+	struct i40e_hw_port_stats *nsd;
 	u16 stat_idx = vsi->info.stat_counter_idx;
 
 	es = &vsi->eth_stats;
 	oes = &vsi->eth_stats_offsets;
+	nsd = &pf->stats;
 
 	/* Gather up the stats that the hw collects */
 	ixl_stat_update32(hw, I40E_GLV_TEPC(stat_idx),
@@ -4078,22 +4119,27 @@ void ixl_update_eth_stats(struct ixl_vsi
 			   &oes->tx_broadcast, &es->tx_broadcast);
 	vsi->stat_offsets_loaded = true;
 
+	tx_discards = es->tx_discards + nsd->tx_dropped_link_down;
+	for (i = 0; i < vsi->num_queues; i++)
+		tx_discards += vsi->queues[i].txr.br->br_drops;
+
 	/* Update ifnet stats */
-	ifp->if_ipackets = es->rx_unicast +
+	IXL_SET_IPACKETS(vsi, es->rx_unicast +
 	                   es->rx_multicast +
-			   es->rx_broadcast;
-	ifp->if_opackets = es->tx_unicast +
+			   es->rx_broadcast);
+	IXL_SET_OPACKETS(vsi, es->tx_unicast +
 	                   es->tx_multicast +
-			   es->tx_broadcast;
-	ifp->if_ibytes = es->rx_bytes;
-	ifp->if_obytes = es->tx_bytes;
-	ifp->if_imcasts = es->rx_multicast;
-	ifp->if_omcasts = es->tx_multicast;
-
-	ifp->if_oerrors = es->tx_errors;
-	ifp->if_iqdrops = es->rx_discards;
-	ifp->if_noproto = es->rx_unknown_protocol;
-	ifp->if_collisions = 0;
+			   es->tx_broadcast);
+	IXL_SET_IBYTES(vsi, es->rx_bytes);
+	IXL_SET_OBYTES(vsi, es->tx_bytes);
+	IXL_SET_IMCASTS(vsi, es->rx_multicast);
+	IXL_SET_OMCASTS(vsi, es->tx_multicast);
+
+	IXL_SET_OERRORS(vsi, es->tx_errors);
+	IXL_SET_IQDROPS(vsi, es->rx_discards + nsd->eth.rx_discards);
+	IXL_SET_OQDROPS(vsi, tx_discards);
+	IXL_SET_NOPROTO(vsi, es->rx_unknown_protocol);
+	IXL_SET_COLLISIONS(vsi, 0);
 }
 
 /**
@@ -4288,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:
@@ -4303,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;
 
 	/*
@@ -4331,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);
@@ -4442,6 +4501,26 @@ ixl_get_bus_info(struct i40e_hw *hw, 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)
@@ -4551,7 +4630,7 @@ ixl_sysctl_sw_filter_list(SYSCTL_HANDLER
 
 #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;
@@ -4608,7 +4687,120 @@ ixl_sysctl_hw_res_info(SYSCTL_HANDLER_AR
 		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);
 }
 
 /*

Modified: releng/10.1/sys/dev/ixl/if_ixlv.c
==============================================================================
--- releng/10.1/sys/dev/ixl/if_ixlv.c	Tue Nov 11 04:48:09 2014	(r274366)
+++ releng/10.1/sys/dev/ixl/if_ixlv.c	Tue Nov 11 05:00:51 2014	(r274367)
@@ -40,7 +40,7 @@
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixlv_driver_version[] = "1.1.4";
+char ixlv_driver_version[] = "1.1.18";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -87,7 +87,6 @@ static void	ixlv_config_rss(struct ixlv_
 static void	ixlv_stop(struct ixlv_sc *);
 static void	ixlv_add_multi(struct ixl_vsi *);
 static void	ixlv_del_multi(struct ixl_vsi *);
-static void	ixlv_update_link_status(struct ixlv_sc *);
 static void	ixlv_free_queues(struct ixl_vsi *);
 static int	ixlv_setup_interface(device_t, struct ixlv_sc *);
 
@@ -97,18 +96,21 @@ static void	ixlv_media_status(struct ifn
 static void	ixlv_local_timer(void *);
 
 static int	ixlv_add_mac_filter(struct ixlv_sc *, u8 *, u16);
+static int	ixlv_del_mac_filter(struct ixlv_sc *sc, u8 *macaddr);
 static void	ixlv_init_filters(struct ixlv_sc *);
 static void	ixlv_free_filters(struct ixlv_sc *);
 
 static void	ixlv_msix_que(void *);
 static void	ixlv_msix_adminq(void *);
 static void	ixlv_do_adminq(void *, int);
-static void	ixlv_sched_aq(void *);
+static void	ixlv_do_adminq_locked(struct ixlv_sc *sc);
 static void	ixlv_handle_que(void *, int);
 static int	ixlv_reset(struct ixlv_sc *);
 static int	ixlv_reset_complete(struct i40e_hw *);
 static void	ixlv_set_queue_rx_itr(struct ixl_queue *);
 static void	ixlv_set_queue_tx_itr(struct ixl_queue *);
+static void	ixl_init_cmd_complete(struct ixl_vc_cmd *, void *,
+		    enum i40e_status_code);
 
 static void	ixlv_enable_adminq_irq(struct i40e_hw *);
 static void	ixlv_disable_adminq_irq(struct i40e_hw *);
@@ -119,10 +121,16 @@ static void	ixlv_setup_vlan_filters(stru
 static void	ixlv_register_vlan(void *, struct ifnet *, u16);
 static void	ixlv_unregister_vlan(void *, struct ifnet *, u16);
 
+static void	ixlv_init_hw(struct ixlv_sc *);
+static int	ixlv_setup_vc(struct ixlv_sc *);
+static int	ixlv_vf_config(struct ixlv_sc *);
+
 static void	ixlv_cap_txcsum_tso(struct ixl_vsi *,
 		    struct ifnet *, int);
 
-static void	ixlv_add_stats_sysctls(struct ixlv_sc *);
+static void	ixlv_add_sysctls(struct ixlv_sc *);
+static int 	ixlv_sysctl_qtx_tail_handler(SYSCTL_HANDLER_ARGS);
+static int 	ixlv_sysctl_qrx_tail_handler(SYSCTL_HANDLER_ARGS);
 
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points
@@ -271,7 +279,7 @@ ixlv_attach(device_t dev)
 	struct ixlv_sc	*sc;
 	struct i40e_hw	*hw;
 	struct ixl_vsi 	*vsi;
-	int            	bufsz, error = 0, retries = 0;
+	int            	error = 0;
 
 	INIT_DBG_DEV(dev, "begin");
 
@@ -282,30 +290,18 @@ ixlv_attach(device_t dev)
 	vsi = &sc->vsi;
 	vsi->dev = dev;
 
+	/* Initialize hw struct */
+	ixlv_init_hw(sc);
+
 	/* Allocate filter lists */
 	ixlv_init_filters(sc);
 
 	/* Core Lock Init*/
 	mtx_init(&sc->mtx, device_get_nameunit(dev),
 	    "IXL SC Lock", MTX_DEF);
-	mtx_init(&sc->aq_task_mtx, device_get_nameunit(dev),
-	    "IXL AQ Task Lock", MTX_DEF);
 
-	/* Set up the timer & aq watchdog callouts */
+	/* Set up the timer callout */
 	callout_init_mtx(&sc->timer, &sc->mtx, 0);
-	callout_init_mtx(&sc->aq_task, &sc->aq_task_mtx, 0);
-
-	/* Save off the information about this board */
-	hw->vendor_id = pci_get_vendor(dev);
-	hw->device_id = pci_get_device(dev);
-	hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
-	hw->subsystem_vendor_id =
-	    pci_read_config(dev, PCIR_SUBVEND_0, 2);
-	hw->subsystem_device_id =
-	    pci_read_config(dev, PCIR_SUBDEV_0, 2);
-
-	hw->bus.device = pci_get_slot(dev);
-	hw->bus.func = pci_get_function(dev);
 
 	/* Do PCI setup - map BAR0, etc */
 	if (ixlv_allocate_pci_resources(sc)) {
@@ -333,50 +329,16 @@ ixlv_attach(device_t dev)
 
 	INIT_DBG_DEV(dev, "VF Device is ready for configuration");
 
-	hw->aq.num_arq_entries = IXL_AQ_LEN;
-	hw->aq.num_asq_entries = IXL_AQ_LEN;
-	hw->aq.arq_buf_size = IXL_AQ_BUFSZ;
-	hw->aq.asq_buf_size = IXL_AQ_BUFSZ;
-
-	error = i40e_init_adminq(hw);
+	error = ixlv_setup_vc(sc);
 	if (error) {
-		device_printf(dev, "%s: init_adminq failed: %d\n",
+		device_printf(dev, "%s: Error setting up PF comms, %d\n",
 		    __func__, error);
 		goto err_pci_res;
 	}
 
-	INIT_DBG_DEV(dev, "Initialized Admin Queue");
-
-	error = ixlv_send_api_ver(sc);
-	if (error) {
-		device_printf(dev, "%s: unable to send to PF (%d)\n",
-		     __func__, error);
-		goto err_aq;
-	}
-
-	while (!i40e_asq_done(hw)) {
-		if (++retries > IXLV_AQ_MAX_ERR) {
-			device_printf(dev, "%s: Admin Queue timeout "
-			    "(waiting for send_api_ver)\n", __func__);
-			error = ENXIO;
-			goto err_aq;
-		}
-		i40e_msec_delay(10);
-	}
-
-	INIT_DBG_DEV(dev, "Sent API version message to PF");
-
-	/* Wait for API version msg to arrive */
-	error = ixlv_verify_api_ver(sc);
-	if (error) {
-		device_printf(dev,
-		    "%s: Unable to verify API version, error %d\n",
-			    __func__, error);
-		goto err_aq;
-	}
-
 	INIT_DBG_DEV(dev, "PF API version verified");
 
+	/* TODO: Figure out why MDD events occur when this reset is removed. */
 	/* Need API version before sending reset message */
 	error = ixlv_reset(sc);
 	if (error) {
@@ -387,49 +349,14 @@ ixlv_attach(device_t dev)
 	INIT_DBG_DEV(dev, "VF reset complete");
 
 	/* Ask for VF config from PF */
-	error = ixlv_send_vf_config_msg(sc);
+	error = ixlv_vf_config(sc);
 	if (error) {
-		device_printf(dev,
-		    "%s: Unable to send VF config request, error %d\n",
-		    __func__, error);
-		goto err_aq;
-	}
-
-	retries = 0;
-	while (!i40e_asq_done(hw)) {
-		if (++retries > IXLV_AQ_MAX_ERR) {
-			device_printf(dev, "%s: Admin Queue timeout "
-			    "(waiting for send_vf_config_msg)\n", __func__);
-			error = ENXIO;
-			goto err_aq;
-		}
-		i40e_msec_delay(10);
-	}
-
-	INIT_DBG_DEV(dev, "Sent VF config message to PF");
-
-	bufsz = sizeof(struct i40e_virtchnl_vf_resource) +
-	    (I40E_MAX_VF_VSI * sizeof(struct i40e_virtchnl_vsi_resource));
-	sc->vf_res = malloc(bufsz, M_DEVBUF, M_NOWAIT);
-	if (!sc->vf_res) {
-		device_printf(dev,
-		    "%s: Unable to allocate memory for VF configuration"
-		    " message from PF\n", __func__);
-		error = ENOMEM;
+		device_printf(dev, "Error getting configuration from PF: %d\n",
+		    error);
 		goto err_aq;
 	}
 
-	/* Check for VF config response */
-	error = ixlv_get_vf_config(sc);
-	if (error) {
-		device_printf(dev,
-		    "%s: Unable to get VF configuration from PF\n",
-		    __func__);
-		error = EBUSY;
-		goto err_res_buf;
-	}
-
-	INIT_DBG_DEV(dev, "Received valid VF config from PF");
+	INIT_DBG_DEV(dev, "VF config from PF:");
 	INIT_DBG_DEV(dev, "VSIs %d, Queues %d, Max Vectors %d, Max MTU %d",
 	    sc->vf_res->num_vsis,
 	    sc->vf_res->num_queue_pairs,
@@ -438,6 +365,7 @@ ixlv_attach(device_t dev)
 	INIT_DBG_DEV(dev, "Offload flags: %#010x",
 	    sc->vf_res->vf_offload_flags);
 
+	// TODO: Move this into ixlv_vf_config?
 	/* got VF config message back from PF, now we can parse it */
 	for (int i = 0; i < sc->vf_res->num_vsis; i++) {
 		if (sc->vf_res->vsi_res[i].vsi_type == I40E_VSI_SRIOV)
@@ -445,6 +373,7 @@ ixlv_attach(device_t dev)
 	}
 	if (!sc->vsi_res) {
 		device_printf(dev, "%s: no LAN VSI found\n", __func__);
+		error = EIO;
 		goto err_res_buf;
 	}
 
@@ -461,14 +390,13 @@ ixlv_attach(device_t dev)
 
 	vsi->id = sc->vsi_res->vsi_id;
 	vsi->back = (void *)sc;
-
-	/* Link in this virtual environment is always 'up' */
 	vsi->link_up = TRUE;
 
 	/* This allocates the memory and early settings */
 	if (ixlv_setup_queues(sc) != 0) {
 		device_printf(dev, "%s: setup queues failed!\n",
 		    __func__);
+		error = EIO;
 		goto out;
 	}
 
@@ -476,6 +404,7 @@ ixlv_attach(device_t dev)
 	if (ixlv_setup_interface(dev, sc) != 0) {
 		device_printf(dev, "%s: setup interface failed!\n",
 		    __func__);
+		error = EIO;
 		goto out;
 	}
 
@@ -487,12 +416,9 @@ ixlv_attach(device_t dev)
 	/* Start AdminQ taskqueue */
 	ixlv_init_taskqueue(sc);
 
-	/* Start the admin queue scheduler timer */
-	callout_reset(&sc->aq_task, 2 * hz, ixlv_sched_aq, sc);
-
 	/* Initialize stats */
 	bzero(&sc->vsi.eth_stats, sizeof(struct i40e_eth_stats));
-	ixlv_add_stats_sysctls(sc);
+	ixlv_add_sysctls(sc);
 
 	/* Register for VLAN events */
 	vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
@@ -504,10 +430,10 @@ ixlv_attach(device_t dev)
 	ixlv_enable_adminq_irq(hw);
 
 	/* Set things up to run init */
-	sc->aq_pending = 0;
-	sc->aq_required = 0;
 	sc->init_state = IXLV_INIT_READY;
 
+	ixl_vc_init_mgr(sc, &sc->vc_mgr);
+
 	INIT_DBG_DEV(dev, "end");
 	return (error);
 
@@ -521,7 +447,6 @@ err_pci_res:
 	ixlv_free_pci_resources(sc);
 err_early:
 	mtx_destroy(&sc->mtx);
-	mtx_destroy(&sc->aq_task_mtx);
 	ixlv_free_filters(sc);
 	INIT_DBG_DEV(dev, "end: error %d", error);
 	return (error);
@@ -542,7 +467,6 @@ ixlv_detach(device_t dev)
 {
 	struct ixlv_sc	*sc = device_get_softc(dev);
 	struct ixl_vsi 	*vsi = &sc->vsi;
-	int 			 retries = 0;
 
 	INIT_DBG_DEV(dev, "begin");
 
@@ -554,23 +478,11 @@ ixlv_detach(device_t dev)
 	}
 
 	/* Stop driver */
+	ether_ifdetach(vsi->ifp);
 	if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) {
 		mtx_lock(&sc->mtx);	
 		ixlv_stop(sc);
 		mtx_unlock(&sc->mtx);	
-
-		/*
-		** Ensure queues are disabled before examining
-		** admin queue state later in detach.
-		*/
-		while (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING
-		    && ++retries < IXLV_AQ_MAX_ERR) {
-			i40e_msec_delay(10);
-		}
-#ifdef IXL_DEBUG
-		if (retries >= IXLV_AQ_MAX_ERR)
-			device_printf(dev, "Issue disabling queues for detach\n");
-#endif
 	}
 
 	/* Unregister VLAN events */
@@ -579,37 +491,16 @@ ixlv_detach(device_t dev)
 	if (vsi->vlan_detach != NULL)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list