From owner-svn-src-head@freebsd.org Fri Nov 10 14:10:43 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 F3BF3E6EDB0; Fri, 10 Nov 2017 14:10:42 +0000 (UTC) (envelope-from hselasky@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 B28DF75069; Fri, 10 Nov 2017 14:10:42 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vAAEAfhB020897; Fri, 10 Nov 2017 14:10:41 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vAAEAfJp020894; Fri, 10 Nov 2017 14:10:41 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201711101410.vAAEAfJp020894@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Fri, 10 Nov 2017 14:10:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r325659 - head/sys/dev/mlx5/mlx5_en X-SVN-Group: head X-SVN-Commit-Author: hselasky X-SVN-Commit-Paths: head/sys/dev/mlx5/mlx5_en X-SVN-Commit-Revision: 325659 X-SVN-Commit-Repository: base 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: Fri, 10 Nov 2017 14:10:43 -0000 Author: hselasky Date: Fri Nov 10 14:10:41 2017 New Revision: 325659 URL: https://svnweb.freebsd.org/changeset/base/325659 Log: Add support for disabling and enabling RX and TX DMA rings in mlx5en(4). This is useful for supporting setups similar to Netmap. Sponsored by: Mellanox Technologies MFC after: 1 week Modified: head/sys/dev/mlx5/mlx5_en/en.h head/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c Modified: head/sys/dev/mlx5/mlx5_en/en.h ============================================================================== --- head/sys/dev/mlx5/mlx5_en/en.h Fri Nov 10 14:02:12 2017 (r325658) +++ head/sys/dev/mlx5/mlx5_en/en.h Fri Nov 10 14:10:41 2017 (r325659) @@ -408,6 +408,8 @@ struct mlx5e_params { m(+1, u64 tx_completion_fact_max, "tx_completion_fact_max", "Maximum completion event ratio") \ m(+1, u64 hw_lro, "hw_lro", "set to enable hw_lro") \ m(+1, u64 cqe_zipping, "cqe_zipping", "0 : CQE zipping disabled") \ + m(+1, u64 modify_tx_dma, "modify_tx_dma", "0: Enable TX 1: Disable TX") \ + m(+1, u64 modify_rx_dma, "modify_rx_dma", "0: Enable RX 1: Disable RX") \ m(+1, u64 diag_pci_enable, "diag_pci_enable", "0: Disabled 1: Enabled") \ m(+1, u64 diag_general_enable, "diag_general_enable", "0: Disabled 1: Enabled") @@ -837,5 +839,8 @@ int mlx5e_enable_sq(struct mlx5e_sq *, struct mlx5e_sq int mlx5e_modify_sq(struct mlx5e_sq *, int curr_state, int next_state); void mlx5e_disable_sq(struct mlx5e_sq *); void mlx5e_drain_sq(struct mlx5e_sq *); +void mlx5e_modify_tx_dma(struct mlx5e_priv *priv, uint8_t value); +void mlx5e_modify_rx_dma(struct mlx5e_priv *priv, uint8_t value); +void mlx5e_resume_sq(struct mlx5e_sq *sq); #endif /* _MLX5_EN_H_ */ Modified: head/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c ============================================================================== --- head/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c Fri Nov 10 14:02:12 2017 (r325658) +++ head/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c Fri Nov 10 14:10:41 2017 (r325659) @@ -377,6 +377,32 @@ mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) mlx5e_open_locked(priv->ifp); break; + case MLX5_PARAM_OFFSET(modify_tx_dma): + /* check if network interface is opened */ + if (was_opened) { + priv->params_ethtool.modify_tx_dma = + priv->params_ethtool.modify_tx_dma ? 1 : 0; + /* modify tx according to value */ + mlx5e_modify_tx_dma(priv, value != 0); + } else { + /* if closed force enable tx */ + priv->params_ethtool.modify_tx_dma = 0; + } + break; + + case MLX5_PARAM_OFFSET(modify_rx_dma): + /* check if network interface is opened */ + if (was_opened) { + priv->params_ethtool.modify_rx_dma = + priv->params_ethtool.modify_rx_dma ? 1 : 0; + /* modify rx according to value */ + mlx5e_modify_rx_dma(priv, value != 0); + } else { + /* if closed force enable rx */ + priv->params_ethtool.modify_rx_dma = 0; + } + break; + case MLX5_PARAM_OFFSET(diag_pci_enable): priv->params_ethtool.diag_pci_enable = priv->params_ethtool.diag_pci_enable ? 1 : 0; Modified: head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c ============================================================================== --- head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c Fri Nov 10 14:02:12 2017 (r325658) +++ head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c Fri Nov 10 14:10:41 2017 (r325659) @@ -2928,6 +2928,164 @@ sysctl_firmware(SYSCTL_HANDLER_ARGS) } static void +mlx5e_disable_tx_dma(struct mlx5e_channel *ch) +{ + int i; + + for (i = 0; i < ch->num_tc; i++) + mlx5e_drain_sq(&ch->sq[i]); +} + +static void +mlx5e_reset_sq_doorbell_record(struct mlx5e_sq *sq) +{ + + sq->doorbell.d32[0] = cpu_to_be32(MLX5_OPCODE_NOP); + sq->doorbell.d32[1] = cpu_to_be32(sq->sqn << 8); + mlx5e_tx_notify_hw(sq, sq->doorbell.d32, 0); + sq->doorbell.d64 = 0; +} + +void +mlx5e_resume_sq(struct mlx5e_sq *sq) +{ + int err; + + /* check if already enabled */ + if (sq->stopped == 0) + return; + + err = mlx5e_modify_sq(sq, MLX5_SQC_STATE_ERR, + MLX5_SQC_STATE_RST); + if (err != 0) { + if_printf(sq->ifp, + "mlx5e_modify_sq() from ERR to RST failed: %d\n", err); + } + + sq->cc = 0; + sq->pc = 0; + + /* reset doorbell prior to moving from RST to RDY */ + mlx5e_reset_sq_doorbell_record(sq); + + err = mlx5e_modify_sq(sq, MLX5_SQC_STATE_RST, + MLX5_SQC_STATE_RDY); + if (err != 0) { + if_printf(sq->ifp, + "mlx5e_modify_sq() from RST to RDY failed: %d\n", err); + } + + mtx_lock(&sq->lock); + sq->cev_next_state = MLX5E_CEV_STATE_INITIAL; + sq->stopped = 0; + mtx_unlock(&sq->lock); + +} + +static void +mlx5e_enable_tx_dma(struct mlx5e_channel *ch) +{ + int i; + + for (i = 0; i < ch->num_tc; i++) + mlx5e_resume_sq(&ch->sq[i]); +} + +static void +mlx5e_disable_rx_dma(struct mlx5e_channel *ch) +{ + struct mlx5e_rq *rq = &ch->rq; + int err; + + mtx_lock(&rq->mtx); + rq->enabled = 0; + callout_stop(&rq->watchdog); + mtx_unlock(&rq->mtx); + + callout_drain(&rq->watchdog); + + err = mlx5e_modify_rq(rq, MLX5_RQC_STATE_RDY, MLX5_RQC_STATE_ERR); + if (err != 0) { + if_printf(rq->ifp, + "mlx5e_modify_rq() from RDY to RST failed: %d\n", err); + } + + while (!mlx5_wq_ll_is_empty(&rq->wq)) { + msleep(1); + rq->cq.mcq.comp(&rq->cq.mcq); + } + + /* + * Transitioning into RST state will allow the FW to track less ERR state queues, + * thus reducing the recv queue flushing time + */ + err = mlx5e_modify_rq(rq, MLX5_RQC_STATE_ERR, MLX5_RQC_STATE_RST); + if (err != 0) { + if_printf(rq->ifp, + "mlx5e_modify_rq() from ERR to RST failed: %d\n", err); + } +} + +static void +mlx5e_enable_rx_dma(struct mlx5e_channel *ch) +{ + struct mlx5e_rq *rq = &ch->rq; + int err; + + rq->wq.wqe_ctr = 0; + mlx5_wq_ll_update_db_record(&rq->wq); + err = mlx5e_modify_rq(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY); + if (err != 0) { + if_printf(rq->ifp, + "mlx5e_modify_rq() from RST to RDY failed: %d\n", err); + } + + rq->enabled = 1; + + rq->cq.mcq.comp(&rq->cq.mcq); +} + +void +mlx5e_modify_tx_dma(struct mlx5e_priv *priv, uint8_t value) +{ + int i; + + if (priv->channel == NULL) + return; + + for (i = 0; i < priv->params.num_channels; i++) { + + if (!priv->channel[i]) + continue; + + if (value) + mlx5e_disable_tx_dma(priv->channel[i]); + else + mlx5e_enable_tx_dma(priv->channel[i]); + } +} + +void +mlx5e_modify_rx_dma(struct mlx5e_priv *priv, uint8_t value) +{ + int i; + + if (priv->channel == NULL) + return; + + for (i = 0; i < priv->params.num_channels; i++) { + + if (!priv->channel[i]) + continue; + + if (value) + mlx5e_disable_rx_dma(priv->channel[i]); + else + mlx5e_enable_rx_dma(priv->channel[i]); + } +} + +static void mlx5e_add_hw_stats(struct mlx5e_priv *priv) { SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(priv->sysctl_hw),