From owner-svn-src-all@FreeBSD.ORG Wed Jun 30 17:26:47 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 87CC3106564A; Wed, 30 Jun 2010 17:26:47 +0000 (UTC) (envelope-from jfv@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 765F28FC08; Wed, 30 Jun 2010 17:26:47 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o5UHQlvY011938; Wed, 30 Jun 2010 17:26:47 GMT (envelope-from jfv@svn.freebsd.org) Received: (from jfv@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o5UHQl7n011935; Wed, 30 Jun 2010 17:26:47 GMT (envelope-from jfv@svn.freebsd.org) Message-Id: <201006301726.o5UHQl7n011935@svn.freebsd.org> From: Jack F Vogel Date: Wed, 30 Jun 2010 17:26:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r209611 - head/sys/dev/e1000 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 30 Jun 2010 17:26:47 -0000 Author: jfv Date: Wed Jun 30 17:26:47 2010 New Revision: 209611 URL: http://svn.freebsd.org/changeset/base/209611 Log: SR-IOV support added to igb What this provides is support for the 'virtual function' interface that a FreeBSD VM may be assigned from a host like KVM on Linux, or newer versions of Xen with such support. When the guest is set up with the capability, a special limited function 82576 PCI device is present in its virtual PCI space, so with this driver installed in the guest that device will be detected and function nearly like the bare metal, as it were. The interface is only allowed a single queue in this configuration however initial performance tests have looked very good. Enjoy!! Modified: head/sys/dev/e1000/if_igb.c head/sys/dev/e1000/if_igb.h Modified: head/sys/dev/e1000/if_igb.c ============================================================================== --- head/sys/dev/e1000/if_igb.c Wed Jun 30 17:20:33 2010 (r209610) +++ head/sys/dev/e1000/if_igb.c Wed Jun 30 17:26:47 2010 (r209611) @@ -99,7 +99,7 @@ int igb_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] = "version - 1.9.6"; +char igb_driver_version[] = "version - 2.0.1"; /********************************************************************* @@ -128,6 +128,7 @@ static igb_vendor_info_t igb_vendor_info PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82576_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_82576_VF, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82580_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82580_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82580_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, @@ -226,7 +227,11 @@ static void igb_dma_free(struct adapter static int igb_sysctl_nvm_info(SYSCTL_HANDLER_ARGS); static void igb_print_nvm_info(struct adapter *); static int igb_is_valid_ether_addr(u8 *); -static void igb_add_hw_stats(struct adapter *adapter); +static void igb_add_hw_stats(struct adapter *); + +static void igb_vf_init_stats(struct adapter *); +static void igb_update_vf_stats_counters(struct adapter *); + /* Management and WOL Support */ static void igb_init_manageability(struct adapter *); static void igb_release_manageability(struct adapter *); @@ -494,6 +499,17 @@ igb_attach(device_t dev) goto err_pci; } + /* Allocate the appropriate stats memory */ + if (adapter->hw.mac.type == e1000_vfadapt) { + adapter->stats = + (struct e1000_vf_stats *)malloc(sizeof \ + (struct e1000_vf_stats), M_DEVBUF, M_NOWAIT | M_ZERO); + igb_vf_init_stats(adapter); + } else + adapter->stats = + (struct e1000_hw_stats *)malloc(sizeof \ + (struct e1000_hw_stats), M_DEVBUF, M_NOWAIT | M_ZERO); + /* ** Start from a known state, this is ** important in reading the nvm and @@ -1788,30 +1804,39 @@ static void igb_set_promisc(struct adapter *adapter) { struct ifnet *ifp = adapter->ifp; - uint32_t reg_rctl; + struct e1000_hw *hw = &adapter->hw; + u32 reg; - reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); + if (hw->mac.type == e1000_vfadapt) { + e1000_promisc_set_vf(hw, e1000_promisc_enabled); + return; + } + reg = E1000_READ_REG(hw, E1000_RCTL); if (ifp->if_flags & IFF_PROMISC) { - reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); - E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); + reg |= (E1000_RCTL_UPE | E1000_RCTL_MPE); + E1000_WRITE_REG(hw, E1000_RCTL, reg); } else if (ifp->if_flags & IFF_ALLMULTI) { - reg_rctl |= E1000_RCTL_MPE; - reg_rctl &= ~E1000_RCTL_UPE; - E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); + reg |= E1000_RCTL_MPE; + reg &= ~E1000_RCTL_UPE; + E1000_WRITE_REG(hw, E1000_RCTL, reg); } } static void igb_disable_promisc(struct adapter *adapter) { - uint32_t reg_rctl; - - reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); + struct e1000_hw *hw = &adapter->hw; + u32 reg; - reg_rctl &= (~E1000_RCTL_UPE); - reg_rctl &= (~E1000_RCTL_MPE); - E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); + if (hw->mac.type == e1000_vfadapt) { + e1000_promisc_set_vf(hw, e1000_promisc_disabled); + return; + } + reg = E1000_READ_REG(hw, E1000_RCTL); + reg &= (~E1000_RCTL_UPE); + reg &= (~E1000_RCTL_MPE); + E1000_WRITE_REG(hw, E1000_RCTL, reg); } @@ -1939,8 +1964,12 @@ igb_update_link_status(struct adapter *a e1000_check_for_link(hw); link_check = adapter->hw.mac.serdes_has_link; break; - default: + /* VF device is type_unknown */ case e1000_media_type_unknown: + e1000_check_for_link(hw); + link_check = !hw->mac.get_link_status; + /* Fall thru */ + default: break; } @@ -2025,8 +2054,8 @@ igb_identify_hardware(struct adapter *ad adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); if (!((adapter->hw.bus.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && (adapter->hw.bus.pci_cmd_word & PCIM_CMD_MEMEN))) { - device_printf(dev, "Memory Access and/or Bus Master bits " - "were not set!\n"); + INIT_DEBUGOUT("Memory Access and/or Bus Master " + "bits were not set!\n"); adapter->hw.bus.pci_cmd_word |= (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); pci_write_config(dev, PCIR_COMMAND, @@ -2041,12 +2070,6 @@ igb_identify_hardware(struct adapter *ad pci_read_config(dev, PCIR_SUBVEND_0, 2); adapter->hw.subsystem_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); - - /* Do Shared Code Init and Setup */ - if (e1000_set_mac_type(&adapter->hw)) { - device_printf(dev, "Setup init failure\n"); - return; - } } static int @@ -2225,6 +2248,7 @@ igb_configure_queues(struct adapter *ada /* Turn on MSIX */ switch (adapter->hw.mac.type) { case e1000_82580: + case e1000_vfadapt: /* RX entries */ for (int i = 0; i < adapter->num_queues; i++) { u32 index = i >> 1; @@ -2446,6 +2470,10 @@ igb_setup_msix(struct adapter *adapter) if ((adapter->hw.mac.type == e1000_82575) && (queues > 4)) queues = 4; + /* Limit the VF adapter to one queues */ + if ((adapter->hw.mac.type == e1000_vfadapt) && (queues > 2)) + queues = 1; + /* ** One vector (RX/TX pair) per queue ** plus an additional for Link interrupt @@ -2503,6 +2531,7 @@ igb_reset(struct adapter *adapter) pba = E1000_PBA_32K; break; case e1000_82576: + case e1000_vfadapt: pba = E1000_PBA_64K; break; case e1000_82580: @@ -3074,7 +3103,8 @@ igb_initialize_transmit_units(struct ada struct e1000_hw *hw = &adapter->hw; u32 tctl, txdctl; - INIT_DEBUGOUT("igb_initialize_transmit_units: begin"); + INIT_DEBUGOUT("igb_initialize_transmit_units: begin"); + tctl = txdctl = 0; /* Setup the Tx Descriptor Rings */ for (int i = 0; i < adapter->num_queues; i++, txr++) { @@ -3097,7 +3127,6 @@ igb_initialize_transmit_units(struct ada txr->watchdog_check = FALSE; - txdctl = E1000_READ_REG(hw, E1000_TXDCTL(i)); txdctl |= IGB_TX_PTHRESH; txdctl |= IGB_TX_HTHRESH << 8; txdctl |= IGB_TX_WTHRESH << 16; @@ -3105,6 +3134,9 @@ igb_initialize_transmit_units(struct ada E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl); } + if (adapter->hw.mac.type == e1000_vfadapt) + return; + /* Program the Transmit Control Register */ tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_CT; @@ -3505,7 +3537,7 @@ igb_txeof(struct tx_ring *txr) /* All clean, turn off the watchdog */ if (txr->tx_avail == adapter->num_tx_desc) { txr->watchdog_check = FALSE; - return FALSE; + return (FALSE); } } @@ -4504,23 +4536,32 @@ igb_setup_vlan_hw_support(struct adapter ** we need to repopulate it now. */ for (int i = 0; i < IGB_VFTA_SIZE; i++) - if (igb_shadow_vfta[i] != 0) - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, - i, igb_shadow_vfta[i]); - - reg = E1000_READ_REG(hw, E1000_CTRL); - reg |= E1000_CTRL_VME; - E1000_WRITE_REG(hw, E1000_CTRL, reg); - - /* Enable the Filter Table */ - reg = E1000_READ_REG(hw, E1000_RCTL); - reg &= ~E1000_RCTL_CFIEN; - reg |= E1000_RCTL_VFE; - E1000_WRITE_REG(hw, E1000_RCTL, reg); + if (igb_shadow_vfta[i] != 0) { + if (hw->mac.type == e1000_vfadapt) + e1000_vfta_set_vf(hw, igb_shadow_vfta[i], TRUE); + else + E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, + i, igb_shadow_vfta[i]); + } - /* Update the frame size */ - E1000_WRITE_REG(&adapter->hw, E1000_RLPML, - adapter->max_frame_size + VLAN_TAG_SIZE); + if (hw->mac.type == e1000_vfadapt) + e1000_rlpml_set_vf(hw, + adapter->max_frame_size + VLAN_TAG_SIZE); + else { + reg = E1000_READ_REG(hw, E1000_CTRL); + reg |= E1000_CTRL_VME; + E1000_WRITE_REG(hw, E1000_CTRL, reg); + + /* Enable the Filter Table */ + reg = E1000_READ_REG(hw, E1000_RCTL); + reg &= ~E1000_RCTL_CFIEN; + reg |= E1000_RCTL_VFE; + E1000_WRITE_REG(hw, E1000_RCTL, reg); + + /* Update the frame size */ + E1000_WRITE_REG(&adapter->hw, E1000_RLPML, + adapter->max_frame_size + VLAN_TAG_SIZE); + } } static void @@ -4610,6 +4651,9 @@ igb_get_hw_control(struct adapter *adapt { u32 ctrl_ext; + if (adapter->hw.mac.type == e1000_vfadapt) + return; + /* Let firmware know the driver has taken over */ ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, @@ -4627,6 +4671,9 @@ igb_release_hw_control(struct adapter *a { u32 ctrl_ext; + if (adapter->hw.mac.type == e1000_vfadapt) + return; + /* Let firmware taken over control of h/w */ ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, @@ -4694,138 +4741,190 @@ igb_led_func(void *arg, int onoff) static void igb_update_stats_counters(struct adapter *adapter) { - struct ifnet *ifp; + struct ifnet *ifp; + struct e1000_hw *hw = &adapter->hw; + struct e1000_hw_stats *stats; - if (adapter->hw.phy.media_type == e1000_media_type_copper || - (E1000_READ_REG(&adapter->hw, E1000_STATUS) & E1000_STATUS_LU)) { - adapter->stats.symerrs += - E1000_READ_REG(&adapter->hw, E1000_SYMERRS); - adapter->stats.sec += - E1000_READ_REG(&adapter->hw, E1000_SEC); - } - adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, E1000_CRCERRS); - adapter->stats.mpc += E1000_READ_REG(&adapter->hw, E1000_MPC); - adapter->stats.scc += E1000_READ_REG(&adapter->hw, E1000_SCC); - adapter->stats.ecol += E1000_READ_REG(&adapter->hw, E1000_ECOL); - - adapter->stats.mcc += E1000_READ_REG(&adapter->hw, E1000_MCC); - adapter->stats.latecol += E1000_READ_REG(&adapter->hw, E1000_LATECOL); - adapter->stats.colc += E1000_READ_REG(&adapter->hw, E1000_COLC); - adapter->stats.dc += E1000_READ_REG(&adapter->hw, E1000_DC); - adapter->stats.rlec += E1000_READ_REG(&adapter->hw, E1000_RLEC); - adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, E1000_XONRXC); - adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, E1000_XONTXC); - adapter->stats.xoffrxc += E1000_READ_REG(&adapter->hw, E1000_XOFFRXC); - adapter->stats.xofftxc += E1000_READ_REG(&adapter->hw, E1000_XOFFTXC); - adapter->stats.fcruc += E1000_READ_REG(&adapter->hw, E1000_FCRUC); - adapter->stats.prc64 += E1000_READ_REG(&adapter->hw, E1000_PRC64); - adapter->stats.prc127 += E1000_READ_REG(&adapter->hw, E1000_PRC127); - adapter->stats.prc255 += E1000_READ_REG(&adapter->hw, E1000_PRC255); - adapter->stats.prc511 += E1000_READ_REG(&adapter->hw, E1000_PRC511); - adapter->stats.prc1023 += E1000_READ_REG(&adapter->hw, E1000_PRC1023); - adapter->stats.prc1522 += E1000_READ_REG(&adapter->hw, E1000_PRC1522); - adapter->stats.gprc += E1000_READ_REG(&adapter->hw, E1000_GPRC); - adapter->stats.bprc += E1000_READ_REG(&adapter->hw, E1000_BPRC); - adapter->stats.mprc += E1000_READ_REG(&adapter->hw, E1000_MPRC); - adapter->stats.gptc += E1000_READ_REG(&adapter->hw, E1000_GPTC); + /* + ** The virtual function adapter has only a + ** small controlled set of stats, do only + ** those and return. + */ + if (adapter->hw.mac.type == e1000_vfadapt) { + igb_update_vf_stats_counters(adapter); + return; + } + + stats = (struct e1000_hw_stats *)adapter->stats; + + if(adapter->hw.phy.media_type == e1000_media_type_copper || + (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { + stats->symerrs += + E1000_READ_REG(hw,E1000_SYMERRS); + stats->sec += E1000_READ_REG(hw, E1000_SEC); + } + + stats->crcerrs += E1000_READ_REG(hw, E1000_CRCERRS); + stats->mpc += E1000_READ_REG(hw, E1000_MPC); + stats->scc += E1000_READ_REG(hw, E1000_SCC); + stats->ecol += E1000_READ_REG(hw, E1000_ECOL); + + stats->mcc += E1000_READ_REG(hw, E1000_MCC); + stats->latecol += E1000_READ_REG(hw, E1000_LATECOL); + stats->colc += E1000_READ_REG(hw, E1000_COLC); + stats->dc += E1000_READ_REG(hw, E1000_DC); + stats->rlec += E1000_READ_REG(hw, E1000_RLEC); + stats->xonrxc += E1000_READ_REG(hw, E1000_XONRXC); + stats->xontxc += E1000_READ_REG(hw, E1000_XONTXC); + stats->xoffrxc += E1000_READ_REG(hw, E1000_XOFFRXC); + stats->xofftxc += E1000_READ_REG(hw, E1000_XOFFTXC); + stats->fcruc += E1000_READ_REG(hw, E1000_FCRUC); + stats->prc64 += E1000_READ_REG(hw, E1000_PRC64); + stats->prc127 += E1000_READ_REG(hw, E1000_PRC127); + stats->prc255 += E1000_READ_REG(hw, E1000_PRC255); + stats->prc511 += E1000_READ_REG(hw, E1000_PRC511); + stats->prc1023 += E1000_READ_REG(hw, E1000_PRC1023); + stats->prc1522 += E1000_READ_REG(hw, E1000_PRC1522); + stats->gprc += E1000_READ_REG(hw, E1000_GPRC); + stats->bprc += E1000_READ_REG(hw, E1000_BPRC); + stats->mprc += E1000_READ_REG(hw, E1000_MPRC); + stats->gptc += E1000_READ_REG(hw, E1000_GPTC); /* For the 64-bit byte counters the low dword must be read first. */ /* Both registers clear on the read of the high dword */ - adapter->stats.gorc += E1000_READ_REG(&adapter->hw, E1000_GORCL) + - ((u64)E1000_READ_REG(&adapter->hw, E1000_GORCH) << 32); - adapter->stats.gotc += E1000_READ_REG(&adapter->hw, E1000_GOTCL) + - ((u64)E1000_READ_REG(&adapter->hw, E1000_GOTCH) << 32) ; - - adapter->stats.rnbc += E1000_READ_REG(&adapter->hw, E1000_RNBC); - adapter->stats.ruc += E1000_READ_REG(&adapter->hw, E1000_RUC); - adapter->stats.rfc += E1000_READ_REG(&adapter->hw, E1000_RFC); - adapter->stats.roc += E1000_READ_REG(&adapter->hw, E1000_ROC); - adapter->stats.rjc += E1000_READ_REG(&adapter->hw, E1000_RJC); - - adapter->stats.tor += E1000_READ_REG(&adapter->hw, E1000_TORH); - adapter->stats.tot += E1000_READ_REG(&adapter->hw, E1000_TOTH); - - adapter->stats.tpr += E1000_READ_REG(&adapter->hw, E1000_TPR); - adapter->stats.tpt += E1000_READ_REG(&adapter->hw, E1000_TPT); - adapter->stats.ptc64 += E1000_READ_REG(&adapter->hw, E1000_PTC64); - adapter->stats.ptc127 += E1000_READ_REG(&adapter->hw, E1000_PTC127); - adapter->stats.ptc255 += E1000_READ_REG(&adapter->hw, E1000_PTC255); - adapter->stats.ptc511 += E1000_READ_REG(&adapter->hw, E1000_PTC511); - adapter->stats.ptc1023 += E1000_READ_REG(&adapter->hw, E1000_PTC1023); - adapter->stats.ptc1522 += E1000_READ_REG(&adapter->hw, E1000_PTC1522); - adapter->stats.mptc += E1000_READ_REG(&adapter->hw, E1000_MPTC); - adapter->stats.bptc += E1000_READ_REG(&adapter->hw, E1000_BPTC); + stats->gorc += E1000_READ_REG(hw, E1000_GORCL) + + ((u64)E1000_READ_REG(hw, E1000_GORCH) << 32); + stats->gotc += E1000_READ_REG(hw, E1000_GOTCL) + + ((u64)E1000_READ_REG(hw, E1000_GOTCH) << 32) ; + + stats->rnbc += E1000_READ_REG(hw, E1000_RNBC); + stats->ruc += E1000_READ_REG(hw, E1000_RUC); + stats->rfc += E1000_READ_REG(hw, E1000_RFC); + stats->roc += E1000_READ_REG(hw, E1000_ROC); + stats->rjc += E1000_READ_REG(hw, E1000_RJC); + + stats->tor += E1000_READ_REG(hw, E1000_TORH); + stats->tot += E1000_READ_REG(hw, E1000_TOTH); + + stats->tpr += E1000_READ_REG(hw, E1000_TPR); + stats->tpt += E1000_READ_REG(hw, E1000_TPT); + stats->ptc64 += E1000_READ_REG(hw, E1000_PTC64); + stats->ptc127 += E1000_READ_REG(hw, E1000_PTC127); + stats->ptc255 += E1000_READ_REG(hw, E1000_PTC255); + stats->ptc511 += E1000_READ_REG(hw, E1000_PTC511); + stats->ptc1023 += E1000_READ_REG(hw, E1000_PTC1023); + stats->ptc1522 += E1000_READ_REG(hw, E1000_PTC1522); + stats->mptc += E1000_READ_REG(hw, E1000_MPTC); + stats->bptc += E1000_READ_REG(hw, E1000_BPTC); /* Interrupt Counts */ - adapter->stats.iac += E1000_READ_REG(&adapter->hw, E1000_IAC); - adapter->stats.icrxptc += E1000_READ_REG(&adapter->hw, E1000_ICRXPTC); - adapter->stats.icrxatc += E1000_READ_REG(&adapter->hw, E1000_ICRXATC); - adapter->stats.ictxptc += E1000_READ_REG(&adapter->hw, E1000_ICTXPTC); - adapter->stats.ictxatc += E1000_READ_REG(&adapter->hw, E1000_ICTXATC); - adapter->stats.ictxqec += E1000_READ_REG(&adapter->hw, E1000_ICTXQEC); - adapter->stats.ictxqmtc += E1000_READ_REG(&adapter->hw, E1000_ICTXQMTC); - adapter->stats.icrxdmtc += E1000_READ_REG(&adapter->hw, E1000_ICRXDMTC); - adapter->stats.icrxoc += E1000_READ_REG(&adapter->hw, E1000_ICRXOC); + stats->iac += E1000_READ_REG(hw, E1000_IAC); + stats->icrxptc += E1000_READ_REG(hw, E1000_ICRXPTC); + stats->icrxatc += E1000_READ_REG(hw, E1000_ICRXATC); + stats->ictxptc += E1000_READ_REG(hw, E1000_ICTXPTC); + stats->ictxatc += E1000_READ_REG(hw, E1000_ICTXATC); + stats->ictxqec += E1000_READ_REG(hw, E1000_ICTXQEC); + stats->ictxqmtc += E1000_READ_REG(hw, E1000_ICTXQMTC); + stats->icrxdmtc += E1000_READ_REG(hw, E1000_ICRXDMTC); + stats->icrxoc += E1000_READ_REG(hw, E1000_ICRXOC); /* Host to Card Statistics */ - adapter->stats.cbtmpc += E1000_READ_REG(&adapter->hw, E1000_CBTMPC); - adapter->stats.htdpmc += E1000_READ_REG(&adapter->hw, E1000_HTDPMC); - adapter->stats.cbrdpc += E1000_READ_REG(&adapter->hw, E1000_CBRDPC); - adapter->stats.cbrmpc += E1000_READ_REG(&adapter->hw, E1000_CBRMPC); - adapter->stats.rpthc += E1000_READ_REG(&adapter->hw, E1000_RPTHC); - adapter->stats.hgptc += E1000_READ_REG(&adapter->hw, E1000_HGPTC); - adapter->stats.htcbdpc += E1000_READ_REG(&adapter->hw, E1000_HTCBDPC); - adapter->stats.hgorc += (E1000_READ_REG(&adapter->hw, E1000_HGORCL) + - ((u64)E1000_READ_REG(&adapter->hw, - E1000_HGORCH) << 32)); - - adapter->stats.hgotc += (E1000_READ_REG(&adapter->hw, E1000_HGOTCL) + - ((u64)E1000_READ_REG(&adapter->hw, - E1000_HGOTCH) << 32)); - adapter->stats.lenerrs += E1000_READ_REG(&adapter->hw, E1000_LENERRS); - adapter->stats.scvpc += E1000_READ_REG(&adapter->hw, E1000_SCVPC); - adapter->stats.hrmpc += E1000_READ_REG(&adapter->hw, E1000_HRMPC); - - adapter->stats.algnerrc += - E1000_READ_REG(&adapter->hw, E1000_ALGNERRC); - adapter->stats.rxerrc += - E1000_READ_REG(&adapter->hw, E1000_RXERRC); - adapter->stats.tncrs += - E1000_READ_REG(&adapter->hw, E1000_TNCRS); - adapter->stats.cexterr += - E1000_READ_REG(&adapter->hw, E1000_CEXTERR); - adapter->stats.tsctc += - E1000_READ_REG(&adapter->hw, E1000_TSCTC); - adapter->stats.tsctfc += - E1000_READ_REG(&adapter->hw, E1000_TSCTFC); + stats->cbtmpc += E1000_READ_REG(hw, E1000_CBTMPC); + stats->htdpmc += E1000_READ_REG(hw, E1000_HTDPMC); + stats->cbrdpc += E1000_READ_REG(hw, E1000_CBRDPC); + stats->cbrmpc += E1000_READ_REG(hw, E1000_CBRMPC); + stats->rpthc += E1000_READ_REG(hw, E1000_RPTHC); + stats->hgptc += E1000_READ_REG(hw, E1000_HGPTC); + stats->htcbdpc += E1000_READ_REG(hw, E1000_HTCBDPC); + stats->hgorc += (E1000_READ_REG(hw, E1000_HGORCL) + + ((u64)E1000_READ_REG(hw, E1000_HGORCH) << 32)); + stats->hgotc += (E1000_READ_REG(hw, E1000_HGOTCL) + + ((u64)E1000_READ_REG(hw, E1000_HGOTCH) << 32)); + stats->lenerrs += E1000_READ_REG(hw, E1000_LENERRS); + stats->scvpc += E1000_READ_REG(hw, E1000_SCVPC); + stats->hrmpc += E1000_READ_REG(hw, E1000_HRMPC); + + stats->algnerrc += E1000_READ_REG(hw, E1000_ALGNERRC); + stats->rxerrc += E1000_READ_REG(hw, E1000_RXERRC); + stats->tncrs += E1000_READ_REG(hw, E1000_TNCRS); + stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR); + stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC); + stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC); ifp = adapter->ifp; - ifp->if_collisions = adapter->stats.colc; + ifp = adapter->ifp; + ifp->if_collisions = stats->colc; /* Rx Errors */ - ifp->if_ierrors = adapter->dropped_pkts + adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.ruc + adapter->stats.roc + - adapter->stats.mpc + adapter->stats.cexterr; + ifp->if_ierrors = adapter->dropped_pkts + stats->rxerrc + + stats->crcerrs + stats->algnerrc + + stats->ruc + stats->roc + stats->mpc + stats->cexterr; /* Tx Errors */ - ifp->if_oerrors = adapter->stats.ecol + - adapter->stats.latecol + adapter->watchdog_events; + ifp->if_oerrors = stats->ecol + + stats->latecol + adapter->watchdog_events; /* Driver specific counters */ - adapter->device_control = E1000_READ_REG(&adapter->hw, E1000_CTRL); - adapter->rx_control = E1000_READ_REG(&adapter->hw, E1000_RCTL); - adapter->int_mask = E1000_READ_REG(&adapter->hw, E1000_IMS); - adapter->eint_mask = E1000_READ_REG(&adapter->hw, E1000_EIMS); - adapter->packet_buf_alloc_tx = ((E1000_READ_REG(&adapter->hw, E1000_PBA) - & 0xffff0000) >> 16); + adapter->device_control = E1000_READ_REG(hw, E1000_CTRL); + adapter->rx_control = E1000_READ_REG(hw, E1000_RCTL); + adapter->int_mask = E1000_READ_REG(hw, E1000_IMS); + adapter->eint_mask = E1000_READ_REG(hw, E1000_EIMS); + adapter->packet_buf_alloc_tx = + ((E1000_READ_REG(hw, E1000_PBA) & 0xffff0000) >> 16); + adapter->packet_buf_alloc_rx = + ((E1000_READ_REG(hw, E1000_PBA) & 0xffff); +} - adapter->packet_buf_alloc_rx = (E1000_READ_REG(&adapter->hw, E1000_PBA) - & 0xffff); +/********************************************************************** + * + * Initialize the VF board statistics counters. + * + **********************************************************************/ +static void +igb_vf_init_stats(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_vf_stats *stats; + + stats = (struct e1000_vf_stats *)adapter->stats; + + stats->last_gprc = E1000_READ_REG(hw, E1000_VFGPRC); + stats->last_gorc = E1000_READ_REG(hw, E1000_VFGORC); + stats->last_gptc = E1000_READ_REG(hw, E1000_VFGPTC); + stats->last_gotc = E1000_READ_REG(hw, E1000_VFGOTC); + stats->last_mprc = E1000_READ_REG(hw, E1000_VFMPRC); +} + +/********************************************************************** + * + * Update the VF board statistics counters. + * + **********************************************************************/ +static void +igb_update_vf_stats_counters(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_vf_stats *stats; + + if (adapter->link_speed == 0) + return; + + stats = (struct e1000_vf_stats *)adapter->stats; + + UPDATE_VF_REG(E1000_VFGPRC, + stats->last_gprc, stats->gprc); + UPDATE_VF_REG(E1000_VFGORC, + stats->last_gorc, stats->gorc); + UPDATE_VF_REG(E1000_VFGPTC, + stats->last_gptc, stats->gptc); + UPDATE_VF_REG(E1000_VFGOTC, + stats->last_gotc, stats->gotc); + UPDATE_VF_REG(E1000_VFMPRC, + stats->last_mprc, stats->mprc); } @@ -4895,10 +4994,14 @@ igb_add_hw_stats(struct adapter *adapter queue_list = SYSCTL_CHILDREN(queue_node); SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "txd_head", - CTLFLAG_RD, &txr->tdh, 0, + CTLFLAG_RD, + E1000_READ_REG(&adapter->hw, + E1000_TDH(txr->me)), 0, "Transmit Descriptor Head"); SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "txd_tail", - CTLFLAG_RD, &txr->tdt, 0, + CTLFLAG_RD, + E1000_READ_REG(&adapter->hw, + E1000_TDT(txr->me))), 0, "Transmit Descriptor Tail"); SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "no_desc_avail", CTLFLAG_RD, &txr->no_desc_avail, @@ -4947,6 +5050,29 @@ igb_add_hw_stats(struct adapter *adapter CTLFLAG_RD, NULL, "MAC Statistics"); stat_list = SYSCTL_CHILDREN(stat_node); + /* + ** VF adapter has a very limited set of stats + ** since its not managing the metal, so to speak. + */ + if (adapter->hw.mac.type == e1000_vfadapt) { + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd", + CTLFLAG_RD, &adapter->stats.gprc, + "Good Packets Received"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", + CTLFLAG_RD, &adapter->stats.gptc, + "Good Packets Transmitted"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd", + CTLFLAG_RD, &adapter->stats.gorc, + "Good Octets Received"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octest_txd", + CTLFLAG_RD, &adapter->stats.gotc, + "Good Octest Transmitted"); + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd", + CTLFLAG_RD, &adapter->stats.mprc, + "Multicast Packets Received"); + return; + } + SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "excess_coll", CTLFLAG_RD, &stats->ecol, "Excessive collisions"); @@ -4989,12 +5115,6 @@ igb_add_hw_stats(struct adapter *adapter SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_jabber", CTLFLAG_RD, &adapter->stats.rjc, "Recevied Jabber"); - - /* RLEC is inaccurate on some hardware, calculate our own. */ -/* SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_len_errs", */ -/* CTLFLAG_RD, adapter->stats.roc + adapter->stats.ruc, */ -/* "Receive Length Errors"); */ - SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_errs", CTLFLAG_RD, &adapter->stats.rxerrc, "Receive Errors"); @@ -5200,9 +5320,9 @@ igb_add_hw_stats(struct adapter *adapter SYSCTL_ADD_QUAD(ctx, host_list, OID_AUTO, "header_redir_missed", CTLFLAG_RD, &adapter->stats.hrmpc, "Header Redirection Missed Packet Count"); +} -} /********************************************************************** * * This routine provides a way to dump out the adapter eeprom, Modified: head/sys/dev/e1000/if_igb.h ============================================================================== --- head/sys/dev/e1000/if_igb.h Wed Jun 30 17:20:33 2010 (r209610) +++ head/sys/dev/e1000/if_igb.h Wed Jun 30 17:26:47 2010 (r209611) @@ -180,7 +180,8 @@ #define IGB_TX_PTHRESH 8 #define IGB_TX_HTHRESH 1 -#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \ +#define IGB_TX_WTHRESH (((hw->mac.type == e1000_82576 || \ + hw->mac.type == e1000_vfadapt) && \ adapter->msix_mem) ? 1 : 16) #define MAX_NUM_MULTICAST_ADDRESSES 128 @@ -317,9 +318,6 @@ struct tx_ring { int watchdog_time; u64 no_desc_avail; u64 tx_packets; - /* Statistics for reporting, ONLY. */ - u32 tdh; /* Transmit Descriptor Head */ - u32 tdt; /* Transmit Descriptor Tail */ }; /* @@ -356,9 +354,6 @@ struct rx_ring { u64 rx_discarded; u64 rx_packets; u64 rx_bytes; - /* Statistics for reporting, ONLY. */ - u32 rdh; /* Transmit Descriptor Head */ - u32 rdt; /* Transmit Descriptor Tail */ }; struct adapter { @@ -449,7 +444,7 @@ struct adapter { struct hwtstamp_ctrl hwtstamp; #endif - struct e1000_hw_stats stats; + void *stats; }; /* ****************************************************************************** @@ -497,7 +492,17 @@ struct igb_rx_buf { #define IGB_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx) #define IGB_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx) #define IGB_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx) -#define IGB_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED) +#define IGB_RX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rx_mtx, MA_OWNED) + +#define UPDATE_VF_REG(reg, last, cur) \ +{ \ + u32 new = E1000_READ_REG(hw, reg); \ + if (new < last) \ + cur += 0x100000000LL; \ + last = new; \ + cur &= 0xFFFFFFFF00000000LL; \ + cur |= new; \ +} #endif /* _IGB_H_DEFINED_ */