From owner-svn-src-head@freebsd.org Tue May 30 11:53:20 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 012D4B7ADE8; Tue, 30 May 2017 11:53:20 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id CFBEB82AED; Tue, 30 May 2017 11:53:19 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v4UBrJbV075764; Tue, 30 May 2017 11:53:19 GMT (envelope-from zbb@FreeBSD.org) Received: (from zbb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4UBrIYi075761; Tue, 30 May 2017 11:53:18 GMT (envelope-from zbb@FreeBSD.org) Message-Id: <201705301153.v4UBrIYi075761@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: zbb set sender to zbb@FreeBSD.org using -f From: Zbigniew Bodek Date: Tue, 30 May 2017 11:53:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r319197 - head/sys/dev/ena X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 30 May 2017 11:53:20 -0000 Author: zbb Date: Tue May 30 11:53:18 2017 New Revision: 319197 URL: https://svnweb.freebsd.org/changeset/base/319197 Log: Add mbuf defragmentation to the ENA driver When mbuf chain is too long and device cannot handle that number of segments in DMA transaction, mbuf chain will be defragmented. Initially, driver was dropping all mbuf chains that were exceeding supported number of segments. Submitted by: Michal Krawczyk Obtained from: Semihalf Sponsored by: Amazon.com Inc. Differential revision: https://reviews.freebsd.org/D10923 Modified: head/sys/dev/ena/ena.c head/sys/dev/ena/ena.h head/sys/dev/ena/ena_sysctl.c Modified: head/sys/dev/ena/ena.c ============================================================================== --- head/sys/dev/ena/ena.c Tue May 30 11:03:05 2017 (r319196) +++ head/sys/dev/ena/ena.c Tue May 30 11:53:18 2017 (r319197) @@ -155,7 +155,7 @@ static void ena_update_hwassist(struct ena_adapter *); static int ena_setup_ifnet(device_t, struct ena_adapter *, struct ena_com_dev_get_features_ctx *); static void ena_tx_csum(struct ena_com_tx_ctx *, struct mbuf *); -static int ena_xmit_mbuf(struct ena_ring *, struct mbuf *); +static int ena_xmit_mbuf(struct ena_ring *, struct mbuf **); static void ena_start_xmit(struct ena_ring *); static int ena_mq_start(if_t, struct mbuf *); static void ena_deferred_mq_start(void *, int); @@ -2601,9 +2601,36 @@ ena_tx_csum(struct ena_com_tx_ctx *ena_tx_ctx, struct } static int -ena_xmit_mbuf(struct ena_ring *tx_ring, struct mbuf *mbuf) +ena_check_and_defragment_mbuf(struct ena_ring *tx_ring, struct mbuf **mbuf) { struct ena_adapter *adapter; + struct mbuf *defrag_mbuf; + int num_frags; + + adapter = tx_ring->adapter; + num_frags = ena_mbuf_count(*mbuf); + + /* One segment must be reserved for configuration descriptor. */ + if (num_frags < adapter->max_tx_sgl_size) + return (0); + counter_u64_add(tx_ring->tx_stats.defragment, 1); + + defrag_mbuf = m_defrag(*mbuf, M_NOWAIT); + if (defrag_mbuf == NULL) { + counter_u64_add(tx_ring->tx_stats.defragment_err, 1); + return (ENOMEM); + } + + /* If mbuf was defragmented succesfully, original mbuf is released. */ + *mbuf = defrag_mbuf; + + return (0); +} + +static int +ena_xmit_mbuf(struct ena_ring *tx_ring, struct mbuf **mbuf) +{ + struct ena_adapter *adapter; struct ena_tx_buffer *tx_info; struct ena_com_tx_ctx ena_tx_ctx; struct ena_com_dev *ena_dev; @@ -2617,40 +2644,40 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, struct mbuf *m uint16_t ena_qid; uint32_t len, nsegs, header_len; int i, rc; - int nb_hw_desc, num_frags; + int nb_hw_desc; ena_qid = ENA_IO_TXQ_IDX(tx_ring->que->id); adapter = tx_ring->que->adapter; ena_dev = adapter->ena_dev; io_sq = &adapter->ena_dev->io_sq_queues[ena_qid]; - ENA_ASSERT(mbuf, "mbuf is NULL\n"); + ENA_ASSERT(*mbuf, "mbuf is NULL\n"); - num_frags = ena_mbuf_count(mbuf); - if (num_frags > (adapter->max_tx_sgl_size - 2)) { - device_printf(adapter->pdev, - "too many fragments. Last fragment: %d!\n", num_frags); - return (ENA_COM_INVAL); + rc = ena_check_and_defragment_mbuf(tx_ring, mbuf); + if (rc) { + ena_trace(ENA_WARNING, + "Failed to defragment mbuf! err: %d", rc); + return (rc); } next_to_use = tx_ring->next_to_use; req_id = tx_ring->free_tx_ids[next_to_use]; tx_info = &tx_ring->tx_buffer_info[req_id]; - tx_info->mbuf = mbuf; + tx_info->mbuf = *mbuf; tx_info->num_of_bufs = 0; ena_buf = tx_info->bufs; - len = mbuf->m_len; + len = (*mbuf)->m_len; - ena_trace(ENA_DBG | ENA_TXPTH, "Tx: %d bytes", mbuf->m_pkthdr.len); + ena_trace(ENA_DBG | ENA_TXPTH, "Tx: %d bytes", (*mbuf)->m_pkthdr.len); push_len = 0; header_len = min_t(uint32_t, len, tx_ring->tx_max_header_size); push_hdr = NULL; rc = bus_dmamap_load_mbuf_sg(adapter->tx_buf_tag, tx_info->map, - mbuf, segs, &nsegs, BUS_DMA_NOWAIT); + *mbuf, segs, &nsegs, BUS_DMA_NOWAIT); if (rc || (nsegs == 0)) { ena_trace(ENA_WARNING, @@ -2678,7 +2705,7 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, struct mbuf *m ena_tx_ctx.header_len = header_len; /* Set flags and meta data */ - ena_tx_csum(&ena_tx_ctx, mbuf); + ena_tx_csum(&ena_tx_ctx, *mbuf); /* Prepare the packet's descriptors and send them to device */ rc = ena_com_prepare_tx(io_sq, &ena_tx_ctx, &nb_hw_desc); if (rc != 0) { @@ -2692,7 +2719,7 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, struct mbuf *m counter_enter(); counter_u64_add_protected(tx_ring->tx_stats.cnt, 1); - counter_u64_add_protected(tx_ring->tx_stats.bytes, mbuf->m_pkthdr.len); + counter_u64_add_protected(tx_ring->tx_stats.bytes, (*mbuf)->m_pkthdr.len); counter_exit(); tx_info->tx_descs = nb_hw_desc; @@ -2740,7 +2767,7 @@ ena_start_xmit(struct ena_ring *tx_ring) if (ena_com_sq_empty_space(io_sq) < ENA_TX_CLEANUP_TRESHOLD) ena_tx_cleanup(tx_ring); - if ((ret = ena_xmit_mbuf(tx_ring, mbuf)) != 0) { + if ((ret = ena_xmit_mbuf(tx_ring, &mbuf)) != 0) { if (ret == ENA_COM_NO_MEM) { drbr_putback(adapter->ifp, tx_ring->br, mbuf); } else if (ret == ENA_COM_NO_SPACE) { Modified: head/sys/dev/ena/ena.h ============================================================================== --- head/sys/dev/ena/ena.h Tue May 30 11:03:05 2017 (r319196) +++ head/sys/dev/ena/ena.h Tue May 30 11:53:18 2017 (r319197) @@ -226,6 +226,8 @@ struct ena_stats_tx { counter_u64_t doorbells; counter_u64_t missing_tx_comp; counter_u64_t bad_req_id; + counter_u64_t defragment; + counter_u64_t defragment_err; }; struct ena_stats_rx { Modified: head/sys/dev/ena/ena_sysctl.c ============================================================================== --- head/sys/dev/ena/ena_sysctl.c Tue May 30 11:03:05 2017 (r319196) +++ head/sys/dev/ena/ena_sysctl.c Tue May 30 11:53:18 2017 (r319197) @@ -155,6 +155,14 @@ ena_sysctl_add_stats(struct ena_adapter *adapter) SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO, "stops", CTLFLAG_RD, &tx_stats->queue_stop, "Queue stops"); + SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO, + "defragmentations", CTLFLAG_RD, + &tx_stats->defragment, + "Mbuf defragmentations"); + SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO, + "defragmentation_err", CTLFLAG_RD, + &tx_stats->defragment_err, + "Mbuf defragmentation failures"); /* RX specific stats */ rx_node = SYSCTL_ADD_NODE(ctx, queue_list, OID_AUTO,