Index: sys/ofed/drivers/net/mlx4/en_netdev.c =================================================================== --- sys/ofed/drivers/net/mlx4/en_netdev.c +++ sys/ofed/drivers/net/mlx4/en_netdev.c @@ -1617,6 +1617,7 @@ priv->tx_ring[i]->bytes = 0; priv->tx_ring[i]->packets = 0; priv->tx_ring[i]->tx_csum = 0; + priv->tx_ring[i]->oversized_packets = 0; } for (i = 0; i < priv->rx_ring_num; i++) { priv->rx_ring[i]->bytes = 0; @@ -1803,8 +1804,11 @@ EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach); /* Unregister device - this will close the port if it was up */ - if (priv->registered) + if (priv->registered) { + mutex_lock(&mdev->state_lock); ether_ifdetach(dev); + mutex_unlock(&mdev->state_lock); + } if (priv->allocated) mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE); @@ -2012,22 +2016,22 @@ error = -mlx4_en_change_mtu(dev, ifr->ifr_mtu); break; case SIOCSIFFLAGS: + mutex_lock(&mdev->state_lock); if (dev->if_flags & IFF_UP) { if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) { - mutex_lock(&mdev->state_lock); mlx4_en_start_port(dev); - mutex_unlock(&mdev->state_lock); } else { + mutex_unlock(&mdev->state_lock); mlx4_en_set_rx_mode(dev); + break; } } else { - mutex_lock(&mdev->state_lock); if (dev->if_drv_flags & IFF_DRV_RUNNING) { mlx4_en_stop_port(dev); if_link_state_change(dev, LINK_STATE_DOWN); } - mutex_unlock(&mdev->state_lock); } + mutex_unlock(&mdev->state_lock); break; case SIOCADDMULTI: case SIOCDELMULTI: @@ -2040,14 +2044,58 @@ case SIOCSIFCAP: mutex_lock(&mdev->state_lock); mask = ifr->ifr_reqcap ^ dev->if_capenable; - if (mask & IFCAP_HWCSUM) - dev->if_capenable ^= IFCAP_HWCSUM; - if (mask & IFCAP_TSO4) + if (mask & IFCAP_TXCSUM) { + dev->if_capenable ^= IFCAP_TXCSUM; + dev->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP); + + if (IFCAP_TSO4 & dev->if_capenable && + !(IFCAP_TXCSUM & dev->if_capenable)) { + dev->if_capenable &= ~IFCAP_TSO4; + dev->if_hwassist &= ~CSUM_IP_TSO; + if_printf(dev, + "tso4 disabled due to -txcsum.\n"); + } + } + if (mask & IFCAP_TXCSUM_IPV6) { + dev->if_capenable ^= IFCAP_TXCSUM_IPV6; + dev->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6); + + if (IFCAP_TSO6 & dev->if_capenable && + !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) { + dev->if_capenable &= ~IFCAP_TSO6; + dev->if_hwassist &= ~CSUM_IP6_TSO; + if_printf(dev, + "tso6 disabled due to -txcsum6.\n"); + } + } + if (mask & IFCAP_RXCSUM) + dev->if_capenable ^= IFCAP_RXCSUM; + if (mask & IFCAP_RXCSUM_IPV6) + dev->if_capenable ^= IFCAP_RXCSUM_IPV6; + + if (mask & IFCAP_TSO4) { + if (!(IFCAP_TSO4 & dev->if_capenable) && + !(IFCAP_TXCSUM & dev->if_capenable)) { + if_printf(dev, "enable txcsum first.\n"); + error = EAGAIN; + goto out; + } dev->if_capenable ^= IFCAP_TSO4; - if (mask & IFCAP_TSO6) + dev->if_hwassist ^= CSUM_IP_TSO; + } + if (mask & IFCAP_TSO6) { + if (!(IFCAP_TSO6 & dev->if_capenable) && + !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) { + if_printf(dev, "enable txcsum6 first.\n"); + error = EAGAIN; + goto out; + } dev->if_capenable ^= IFCAP_TSO6; + dev->if_hwassist ^= CSUM_IP6_TSO; + } if (mask & IFCAP_LRO) dev->if_capenable ^= IFCAP_LRO; + if (mask & IFCAP_VLAN_HWTAGGING) dev->if_capenable ^= IFCAP_VLAN_HWTAGGING; if (mask & IFCAP_VLAN_HWFILTER) @@ -2056,6 +2104,7 @@ dev->if_capenable ^= IFCAP_WOL_MAGIC; if (dev->if_drv_flags & IFF_DRV_RUNNING) mlx4_en_start_port(dev); +out: mutex_unlock(&mdev->state_lock); VLAN_CAPABILITIES(dev); break; @@ -2315,7 +2364,7 @@ /* * Set driver features */ - dev->if_capabilities |= IFCAP_RXCSUM | IFCAP_TXCSUM; + dev->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6; dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER; dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU; @@ -2340,6 +2389,8 @@ dev->if_hwassist |= CSUM_TSO; if (dev->if_capenable & IFCAP_TXCSUM) dev->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP); + if (dev->if_capenable & IFCAP_TXCSUM_IPV6) + dev->if_hwassist |= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6); /* Register for VLAN events */ @@ -3161,6 +3212,8 @@ &priv->port_stats.wake_queue, "Queue resumed after full"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_timeout", CTLFLAG_RD, &priv->port_stats.tx_timeout, "Transmit timeouts"); + SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_oversized_packets", CTLFLAG_RD, + &priv->port_stats.oversized_packets, "TX oversized packets, m_defrag failed"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_alloc_failed", CTLFLAG_RD, &priv->port_stats.rx_alloc_failed, "RX failed to allocate mbuf"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_good", CTLFLAG_RD, Index: sys/ofed/drivers/net/mlx4/en_port.c =================================================================== --- sys/ofed/drivers/net/mlx4/en_port.c +++ sys/ofed/drivers/net/mlx4/en_port.c @@ -198,6 +198,7 @@ priv->port_stats.tx_chksum_offload += priv->tx_ring[i]->tx_csum; priv->port_stats.queue_stopped += priv->tx_ring[i]->queue_stopped; priv->port_stats.wake_queue += priv->tx_ring[i]->wake_queue; + priv->port_stats.oversized_packets += priv->tx_ring[i]->oversized_packets; } /* RX Statistics */ priv->pkstats.rx_packets = be64_to_cpu(mlx4_en_stats->RTOT_prio_0) + Index: sys/ofed/drivers/net/mlx4/en_rx.c =================================================================== --- sys/ofed/drivers/net/mlx4/en_rx.c +++ sys/ofed/drivers/net/mlx4/en_rx.c @@ -611,7 +611,8 @@ mb->m_pkthdr.ether_vtag = be16_to_cpu(cqe->sl_vid); mb->m_flags |= M_VLANTAG; } - if (likely(dev->if_capabilities & IFCAP_RXCSUM) && + if (likely(dev->if_capenable & + (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) && (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && (cqe->checksum == cpu_to_be16(0xffff))) { priv->port_stats.rx_chksum_good++; @@ -692,6 +693,7 @@ // Because there is no NAPI in freeBSD done = mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET); if (priv->port_up && (done == MLX4_EN_RX_BUDGET) ) { + cq->curr_poll_rx_cpu_id = curcpu; taskqueue_enqueue(cq->tq, &cq->cq_task); } else { @@ -702,8 +704,15 @@ void mlx4_en_rx_que(void *context, int pending) { struct mlx4_en_cq *cq; + struct thread *td; cq = context; + td = curthread; + + thread_lock(td); + sched_bind(td, cq->curr_poll_rx_cpu_id); + thread_unlock(td); + while (mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET) == MLX4_EN_RX_BUDGET); mlx4_en_arm_cq(cq->dev->if_softc, cq); Index: sys/ofed/drivers/net/mlx4/en_tx.c =================================================================== --- sys/ofed/drivers/net/mlx4/en_tx.c +++ sys/ofed/drivers/net/mlx4/en_tx.c @@ -813,14 +813,6 @@ /* Optimize the common case when there are no wraparounds */ if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) { if (!tx_info->inl) { - if (tx_info->linear) { - dma_unmap_single(priv->ddev, - (dma_addr_t) be64_to_cpu(data->addr), - be32_to_cpu(data->byte_count), - PCI_DMA_TODEVICE); - ++data; - } - for (i = 0; i < frags; i++) { pci_unmap_single(mdev->pdev, (dma_addr_t) be64_to_cpu(data[i].addr), @@ -832,15 +824,6 @@ if ((void *) data >= end) { data = ring->buf + ((void *)data - end); } - - if (tx_info->linear) { - dma_unmap_single(priv->ddev, - (dma_addr_t) be64_to_cpu(data->addr), - be32_to_cpu(data->byte_count), - PCI_DMA_TODEVICE); - ++data; - } - for (i = 0; i < frags; i++) { /* Check for wraparound before unmapping */ if ((void *) data >= end) @@ -1271,11 +1254,7 @@ up = (vlan_tag >> 13) % MLX4_EN_NUM_UP; } #endif - /* check if flowid is set */ - if (M_HASHTYPE_GET(mb) != M_HASHTYPE_NONE) - queue_index = mb->m_pkthdr.flowid; - else - queue_index = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4, mb, hashrandom); + queue_index = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4, mb, hashrandom); return ((queue_index % rings_p_up) + (up * rings_p_up)); } @@ -1351,13 +1330,15 @@ mb = m_defrag(*mbp, M_NOWAIT); if (mb == NULL) { mb = *mbp; + ring->oversized_packets++; goto tx_drop; } *mbp = mb; defrag = 0; goto retry; } - en_warn(priv, "Oversized header or SG list\n"); + /*Oversized header or SG list*/ + ring->oversized_packets++; goto tx_drop; } @@ -1622,13 +1603,15 @@ } enqueued = 0; - if (m != NULL) { - if ((err = drbr_enqueue(dev, ring->br, m)) != 0) - return (err); - } + if (m != NULL) + /* If we can't insert mbuf into drbr, try to xmit anyway. + * We keep the error we got so we could return that after xmit. + */ + err = drbr_enqueue(dev, ring->br, m); + /* Process the queue */ while ((next = drbr_peek(dev, ring->br)) != NULL) { - if ((err = mlx4_en_xmit(dev, tx_ind, &next)) != 0) { + if (mlx4_en_xmit(dev, tx_ind, &next) != 0) { if (next == NULL) { drbr_advance(dev, ring->br); } else { @@ -1694,7 +1677,12 @@ else #endif /* Compute which queue to use */ - i = mlx4_en_select_queue(dev, m); + if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { + i = m->m_pkthdr.flowid % priv->tx_ring_num; + } + else { + i = mlx4_en_select_queue(dev, m); + } #ifdef CONFIG_RATELIMIT lock_and_transmit: Index: sys/ofed/drivers/net/mlx4/mlx4_en.h =================================================================== --- sys/ofed/drivers/net/mlx4/mlx4_en.h +++ sys/ofed/drivers/net/mlx4/mlx4_en.h @@ -260,7 +260,6 @@ struct mbuf *mb; u32 nr_txbb; u32 nr_bytes; - u8 linear; u8 nr_segs; u8 data_offset; u8 inl; @@ -334,6 +333,7 @@ unsigned long packets; unsigned long tx_csum; unsigned long queue_stopped; + unsigned long oversized_packets; unsigned long wake_queue; struct mlx4_bf bf; bool bf_enabled; @@ -437,6 +437,7 @@ #define MLX4_EN_OPCODE_ERROR 0x1e u32 tot_rx; u32 tot_tx; + u32 curr_poll_rx_cpu_id; #ifdef CONFIG_NET_RX_BUSY_POLL unsigned int state; Index: sys/ofed/drivers/net/mlx4/mlx4_stats.h =================================================================== --- sys/ofed/drivers/net/mlx4/mlx4_stats.h +++ sys/ofed/drivers/net/mlx4/mlx4_stats.h @@ -124,6 +124,7 @@ unsigned long queue_stopped; unsigned long wake_queue; unsigned long tx_timeout; + unsigned long oversized_packets; unsigned long rx_alloc_failed; unsigned long rx_chksum_good; unsigned long rx_chksum_none;