Netdev List
 help / color / mirror / Atom feed
* [net-next 0/9][pull request] 40GbE Intel Wired LAN Driver Updates 2018-03-14
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Jeff Kirsher, netdev, nhorman, sassmann, jogreene

This series contains updates to i40e and i40evf only.

Corentin Labbe cleans up the left over FCoE files in the i40e driver.

Gustavo A R Silva fixes a cut and paste error.

Paweł fixes a race condition when the VF driver is loaded on a host and
virsh is trying to attach it to the virtual machine and set a MAC
address.  Resolve the issue by adding polling in i40e_ndo_set_vf_mac()
when the VF is in reset mode.

Jake cleans up i40e_vlan_rx_register() since this only used in a single
location, so just inline the contents of the function.  Created a helper
function to proper update the per-filter statistics when we delete it.
Factored out the re-enabling ATR and SB rules.  Fixed an issue when
re-enabling ATR after the last TCPv4 filter is removed and ntuple is
still active, we were not restoring the TCPv4 filter input set.

Filip modifies the permission check function to ensure that it knows how
many filters are being requested, which allows the check to ensure that
the total number of filters in a single request does not cause us to go
over the limit.

Mariusz fixed an issue where the wrong calculation of partition id was
being done on OCP PHY mezzanine cards, which in turn caused wake on LAN
to be disabled on certain ports.

The following are changes since commit c292566a7779f88ed63d555b1015ab29ca0d5530:
  Merge branch 'sctp-add-support-for-some-sctp-auth-APIs-from-RFC6458'
and are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue 40GbE

Corentin Labbe (1):
  i40e: remove i40e_fcoe files

Filip Sadowski (1):
  i40e: Fix permission check for VF MAC filters

Gustavo A R Silva (1):
  i40evf/i40evf_main: Fix variable assignment in i40evf_parse_cls_flower

Jacob Keller (4):
  i40e: Cleanup i40e_vlan_rx_register
  i40e: track filter type statistics when deleting invalid filters
  i40e: factor out re-enable functions for ATR and SB
  i40e: restore TCPv4 input set when re-enabling ATR

Mariusz Stachura (1):
  i40e: fix for wrong partition id calculation on OCP mezz cards

Paweł Jabłoński (1):
  i40e: Fix attach VF to VM issue

 drivers/net/ethernet/intel/i40e/i40e_common.c      |   23 +-
 drivers/net/ethernet/intel/i40e/i40e_fcoe.c        | 1571 --------------------
 drivers/net/ethernet/intel/i40e/i40e_fcoe.h        |  127 --
 drivers/net/ethernet/intel/i40e/i40e_main.c        |  134 +-
 drivers/net/ethernet/intel/i40e/i40e_type.h        |    3 +
 drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |   90 +-
 drivers/net/ethernet/intel/i40evf/i40evf_main.c    |    2 +-
 7 files changed, 181 insertions(+), 1769 deletions(-)
 delete mode 100644 drivers/net/ethernet/intel/i40e/i40e_fcoe.c
 delete mode 100644 drivers/net/ethernet/intel/i40e/i40e_fcoe.h

-- 
2.14.3

^ permalink raw reply

* [net-next 2/9] i40evf/i40evf_main: Fix variable assignment in i40evf_parse_cls_flower
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Gustavo A R Silva, netdev, nhorman, sassmann, jogreene,
	Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Gustavo A R Silva <garsilva@embeddedor.com>

It seems this is a copy-paste error and that the proper variable to use
in this particular case is _src_ instead of _dst_.

Addresses-Coverity-ID: 1465282 ("Copy-paste error")
Fixes: 0075fa0fadd0 ("i40evf: Add support to apply cloud filters")
Signed-off-by: Gustavo A R Silva <garsilva@embeddedor.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index dae121877935..486cf491b000 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -2749,7 +2749,7 @@ static int i40evf_parse_cls_flower(struct i40evf_adapter *adapter,
 
 		if (key->src) {
 			vf->mask.tcp_spec.src_port |= cpu_to_be16(0xffff);
-			vf->data.tcp_spec.src_port = key->dst;
+			vf->data.tcp_spec.src_port = key->src;
 		}
 	}
 	vf->field_flags = field_flags;
-- 
2.14.3

^ permalink raw reply related

* [net-next 1/9] i40e: remove i40e_fcoe files
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Corentin Labbe, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Corentin Labbe <clabbe@baylibre.com>

i40e_fcoe support was removed via commit 9eed69a9147c ("i40e: Drop FCoE code from core driver files")
But this left files in place but un-compilable.
Let's finish the cleaning.

Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 1571 ---------------------------
 drivers/net/ethernet/intel/i40e/i40e_fcoe.h |  127 ---
 2 files changed, 1698 deletions(-)
 delete mode 100644 drivers/net/ethernet/intel/i40e/i40e_fcoe.c
 delete mode 100644 drivers/net/ethernet/intel/i40e/i40e_fcoe.h

diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
deleted file mode 100644
index 2d1253c5b7a1..000000000000
--- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
+++ /dev/null
@@ -1,1571 +0,0 @@
-/*******************************************************************************
- *
- * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 - 2016 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- ******************************************************************************/
-
-#include <linux/if_ether.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/fc/fc_fs.h>
-#include <scsi/fc/fc_fip.h>
-#include <scsi/fc/fc_fcoe.h>
-#include <scsi/libfc.h>
-#include <scsi/libfcoe.h>
-#include <uapi/linux/dcbnl.h>
-
-#include "i40e.h"
-#include "i40e_fcoe.h"
-
-/**
- * i40e_fcoe_sof_is_class2 - returns true if this is a FC Class 2 SOF
- * @sof: the FCoE start of frame delimiter
- **/
-static inline bool i40e_fcoe_sof_is_class2(u8 sof)
-{
-	return (sof == FC_SOF_I2) || (sof == FC_SOF_N2);
-}
-
-/**
- * i40e_fcoe_sof_is_class3 - returns true if this is a FC Class 3 SOF
- * @sof: the FCoE start of frame delimiter
- **/
-static inline bool i40e_fcoe_sof_is_class3(u8 sof)
-{
-	return (sof == FC_SOF_I3) || (sof == FC_SOF_N3);
-}
-
-/**
- * i40e_fcoe_sof_is_supported - returns true if the FC SOF is supported by HW
- * @sof: the input SOF value from the frame
- **/
-static inline bool i40e_fcoe_sof_is_supported(u8 sof)
-{
-	return i40e_fcoe_sof_is_class2(sof) ||
-	       i40e_fcoe_sof_is_class3(sof);
-}
-
-/**
- * i40e_fcoe_fc_sof - pull the SOF from FCoE header in the frame
- * @skb: the frame whose EOF is to be pulled from
- **/
-static inline int i40e_fcoe_fc_sof(struct sk_buff *skb, u8 *sof)
-{
-	*sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
-
-	if (!i40e_fcoe_sof_is_supported(*sof))
-		return -EINVAL;
-	return 0;
-}
-
-/**
- * i40e_fcoe_eof_is_supported - returns true if the EOF is supported by HW
- * @eof:     the input EOF value from the frame
- **/
-static inline bool i40e_fcoe_eof_is_supported(u8 eof)
-{
-	return (eof == FC_EOF_N) || (eof == FC_EOF_T) ||
-	       (eof == FC_EOF_NI) || (eof == FC_EOF_A);
-}
-
-/**
- * i40e_fcoe_fc_eof - pull EOF from FCoE trailer in the frame
- * @skb: the frame whose EOF is to be pulled from
- **/
-static inline int i40e_fcoe_fc_eof(struct sk_buff *skb, u8 *eof)
-{
-	/* the first byte of the last dword is EOF */
-	skb_copy_bits(skb, skb->len - 4, eof, 1);
-
-	if (!i40e_fcoe_eof_is_supported(*eof))
-		return -EINVAL;
-	return 0;
-}
-
-/**
- * i40e_fcoe_ctxt_eof - convert input FC EOF for descriptor programming
- * @eof: the input eof value from the frame
- *
- * The FC EOF is converted to the value understood by HW for descriptor
- * programming. Never call this w/o calling i40e_fcoe_eof_is_supported()
- * first and that already checks for all supported valid eof values.
- **/
-static inline u32 i40e_fcoe_ctxt_eof(u8 eof)
-{
-	switch (eof) {
-	case FC_EOF_N:
-		return I40E_TX_DESC_CMD_L4T_EOFT_EOF_N;
-	case FC_EOF_T:
-		return I40E_TX_DESC_CMD_L4T_EOFT_EOF_T;
-	case FC_EOF_NI:
-		return I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI;
-	case FC_EOF_A:
-		return I40E_TX_DESC_CMD_L4T_EOFT_EOF_A;
-	default:
-		/* Supported valid eof shall be already checked by
-		 * calling i40e_fcoe_eof_is_supported() first,
-		 * therefore this default case shall never hit.
-		 */
-		WARN_ON(1);
-		return -EINVAL;
-	}
-}
-
-/**
- * i40e_fcoe_xid_is_valid - returns true if the exchange id is valid
- * @xid: the exchange id
- **/
-static inline bool i40e_fcoe_xid_is_valid(u16 xid)
-{
-	return (xid != FC_XID_UNKNOWN) && (xid < I40E_FCOE_DDP_MAX);
-}
-
-/**
- * i40e_fcoe_ddp_unmap - unmap the mapped sglist associated
- * @pf: pointer to PF
- * @ddp: sw DDP context
- *
- * Unmap the scatter-gather list associated with the given SW DDP context
- *
- * Returns: data length already ddp-ed in bytes
- *
- **/
-static inline void i40e_fcoe_ddp_unmap(struct i40e_pf *pf,
-				       struct i40e_fcoe_ddp *ddp)
-{
-	if (test_and_set_bit(__I40E_FCOE_DDP_UNMAPPED, &ddp->flags))
-		return;
-
-	if (ddp->sgl) {
-		dma_unmap_sg(&pf->pdev->dev, ddp->sgl, ddp->sgc,
-			     DMA_FROM_DEVICE);
-		ddp->sgl = NULL;
-		ddp->sgc = 0;
-	}
-
-	if (ddp->pool) {
-		dma_pool_free(ddp->pool, ddp->udl, ddp->udp);
-		ddp->pool = NULL;
-	}
-}
-
-/**
- * i40e_fcoe_ddp_clear - clear the given SW DDP context
- * @ddp - SW DDP context
- **/
-static inline void i40e_fcoe_ddp_clear(struct i40e_fcoe_ddp *ddp)
-{
-	memset(ddp, 0, sizeof(struct i40e_fcoe_ddp));
-	ddp->xid = FC_XID_UNKNOWN;
-	ddp->flags = __I40E_FCOE_DDP_NONE;
-}
-
-/**
- * i40e_fcoe_progid_is_fcoe - check if the prog_id is for FCoE
- * @id: the prog id for the programming status Rx descriptor write-back
- **/
-static inline bool i40e_fcoe_progid_is_fcoe(u8 id)
-{
-	return (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) ||
-	       (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS);
-}
-
-/**
- * i40e_fcoe_fc_get_xid - get xid from the frame header
- * @fh: the fc frame header
- *
- * In case the incoming frame's exchange is originated from
- * the initiator, then received frame's exchange id is ANDed
- * with fc_cpu_mask bits to get the same cpu on which exchange
- * was originated, otherwise just use the current cpu.
- *
- * Returns ox_id if exchange originator, rx_id if responder
- **/
-static inline u16 i40e_fcoe_fc_get_xid(struct fc_frame_header *fh)
-{
-	u32 f_ctl = ntoh24(fh->fh_f_ctl);
-
-	return (f_ctl & FC_FC_EX_CTX) ?
-		be16_to_cpu(fh->fh_ox_id) :
-		be16_to_cpu(fh->fh_rx_id);
-}
-
-/**
- * i40e_fcoe_fc_frame_header - get fc frame header from skb
- * @skb: packet
- *
- * This checks if there is a VLAN header and returns the data
- * pointer to the start of the fc_frame_header.
- *
- * Returns pointer to the fc_frame_header
- **/
-static inline struct fc_frame_header *i40e_fcoe_fc_frame_header(
-	struct sk_buff *skb)
-{
-	void *fh = skb->data + sizeof(struct fcoe_hdr);
-
-	if (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q))
-		fh += sizeof(struct vlan_hdr);
-
-	return (struct fc_frame_header *)fh;
-}
-
-/**
- * i40e_fcoe_ddp_put - release the DDP context for a given exchange id
- * @netdev: the corresponding net_device
- * @xid: the exchange id that corresponding DDP context will be released
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_done
- * and it is expected to be called by ULD, i.e., FCP layer of libfc
- * to release the corresponding ddp context when the I/O is done.
- *
- * Returns : data length already ddp-ed in bytes
- **/
-static int i40e_fcoe_ddp_put(struct net_device *netdev, u16 xid)
-{
-	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_pf *pf = np->vsi->back;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-	int len = 0;
-	struct i40e_fcoe_ddp *ddp = &fcoe->ddp[xid];
-
-	if (!fcoe || !ddp)
-		goto out;
-
-	if (test_bit(__I40E_FCOE_DDP_DONE, &ddp->flags))
-		len = ddp->len;
-	i40e_fcoe_ddp_unmap(pf, ddp);
-out:
-	return len;
-}
-
-/**
- * i40e_fcoe_sw_init - sets up the HW for FCoE
- * @pf: pointer to PF
- **/
-void i40e_init_pf_fcoe(struct i40e_pf *pf)
-{
-	struct i40e_hw *hw = &pf->hw;
-	u32 val;
-
-	pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
-	pf->num_fcoe_qps = 0;
-	pf->fcoe_hmc_cntx_num = 0;
-	pf->fcoe_hmc_filt_num = 0;
-
-	if (!pf->hw.func_caps.fcoe) {
-		dev_dbg(&pf->pdev->dev, "FCoE capability is disabled\n");
-		return;
-	}
-
-	if (!pf->hw.func_caps.dcb) {
-		dev_warn(&pf->pdev->dev,
-			 "Hardware is not DCB capable not enabling FCoE.\n");
-		return;
-	}
-
-	/* enable FCoE hash filter */
-	val = i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1));
-	val |= BIT(I40E_FILTER_PCTYPE_FCOE_OX - 32);
-	val |= BIT(I40E_FILTER_PCTYPE_FCOE_RX - 32);
-	val &= I40E_PFQF_HENA_PTYPE_ENA_MASK;
-	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), val);
-
-	/* enable flag */
-	pf->flags |= I40E_FLAG_FCOE_ENABLED;
-	pf->num_fcoe_qps = I40E_DEFAULT_FCOE;
-
-	/* Reserve 4K DDP contexts and 20K filter size for FCoE */
-	pf->fcoe_hmc_cntx_num = BIT(I40E_DMA_CNTX_SIZE_4K) *
-				I40E_DMA_CNTX_BASE_SIZE;
-	pf->fcoe_hmc_filt_num = pf->fcoe_hmc_cntx_num +
-				BIT(I40E_HASH_FILTER_SIZE_16K) *
-				I40E_HASH_FILTER_BASE_SIZE;
-
-	/* FCoE object: max 16K filter buckets and 4K DMA contexts */
-	pf->filter_settings.fcoe_filt_num = I40E_HASH_FILTER_SIZE_16K;
-	pf->filter_settings.fcoe_cntx_num = I40E_DMA_CNTX_SIZE_4K;
-
-	/* Setup max frame with FCoE_MTU plus L2 overheads */
-	val = i40e_read_rx_ctl(hw, I40E_GLFCOE_RCTL);
-	val &= ~I40E_GLFCOE_RCTL_MAX_SIZE_MASK;
-	val |= ((FCOE_MTU + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
-		 << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT);
-	i40e_write_rx_ctl(hw, I40E_GLFCOE_RCTL, val);
-
-	dev_info(&pf->pdev->dev, "FCoE is supported.\n");
-}
-
-/**
- * i40e_get_fcoe_tc_map - Return TC map for FCoE APP
- * @pf: pointer to PF
- *
- **/
-u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf)
-{
-	struct i40e_dcb_app_priority_table app;
-	struct i40e_hw *hw = &pf->hw;
-	u8 enabled_tc = 0;
-	u8 tc, i;
-	/* Get the FCoE APP TLV */
-	struct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config;
-
-	for (i = 0; i < dcbcfg->numapps; i++) {
-		app = dcbcfg->app[i];
-		if (app.selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
-		    app.protocolid == ETH_P_FCOE) {
-			tc = dcbcfg->etscfg.prioritytable[app.priority];
-			enabled_tc |= BIT(tc);
-			break;
-		}
-	}
-
-	/* TC0 if there is no TC defined for FCoE APP TLV */
-	enabled_tc = enabled_tc ? enabled_tc : 0x1;
-
-	return enabled_tc;
-}
-
-/**
- * i40e_fcoe_vsi_init - prepares the VSI context for creating a FCoE VSI
- * @vsi: pointer to the associated VSI struct
- * @ctxt: pointer to the associated VSI context to be passed to HW
- *
- * Returns 0 on success or < 0 on error
- **/
-int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt)
-{
-	struct i40e_aqc_vsi_properties_data *info = &ctxt->info;
-	struct i40e_pf *pf = vsi->back;
-	struct i40e_hw *hw = &pf->hw;
-	u8 enabled_tc = 0;
-
-	if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
-		dev_err(&pf->pdev->dev,
-			"FCoE is not enabled for this device\n");
-		return -EPERM;
-	}
-
-	/* initialize the hardware for FCoE */
-	ctxt->pf_num = hw->pf_id;
-	ctxt->vf_num = 0;
-	ctxt->uplink_seid = vsi->uplink_seid;
-	ctxt->connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL;
-	ctxt->flags = I40E_AQ_VSI_TYPE_PF;
-
-	/* FCoE VSI would need the following sections */
-	info->valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
-
-	/* FCoE VSI does not need these sections */
-	info->valid_sections &= cpu_to_le16(~(I40E_AQ_VSI_PROP_SECURITY_VALID |
-					    I40E_AQ_VSI_PROP_VLAN_VALID |
-					    I40E_AQ_VSI_PROP_CAS_PV_VALID |
-					    I40E_AQ_VSI_PROP_INGRESS_UP_VALID |
-					    I40E_AQ_VSI_PROP_EGRESS_UP_VALID));
-
-	if (i40e_is_vsi_uplink_mode_veb(vsi)) {
-		info->valid_sections |=
-				cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
-		info->switch_id =
-				cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);
-	}
-	enabled_tc = i40e_get_fcoe_tc_map(pf);
-	i40e_vsi_setup_queue_map(vsi, ctxt, enabled_tc, true);
-
-	/* set up queue option section: only enable FCoE */
-	info->queueing_opt_flags = I40E_AQ_VSI_QUE_OPT_FCOE_ENA;
-
-	return 0;
-}
-
-/**
- * i40e_fcoe_enable - this is the implementation of ndo_fcoe_enable,
- * indicating the upper FCoE protocol stack is ready to use FCoE
- * offload features.
- *
- * @netdev: pointer to the netdev that FCoE is created on
- *
- * Returns 0 on success
- *
- * in RTNL
- *
- **/
-int i40e_fcoe_enable(struct net_device *netdev)
-{
-	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_vsi *vsi = np->vsi;
-	struct i40e_pf *pf = vsi->back;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-
-	if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
-		netdev_err(netdev, "HW does not support FCoE.\n");
-		return -ENODEV;
-	}
-
-	if (vsi->type != I40E_VSI_FCOE) {
-		netdev_err(netdev, "interface does not support FCoE.\n");
-		return -EBUSY;
-	}
-
-	atomic_inc(&fcoe->refcnt);
-
-	return 0;
-}
-
-/**
- * i40e_fcoe_disable- disables FCoE for upper FCoE protocol stack.
- * @dev: pointer to the netdev that FCoE is created on
- *
- * Returns 0 on success
- *
- **/
-int i40e_fcoe_disable(struct net_device *netdev)
-{
-	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_vsi *vsi = np->vsi;
-	struct i40e_pf *pf = vsi->back;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-
-	if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
-		netdev_err(netdev, "device does not support FCoE\n");
-		return -ENODEV;
-	}
-	if (vsi->type != I40E_VSI_FCOE)
-		return -EBUSY;
-
-	if (!atomic_dec_and_test(&fcoe->refcnt))
-		return -EINVAL;
-
-	netdev_info(netdev, "FCoE disabled\n");
-
-	return 0;
-}
-
-/**
- * i40e_fcoe_dma_pool_free - free the per cpu pool for FCoE DDP
- * @fcoe: the FCoE sw object
- * @dev: the device that the pool is associated with
- * @cpu: the cpu for this pool
- *
- **/
-static void i40e_fcoe_dma_pool_free(struct i40e_fcoe *fcoe,
-				    struct device *dev,
-				    unsigned int cpu)
-{
-	struct i40e_fcoe_ddp_pool *ddp_pool;
-
-	ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu);
-	if (!ddp_pool->pool) {
-		dev_warn(dev, "DDP pool already freed for cpu %d\n", cpu);
-		return;
-	}
-	dma_pool_destroy(ddp_pool->pool);
-	ddp_pool->pool = NULL;
-}
-
-/**
- * i40e_fcoe_dma_pool_create - per cpu pool for FCoE DDP
- * @fcoe: the FCoE sw object
- * @dev: the device that the pool is associated with
- * @cpu: the cpu for this pool
- *
- * Returns 0 on successful or non zero on failure
- *
- **/
-static int i40e_fcoe_dma_pool_create(struct i40e_fcoe *fcoe,
-				     struct device *dev,
-				     unsigned int cpu)
-{
-	struct i40e_fcoe_ddp_pool *ddp_pool;
-	struct dma_pool *pool;
-	char pool_name[32];
-
-	ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu);
-	if (ddp_pool && ddp_pool->pool) {
-		dev_warn(dev, "DDP pool already allocated for cpu %d\n", cpu);
-		return 0;
-	}
-	snprintf(pool_name, sizeof(pool_name), "i40e_fcoe_ddp_%d", cpu);
-	pool = dma_pool_create(pool_name, dev, I40E_FCOE_DDP_PTR_MAX,
-			       I40E_FCOE_DDP_PTR_ALIGN, PAGE_SIZE);
-	if (!pool) {
-		dev_err(dev, "dma_pool_create %s failed\n", pool_name);
-		return -ENOMEM;
-	}
-	ddp_pool->pool = pool;
-	return 0;
-}
-
-/**
- * i40e_fcoe_free_ddp_resources - release FCoE DDP resources
- * @vsi: the vsi FCoE is associated with
- *
- **/
-void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi)
-{
-	struct i40e_pf *pf = vsi->back;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-	int cpu, i;
-
-	/* do nothing if not FCoE VSI */
-	if (vsi->type != I40E_VSI_FCOE)
-		return;
-
-	/* do nothing if no DDP pools were allocated */
-	if (!fcoe->ddp_pool)
-		return;
-
-	for (i = 0; i < I40E_FCOE_DDP_MAX; i++)
-		i40e_fcoe_ddp_put(vsi->netdev, i);
-
-	for_each_possible_cpu(cpu)
-		i40e_fcoe_dma_pool_free(fcoe, &pf->pdev->dev, cpu);
-
-	free_percpu(fcoe->ddp_pool);
-	fcoe->ddp_pool = NULL;
-
-	netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources released\n",
-		    vsi->id, vsi->seid);
-}
-
-/**
- * i40e_fcoe_setup_ddp_resources - allocate per cpu DDP resources
- * @vsi: the VSI FCoE is associated with
- *
- * Returns 0 on successful or non zero on failure
- *
- **/
-int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi)
-{
-	struct i40e_pf *pf = vsi->back;
-	struct device *dev = &pf->pdev->dev;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-	unsigned int cpu;
-	int i;
-
-	if (vsi->type != I40E_VSI_FCOE)
-		return -ENODEV;
-
-	/* do nothing if no DDP pools were allocated */
-	if (fcoe->ddp_pool)
-		return -EEXIST;
-
-	/* allocate per CPU memory to track DDP pools */
-	fcoe->ddp_pool = alloc_percpu(struct i40e_fcoe_ddp_pool);
-	if (!fcoe->ddp_pool) {
-		dev_err(&pf->pdev->dev, "failed to allocate percpu DDP\n");
-		return -ENOMEM;
-	}
-
-	/* allocate pci pool for each cpu */
-	for_each_possible_cpu(cpu) {
-		if (!i40e_fcoe_dma_pool_create(fcoe, dev, cpu))
-			continue;
-
-		dev_err(dev, "failed to alloc DDP pool on cpu:%d\n", cpu);
-		i40e_fcoe_free_ddp_resources(vsi);
-		return -ENOMEM;
-	}
-
-	/* initialize the sw context */
-	for (i = 0; i < I40E_FCOE_DDP_MAX; i++)
-		i40e_fcoe_ddp_clear(&fcoe->ddp[i]);
-
-	netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources allocated\n",
-		    vsi->id, vsi->seid);
-
-	return 0;
-}
-
-/**
- * i40e_fcoe_handle_status - check the Programming Status for FCoE
- * @rx_ring: the Rx ring for this descriptor
- * @rx_desc: the Rx descriptor for Programming Status, not a packet descriptor.
- *
- * Check if this is the Rx Programming Status descriptor write-back for FCoE.
- * This is used to verify if the context/filter programming or invalidation
- * requested by SW to the HW is successful or not and take actions accordingly.
- **/
-void i40e_fcoe_handle_status(struct i40e_ring *rx_ring,
-			     union i40e_rx_desc *rx_desc, u8 prog_id)
-{
-	struct i40e_pf *pf = rx_ring->vsi->back;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-	struct i40e_fcoe_ddp *ddp;
-	u32 error;
-	u16 xid;
-	u64 qw;
-
-	/* we only care for FCoE here */
-	if (!i40e_fcoe_progid_is_fcoe(prog_id))
-		return;
-
-	xid = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param) &
-	      (I40E_FCOE_DDP_MAX - 1);
-
-	if (!i40e_fcoe_xid_is_valid(xid))
-		return;
-
-	ddp = &fcoe->ddp[xid];
-	WARN_ON(xid != ddp->xid);
-
-	qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-	error = (qw & I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK) >>
-		I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT;
-
-	/* DDP context programming status: failure or success */
-	if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) {
-		if (I40E_RX_PROG_FCOE_ERROR_TBL_FULL(error)) {
-			dev_err(&pf->pdev->dev, "xid %x ddp->xid %x TABLE FULL\n",
-				xid, ddp->xid);
-			ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT;
-		}
-		if (I40E_RX_PROG_FCOE_ERROR_CONFLICT(error)) {
-			dev_err(&pf->pdev->dev, "xid %x ddp->xid %x CONFLICT\n",
-				xid, ddp->xid);
-			ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT;
-		}
-	}
-
-	/* DDP context invalidation status: failure or success */
-	if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS) {
-		if (I40E_RX_PROG_FCOE_ERROR_INVLFAIL(error)) {
-			dev_err(&pf->pdev->dev, "xid %x ddp->xid %x INVALIDATION FAILURE\n",
-				xid, ddp->xid);
-			ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT;
-		}
-		/* clear the flag so we can retry invalidation */
-		clear_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags);
-	}
-
-	/* unmap DMA */
-	i40e_fcoe_ddp_unmap(pf, ddp);
-	i40e_fcoe_ddp_clear(ddp);
-}
-
-/**
- * i40e_fcoe_handle_offload - check ddp status and mark it done
- * @adapter: i40e adapter
- * @rx_desc: advanced rx descriptor
- * @skb: the skb holding the received data
- *
- * This checks ddp status.
- *
- * Returns : < 0 indicates an error or not a FCOE ddp, 0 indicates
- * not passing the skb to ULD, > 0 indicates is the length of data
- * being ddped.
- *
- **/
-int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
-			     union i40e_rx_desc *rx_desc,
-			     struct sk_buff *skb)
-{
-	struct i40e_pf *pf = rx_ring->vsi->back;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-	struct fc_frame_header *fh = NULL;
-	struct i40e_fcoe_ddp *ddp = NULL;
-	u32 status, fltstat;
-	u32 error, fcerr;
-	int rc = -EINVAL;
-	u16 ptype;
-	u16 xid;
-	u64 qw;
-
-	/* check this rxd is for programming status */
-	qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-	/* packet descriptor, check packet type */
-	ptype = (qw & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT;
-	if (!i40e_rx_is_fcoe(ptype))
-		goto out_no_ddp;
-
-	error = (qw & I40E_RXD_QW1_ERROR_MASK) >> I40E_RXD_QW1_ERROR_SHIFT;
-	fcerr = (error >> I40E_RX_DESC_ERROR_L3L4E_SHIFT) &
-		 I40E_RX_DESC_FCOE_ERROR_MASK;
-
-	/* check stateless offload error */
-	if (unlikely(fcerr == I40E_RX_DESC_ERROR_L3L4E_PROT)) {
-		dev_err(&pf->pdev->dev, "Protocol Error\n");
-		skb->ip_summed = CHECKSUM_NONE;
-	} else {
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	}
-
-	/* check hw status on ddp */
-	status = (qw & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT;
-	fltstat = (status >> I40E_RX_DESC_STATUS_FLTSTAT_SHIFT) &
-		   I40E_RX_DESC_FLTSTAT_FCMASK;
-
-	/* now we are ready to check DDP */
-	fh = i40e_fcoe_fc_frame_header(skb);
-	xid = i40e_fcoe_fc_get_xid(fh);
-	if (!i40e_fcoe_xid_is_valid(xid))
-		goto out_no_ddp;
-
-	/* non DDP normal receive, return to the protocol stack */
-	if (fltstat == I40E_RX_DESC_FLTSTAT_NOMTCH)
-		goto out_no_ddp;
-
-	/* do we have a sw ddp context setup ? */
-	ddp = &fcoe->ddp[xid];
-	if (!ddp->sgl)
-		goto out_no_ddp;
-
-	/* fetch xid from hw rxd wb, which should match up the sw ctxt */
-	xid = le16_to_cpu(rx_desc->wb.qword0.lo_dword.mirr_fcoe.fcoe_ctx_id);
-	if (ddp->xid != xid) {
-		dev_err(&pf->pdev->dev, "xid 0x%x does not match ctx_xid 0x%x\n",
-			ddp->xid, xid);
-		goto out_put_ddp;
-	}
-
-	/* the same exchange has already errored out */
-	if (ddp->fcerr) {
-		dev_err(&pf->pdev->dev, "xid 0x%x fcerr 0x%x reported fcer 0x%x\n",
-			xid, ddp->fcerr, fcerr);
-		goto out_put_ddp;
-	}
-
-	/* fcoe param is valid by now with correct DDPed length */
-	ddp->len = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param);
-	ddp->fcerr = fcerr;
-	/* header posting only, useful only for target mode and debugging */
-	if (fltstat == I40E_RX_DESC_FLTSTAT_DDP) {
-		/* For target mode, we get header of the last packet but it
-		 * does not have the FCoE trailer field, i.e., CRC and EOF
-		 * Ordered Set since they are offloaded by the HW, so fill
-		 * it up correspondingly to allow the packet to pass through
-		 * to the upper protocol stack.
-		 */
-		u32 f_ctl = ntoh24(fh->fh_f_ctl);
-
-		if ((f_ctl & FC_FC_END_SEQ) &&
-		    (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA)) {
-			struct fcoe_crc_eof *crc = NULL;
-
-			crc = skb_put(skb, sizeof(*crc));
-			crc->fcoe_eof = FC_EOF_T;
-		} else {
-			/* otherwise, drop the header only frame */
-			rc = 0;
-			goto out_no_ddp;
-		}
-	}
-
-out_put_ddp:
-	/* either we got RSP or we have an error, unmap DMA in both cases */
-	i40e_fcoe_ddp_unmap(pf, ddp);
-	if (ddp->len && !ddp->fcerr) {
-		int pkts;
-
-		rc = ddp->len;
-		i40e_fcoe_ddp_clear(ddp);
-		ddp->len = rc;
-		pkts = DIV_ROUND_UP(rc, 2048);
-		rx_ring->stats.bytes += rc;
-		rx_ring->stats.packets += pkts;
-		rx_ring->q_vector->rx.total_bytes += rc;
-		rx_ring->q_vector->rx.total_packets += pkts;
-		set_bit(__I40E_FCOE_DDP_DONE, &ddp->flags);
-	}
-
-out_no_ddp:
-	return rc;
-}
-
-/**
- * i40e_fcoe_ddp_setup - called to set up ddp context
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- * @target_mode: indicates this is a DDP request for target
- *
- * Returns : 1 for success and 0 for no DDP on this I/O
- **/
-static int i40e_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
-			       struct scatterlist *sgl, unsigned int sgc,
-			       int target_mode)
-{
-	static const unsigned int bufflen = I40E_FCOE_DDP_BUF_MIN;
-	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_fcoe_ddp_pool *ddp_pool;
-	struct i40e_pf *pf = np->vsi->back;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-	unsigned int i, j, dmacount;
-	struct i40e_fcoe_ddp *ddp;
-	unsigned int firstoff = 0;
-	unsigned int thisoff = 0;
-	unsigned int thislen = 0;
-	struct scatterlist *sg;
-	dma_addr_t addr = 0;
-	unsigned int len;
-
-	if (xid >= I40E_FCOE_DDP_MAX) {
-		dev_warn(&pf->pdev->dev, "xid=0x%x out-of-range\n", xid);
-		return 0;
-	}
-
-	/* no DDP if we are already down or resetting */
-	if (test_bit(__I40E_DOWN, &pf->state) ||
-	    test_bit(__I40E_NEEDS_RESTART, &pf->state)) {
-		dev_info(&pf->pdev->dev, "xid=0x%x device in reset/down\n",
-			 xid);
-		return 0;
-	}
-
-	ddp = &fcoe->ddp[xid];
-	if (ddp->sgl) {
-		dev_info(&pf->pdev->dev, "xid 0x%x w/ non-null sgl=%p nents=%d\n",
-			 xid, ddp->sgl, ddp->sgc);
-		return 0;
-	}
-	i40e_fcoe_ddp_clear(ddp);
-
-	if (!fcoe->ddp_pool) {
-		dev_info(&pf->pdev->dev, "No DDP pool, xid 0x%x\n", xid);
-		return 0;
-	}
-
-	ddp_pool = per_cpu_ptr(fcoe->ddp_pool, get_cpu());
-	if (!ddp_pool->pool) {
-		dev_info(&pf->pdev->dev, "No percpu ddp pool, xid 0x%x\n", xid);
-		goto out_noddp;
-	}
-
-	/* setup dma from scsi command sgl */
-	dmacount = dma_map_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE);
-	if (dmacount == 0) {
-		dev_info(&pf->pdev->dev, "dma_map_sg for sgl %p, sgc %d failed\n",
-			 sgl, sgc);
-		goto out_noddp_unmap;
-	}
-
-	/* alloc the udl from our ddp pool */
-	ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_ATOMIC, &ddp->udp);
-	if (!ddp->udl) {
-		dev_info(&pf->pdev->dev,
-			 "Failed allocated ddp context, xid 0x%x\n", xid);
-		goto out_noddp_unmap;
-	}
-
-	j = 0;
-	ddp->len = 0;
-	for_each_sg(sgl, sg, dmacount, i) {
-		addr = sg_dma_address(sg);
-		len = sg_dma_len(sg);
-		ddp->len += len;
-		while (len) {
-			/* max number of buffers allowed in one DDP context */
-			if (j >= I40E_FCOE_DDP_BUFFCNT_MAX) {
-				dev_info(&pf->pdev->dev,
-					 "xid=%x:%d,%d,%d:addr=%llx not enough descriptors\n",
-					 xid, i, j, dmacount, (u64)addr);
-				goto out_noddp_free;
-			}
-
-			/* get the offset of length of current buffer */
-			thisoff = addr & ((dma_addr_t)bufflen - 1);
-			thislen = min_t(unsigned int, (bufflen - thisoff), len);
-			/* all but the 1st buffer (j == 0)
-			 * must be aligned on bufflen
-			 */
-			if ((j != 0) && (thisoff))
-				goto out_noddp_free;
-
-			/* all but the last buffer
-			 * ((i == (dmacount - 1)) && (thislen == len))
-			 * must end at bufflen
-			 */
-			if (((i != (dmacount - 1)) || (thislen != len)) &&
-			    ((thislen + thisoff) != bufflen))
-				goto out_noddp_free;
-
-			ddp->udl[j] = (u64)(addr - thisoff);
-			/* only the first buffer may have none-zero offset */
-			if (j == 0)
-				firstoff = thisoff;
-			len -= thislen;
-			addr += thislen;
-			j++;
-		}
-	}
-	/* only the last buffer may have non-full bufflen */
-	ddp->lastsize = thisoff + thislen;
-	ddp->firstoff = firstoff;
-	ddp->list_len = j;
-	ddp->pool = ddp_pool->pool;
-	ddp->sgl = sgl;
-	ddp->sgc = sgc;
-	ddp->xid = xid;
-	if (target_mode)
-		set_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags);
-	set_bit(__I40E_FCOE_DDP_INITALIZED, &ddp->flags);
-
-	put_cpu();
-	return 1; /* Success */
-
-out_noddp_free:
-	dma_pool_free(ddp->pool, ddp->udl, ddp->udp);
-	i40e_fcoe_ddp_clear(ddp);
-
-out_noddp_unmap:
-	dma_unmap_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE);
-out_noddp:
-	put_cpu();
-	return 0;
-}
-
-/**
- * i40e_fcoe_ddp_get - called to set up ddp context in initiator mode
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup
- * and is expected to be called from ULD, e.g., FCP layer of libfc
- * to set up ddp for the corresponding xid of the given sglist for
- * the corresponding I/O.
- *
- * Returns : 1 for success and 0 for no ddp
- **/
-static int i40e_fcoe_ddp_get(struct net_device *netdev, u16 xid,
-			     struct scatterlist *sgl, unsigned int sgc)
-{
-	return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0);
-}
-
-/**
- * i40e_fcoe_ddp_target - called to set up ddp context in target mode
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_target
- * and is expected to be called from ULD, e.g., FCP layer of libfc
- * to set up ddp for the corresponding xid of the given sglist for
- * the corresponding I/O. The DDP in target mode is a write I/O request
- * from the initiator.
- *
- * Returns : 1 for success and 0 for no ddp
- **/
-static int i40e_fcoe_ddp_target(struct net_device *netdev, u16 xid,
-				struct scatterlist *sgl, unsigned int sgc)
-{
-	return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1);
-}
-
-/**
- * i40e_fcoe_program_ddp - programs the HW DDP related descriptors
- * @tx_ring: transmit ring for this packet
- * @skb:     the packet to be sent out
- * @sof: the SOF to indicate class of service
- *
- * Determine if it is READ/WRITE command, and finds out if there is
- * a matching SW DDP context for this command. DDP is applicable
- * only in case of READ if initiator or WRITE in case of
- * responder (via checking XFER_RDY).
- *
- * Note: caller checks sof and ddp sw context
- *
- * Returns : none
- *
- **/
-static void i40e_fcoe_program_ddp(struct i40e_ring *tx_ring,
-				  struct sk_buff *skb,
-				  struct i40e_fcoe_ddp *ddp, u8 sof)
-{
-	struct i40e_fcoe_filter_context_desc *filter_desc = NULL;
-	struct i40e_fcoe_queue_context_desc *queue_desc = NULL;
-	struct i40e_fcoe_ddp_context_desc *ddp_desc = NULL;
-	struct i40e_pf *pf = tx_ring->vsi->back;
-	u16 i = tx_ring->next_to_use;
-	struct fc_frame_header *fh;
-	u64 flags_rsvd_lanq = 0;
-	bool target_mode;
-
-	/* check if abort is still pending */
-	if (test_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags)) {
-		dev_warn(&pf->pdev->dev,
-			 "DDP abort is still pending xid:%hx and ddp->flags:%lx:\n",
-			 ddp->xid, ddp->flags);
-		return;
-	}
-
-	/* set the flag to indicate this is programmed */
-	if (test_and_set_bit(__I40E_FCOE_DDP_PROGRAMMED, &ddp->flags)) {
-		dev_warn(&pf->pdev->dev,
-			 "DDP is already programmed for xid:%hx and ddp->flags:%lx:\n",
-			 ddp->xid, ddp->flags);
-		return;
-	}
-
-	/* Prepare the DDP context descriptor */
-	ddp_desc = I40E_DDP_CONTEXT_DESC(tx_ring, i);
-	i++;
-	if (i == tx_ring->count)
-		i = 0;
-
-	ddp_desc->type_cmd_foff_lsize =
-				cpu_to_le64(I40E_TX_DESC_DTYPE_DDP_CTX	|
-				((u64)I40E_FCOE_DDP_CTX_DESC_BSIZE_4K  <<
-				I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT)	|
-				((u64)ddp->firstoff		       <<
-				I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT)	|
-				((u64)ddp->lastsize		       <<
-				I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT));
-	ddp_desc->rsvd = cpu_to_le64(0);
-
-	/* target mode needs last packet in the sequence  */
-	target_mode = test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags);
-	if (target_mode)
-		ddp_desc->type_cmd_foff_lsize |=
-			cpu_to_le64(I40E_FCOE_DDP_CTX_DESC_LASTSEQH);
-
-	/* Prepare queue_context descriptor */
-	queue_desc = I40E_QUEUE_CONTEXT_DESC(tx_ring, i++);
-	if (i == tx_ring->count)
-		i = 0;
-	queue_desc->dmaindx_fbase = cpu_to_le64(ddp->xid | ((u64)ddp->udp));
-	queue_desc->flen_tph = cpu_to_le64(ddp->list_len |
-				((u64)(I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC |
-				I40E_FCOE_QUEUE_CTX_DESC_TPHDATA) <<
-				I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT));
-
-	/* Prepare filter_context_desc */
-	filter_desc = I40E_FILTER_CONTEXT_DESC(tx_ring, i);
-	i++;
-	if (i == tx_ring->count)
-		i = 0;
-
-	fh = (struct fc_frame_header *)skb_transport_header(skb);
-	filter_desc->param = cpu_to_le32(ntohl(fh->fh_parm_offset));
-	filter_desc->seqn = cpu_to_le16(ntohs(fh->fh_seq_cnt));
-	filter_desc->rsvd_dmaindx = cpu_to_le16(ddp->xid <<
-				I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT);
-
-	flags_rsvd_lanq = I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP;
-	flags_rsvd_lanq |= (u64)(target_mode ?
-			I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP :
-			I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT);
-
-	flags_rsvd_lanq |= (u64)((sof == FC_SOF_I2 || sof == FC_SOF_N2) ?
-			I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2 :
-			I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3);
-
-	flags_rsvd_lanq |= ((u64)skb->queue_mapping <<
-				I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT);
-	filter_desc->flags_rsvd_lanq = cpu_to_le64(flags_rsvd_lanq);
-
-	/* By this time, all offload related descriptors has been programmed */
-	tx_ring->next_to_use = i;
-}
-
-/**
- * i40e_fcoe_invalidate_ddp - invalidates DDP in case of abort
- * @tx_ring: transmit ring for this packet
- * @skb: the packet associated w/ this DDP invalidation, i.e., ABTS
- * @ddp: the SW DDP context for this DDP
- *
- * Programs the Tx context descriptor to do DDP invalidation.
- **/
-static void i40e_fcoe_invalidate_ddp(struct i40e_ring *tx_ring,
-				     struct sk_buff *skb,
-				     struct i40e_fcoe_ddp *ddp)
-{
-	struct i40e_tx_context_desc *context_desc;
-	int i;
-
-	if (test_and_set_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags))
-		return;
-
-	i = tx_ring->next_to_use;
-	context_desc = I40E_TX_CTXTDESC(tx_ring, i);
-	i++;
-	if (i == tx_ring->count)
-		i = 0;
-
-	context_desc->tunneling_params = cpu_to_le32(0);
-	context_desc->l2tag2 = cpu_to_le16(0);
-	context_desc->rsvd = cpu_to_le16(0);
-	context_desc->type_cmd_tso_mss = cpu_to_le64(
-		I40E_TX_DESC_DTYPE_FCOE_CTX |
-		(I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL <<
-		I40E_TXD_CTX_QW1_CMD_SHIFT) |
-		(I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND <<
-		I40E_TXD_CTX_QW1_CMD_SHIFT));
-	tx_ring->next_to_use = i;
-}
-
-/**
- * i40e_fcoe_handle_ddp - check we should setup or invalidate DDP
- * @tx_ring: transmit ring for this packet
- * @skb: the packet to be sent out
- * @sof: the SOF to indicate class of service
- *
- * Determine if it is ABTS/READ/XFER_RDY, and finds out if there is
- * a matching SW DDP context for this command. DDP is applicable
- * only in case of READ if initiator or WRITE in case of
- * responder (via checking XFER_RDY). In case this is an ABTS, send
- * just invalidate the context.
- **/
-static void i40e_fcoe_handle_ddp(struct i40e_ring *tx_ring,
-				 struct sk_buff *skb, u8 sof)
-{
-	struct i40e_pf *pf = tx_ring->vsi->back;
-	struct i40e_fcoe *fcoe = &pf->fcoe;
-	struct fc_frame_header *fh;
-	struct i40e_fcoe_ddp *ddp;
-	u32 f_ctl;
-	u8 r_ctl;
-	u16 xid;
-
-	fh = (struct fc_frame_header *)skb_transport_header(skb);
-	f_ctl = ntoh24(fh->fh_f_ctl);
-	r_ctl = fh->fh_r_ctl;
-	ddp = NULL;
-
-	if ((r_ctl == FC_RCTL_DD_DATA_DESC) && (f_ctl & FC_FC_EX_CTX)) {
-		/* exchange responder? if so, XFER_RDY for write */
-		xid = ntohs(fh->fh_rx_id);
-		if (i40e_fcoe_xid_is_valid(xid)) {
-			ddp = &fcoe->ddp[xid];
-			if ((ddp->xid == xid) &&
-			    (test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
-				i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof);
-		}
-	} else if (r_ctl == FC_RCTL_DD_UNSOL_CMD) {
-		/* exchange originator, check READ cmd */
-		xid = ntohs(fh->fh_ox_id);
-		if (i40e_fcoe_xid_is_valid(xid)) {
-			ddp = &fcoe->ddp[xid];
-			if ((ddp->xid == xid) &&
-			    (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
-				i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof);
-		}
-	} else if (r_ctl == FC_RCTL_BA_ABTS) {
-		/* exchange originator, check ABTS */
-		xid = ntohs(fh->fh_ox_id);
-		if (i40e_fcoe_xid_is_valid(xid)) {
-			ddp = &fcoe->ddp[xid];
-			if ((ddp->xid == xid) &&
-			    (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
-				i40e_fcoe_invalidate_ddp(tx_ring, skb, ddp);
-		}
-	}
-}
-
-/**
- * i40e_fcoe_tso - set up FCoE TSO
- * @tx_ring:  ring to send buffer on
- * @skb:      send buffer
- * @tx_flags: collected send information
- * @hdr_len:  the tso header length
- * @sof: the SOF to indicate class of service
- *
- * Note must already have sof checked to be either class 2 or class 3 before
- * calling this function.
- *
- * Returns 1 to indicate sequence segmentation offload is properly setup
- * or returns 0 to indicate no tso is needed, otherwise returns error
- * code to drop the frame.
- **/
-static int i40e_fcoe_tso(struct i40e_ring *tx_ring,
-			 struct sk_buff *skb,
-			 u32 tx_flags, u8 *hdr_len, u8 sof)
-{
-	struct i40e_tx_context_desc *context_desc;
-	u32 cd_type, cd_cmd, cd_tso_len, cd_mss;
-	struct fc_frame_header *fh;
-	u64 cd_type_cmd_tso_mss;
-
-	/* must match gso type as FCoE */
-	if (!skb_is_gso(skb))
-		return 0;
-
-	/* is it the expected gso type for FCoE ?*/
-	if (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE) {
-		netdev_err(skb->dev,
-			   "wrong gso type %d:expecting SKB_GSO_FCOE\n",
-			   skb_shinfo(skb)->gso_type);
-		return -EINVAL;
-	}
-
-	/* header and trailer are inserted by hw */
-	*hdr_len = skb_transport_offset(skb) + sizeof(struct fc_frame_header) +
-		   sizeof(struct fcoe_crc_eof);
-
-	/* check sof to decide a class 2 or 3 TSO */
-	if (likely(i40e_fcoe_sof_is_class3(sof)))
-		cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3;
-	else
-		cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2;
-
-	/* param field valid? */
-	fh = (struct fc_frame_header *)skb_transport_header(skb);
-	if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
-		cd_cmd |= I40E_FCOE_TX_CTX_DESC_RELOFF;
-
-	/* fill the field values */
-	cd_type = I40E_TX_DESC_DTYPE_FCOE_CTX;
-	cd_tso_len = skb->len - *hdr_len;
-	cd_mss = skb_shinfo(skb)->gso_size;
-	cd_type_cmd_tso_mss =
-		((u64)cd_type  << I40E_TXD_CTX_QW1_DTYPE_SHIFT)     |
-		((u64)cd_cmd     << I40E_TXD_CTX_QW1_CMD_SHIFT)	    |
-		((u64)cd_tso_len << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
-		((u64)cd_mss     << I40E_TXD_CTX_QW1_MSS_SHIFT);
-
-	/* grab the next descriptor */
-	context_desc = I40E_TX_CTXTDESC(tx_ring, tx_ring->next_to_use);
-	tx_ring->next_to_use++;
-	if (tx_ring->next_to_use == tx_ring->count)
-		tx_ring->next_to_use = 0;
-
-	context_desc->tunneling_params = 0;
-	context_desc->l2tag2 = cpu_to_le16((tx_flags & I40E_TX_FLAGS_VLAN_MASK)
-					    >> I40E_TX_FLAGS_VLAN_SHIFT);
-	context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
-
-	return 1;
-}
-
-/**
- * i40e_fcoe_tx_map - build the tx descriptor
- * @tx_ring:  ring to send buffer on
- * @skb:      send buffer
- * @first:    first buffer info buffer to use
- * @tx_flags: collected send information
- * @hdr_len:  ptr to the size of the packet header
- * @eof:      the frame eof value
- *
- * Note, for FCoE, sof and eof are already checked
- **/
-static void i40e_fcoe_tx_map(struct i40e_ring *tx_ring,
-			     struct sk_buff *skb,
-			     struct i40e_tx_buffer *first,
-			     u32 tx_flags, u8 hdr_len, u8 eof)
-{
-	u32 td_offset = 0;
-	u32 td_cmd = 0;
-	u32 maclen;
-
-	/* insert CRC */
-	td_cmd = I40E_TX_DESC_CMD_ICRC;
-
-	/* setup MACLEN */
-	maclen = skb_network_offset(skb);
-	if (tx_flags & I40E_TX_FLAGS_SW_VLAN)
-		maclen += sizeof(struct vlan_hdr);
-
-	if (skb->protocol == htons(ETH_P_FCOE)) {
-		/* for FCoE, maclen should exclude ether type */
-		maclen -= 2;
-		/* setup type as FCoE and EOF insertion */
-		td_cmd |= (I40E_TX_DESC_CMD_FCOET | i40e_fcoe_ctxt_eof(eof));
-		/* setup FCoELEN and FCLEN */
-		td_offset |= ((((sizeof(struct fcoe_hdr) + 2) >> 2) <<
-				I40E_TX_DESC_LENGTH_IPLEN_SHIFT) |
-			      ((sizeof(struct fc_frame_header) >> 2) <<
-				I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT));
-		/* trim to exclude trailer */
-		pskb_trim(skb, skb->len - sizeof(struct fcoe_crc_eof));
-	}
-
-	/* MACLEN is ether header length in words not bytes */
-	td_offset |= (maclen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
-
-	i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len, td_cmd, td_offset);
-}
-
-/**
- * i40e_fcoe_set_skb_header - adjust skb header point for FIP/FCoE/FC
- * @skb: the skb to be adjusted
- *
- * Returns true if this skb is a FCoE/FIP or VLAN carried FCoE/FIP and then
- * adjusts the skb header pointers correspondingly. Otherwise, returns false.
- **/
-static inline int i40e_fcoe_set_skb_header(struct sk_buff *skb)
-{
-	__be16 protocol = skb->protocol;
-
-	skb_reset_mac_header(skb);
-	skb->mac_len = sizeof(struct ethhdr);
-	if (protocol == htons(ETH_P_8021Q)) {
-		struct vlan_ethhdr *veth = (struct vlan_ethhdr *)eth_hdr(skb);
-
-		protocol = veth->h_vlan_encapsulated_proto;
-		skb->mac_len += sizeof(struct vlan_hdr);
-	}
-
-	/* FCoE or FIP only */
-	if ((protocol != htons(ETH_P_FIP)) &&
-	    (protocol != htons(ETH_P_FCOE)))
-		return -EINVAL;
-
-	/* set header to L2 of FCoE/FIP */
-	skb_set_network_header(skb, skb->mac_len);
-	if (protocol == htons(ETH_P_FIP))
-		return 0;
-
-	/* set header to L3 of FC */
-	skb_set_transport_header(skb, skb->mac_len + sizeof(struct fcoe_hdr));
-	return 0;
-}
-
-/**
- * i40e_fcoe_xmit_frame - transmit buffer
- * @skb:     send buffer
- * @netdev:  the fcoe netdev
- *
- * Returns 0 if sent, else an error code
- **/
-static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb,
-					struct net_device *netdev)
-{
-	struct i40e_netdev_priv *np = netdev_priv(skb->dev);
-	struct i40e_vsi *vsi = np->vsi;
-	struct i40e_ring *tx_ring = vsi->tx_rings[skb->queue_mapping];
-	struct i40e_tx_buffer *first;
-	u32 tx_flags = 0;
-	int fso, count;
-	u8 hdr_len = 0;
-	u8 sof = 0;
-	u8 eof = 0;
-
-	if (i40e_fcoe_set_skb_header(skb))
-		goto out_drop;
-
-	count = i40e_xmit_descriptor_count(skb);
-	if (i40e_chk_linearize(skb, count)) {
-		if (__skb_linearize(skb))
-			goto out_drop;
-		count = i40e_txd_use_count(skb->len);
-		tx_ring->tx_stats.tx_linearize++;
-	}
-
-	/* need: 1 descriptor per page * PAGE_SIZE/I40E_MAX_DATA_PER_TXD,
-	 *       + 1 desc for skb_head_len/I40E_MAX_DATA_PER_TXD,
-	 *       + 4 desc gap to avoid the cache line where head is,
-	 *       + 1 desc for context descriptor,
-	 * otherwise try next time
-	 */
-	if (i40e_maybe_stop_tx(tx_ring, count + 4 + 1)) {
-		tx_ring->tx_stats.tx_busy++;
-		return NETDEV_TX_BUSY;
-	}
-
-	/* prepare the xmit flags */
-	if (i40e_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags))
-		goto out_drop;
-
-	/* record the location of the first descriptor for this packet */
-	first = &tx_ring->tx_bi[tx_ring->next_to_use];
-
-	/* FIP is a regular L2 traffic w/o offload */
-	if (skb->protocol == htons(ETH_P_FIP))
-		goto out_send;
-
-	/* check sof and eof, only supports FC Class 2 or 3 */
-	if (i40e_fcoe_fc_sof(skb, &sof) || i40e_fcoe_fc_eof(skb, &eof)) {
-		netdev_err(netdev, "SOF/EOF error:%02x - %02x\n", sof, eof);
-		goto out_drop;
-	}
-
-	/* always do FCCRC for FCoE */
-	tx_flags |= I40E_TX_FLAGS_FCCRC;
-
-	/* check we should do sequence offload */
-	fso = i40e_fcoe_tso(tx_ring, skb, tx_flags, &hdr_len, sof);
-	if (fso < 0)
-		goto out_drop;
-	else if (fso)
-		tx_flags |= I40E_TX_FLAGS_FSO;
-	else
-		i40e_fcoe_handle_ddp(tx_ring, skb, sof);
-
-out_send:
-	/* send out the packet */
-	i40e_fcoe_tx_map(tx_ring, skb, first, tx_flags, hdr_len, eof);
-
-	i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
-	return NETDEV_TX_OK;
-
-out_drop:
-	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
-}
-
-/**
- * i40e_fcoe_change_mtu - NDO callback to change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns error as operation not permitted
- *
- **/
-static int i40e_fcoe_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	netdev_warn(netdev, "MTU change is not supported on FCoE interfaces\n");
-	return -EPERM;
-}
-
-/**
- * i40e_fcoe_set_features - set the netdev feature flags
- * @netdev: ptr to the netdev being adjusted
- * @features: the feature set that the stack is suggesting
- *
- **/
-static int i40e_fcoe_set_features(struct net_device *netdev,
-				  netdev_features_t features)
-{
-	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_vsi *vsi = np->vsi;
-
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		i40e_vlan_stripping_enable(vsi);
-	else
-		i40e_vlan_stripping_disable(vsi);
-
-	return 0;
-}
-
-static const struct net_device_ops i40e_fcoe_netdev_ops = {
-	.ndo_open		= i40e_open,
-	.ndo_stop		= i40e_close,
-	.ndo_get_stats64	= i40e_get_netdev_stats_struct,
-	.ndo_set_rx_mode	= i40e_set_rx_mode,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= i40e_set_mac,
-	.ndo_change_mtu		= i40e_fcoe_change_mtu,
-	.ndo_do_ioctl		= i40e_ioctl,
-	.ndo_tx_timeout		= i40e_tx_timeout,
-	.ndo_vlan_rx_add_vid	= i40e_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid	= i40e_vlan_rx_kill_vid,
-	.ndo_setup_tc		= __i40e_setup_tc,
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= i40e_netpoll,
-#endif
-	.ndo_start_xmit		= i40e_fcoe_xmit_frame,
-	.ndo_fcoe_enable	= i40e_fcoe_enable,
-	.ndo_fcoe_disable	= i40e_fcoe_disable,
-	.ndo_fcoe_ddp_setup	= i40e_fcoe_ddp_get,
-	.ndo_fcoe_ddp_done	= i40e_fcoe_ddp_put,
-	.ndo_fcoe_ddp_target	= i40e_fcoe_ddp_target,
-	.ndo_set_features	= i40e_fcoe_set_features,
-};
-
-/* fcoe network device type */
-static struct device_type fcoe_netdev_type = {
-	.name = "fcoe",
-};
-
-/**
- * i40e_fcoe_config_netdev - prepares the VSI context for creating a FCoE VSI
- * @vsi: pointer to the associated VSI struct
- * @ctxt: pointer to the associated VSI context to be passed to HW
- *
- * Returns 0 on success or < 0 on error
- **/
-void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi)
-{
-	struct i40e_hw *hw = &vsi->back->hw;
-	struct i40e_pf *pf = vsi->back;
-
-	if (vsi->type != I40E_VSI_FCOE)
-		return;
-
-	netdev->features = (NETIF_F_HW_VLAN_CTAG_TX |
-			    NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_FILTER);
-
-	netdev->vlan_features = netdev->features;
-	netdev->vlan_features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
-				   NETIF_F_HW_VLAN_CTAG_RX |
-				   NETIF_F_HW_VLAN_CTAG_FILTER);
-	netdev->fcoe_ddp_xid = I40E_FCOE_DDP_MAX - 1;
-	netdev->features |= NETIF_F_ALL_FCOE;
-	netdev->vlan_features |= NETIF_F_ALL_FCOE;
-	netdev->hw_features |= netdev->features;
-	netdev->priv_flags |= IFF_UNICAST_FLT;
-	netdev->priv_flags |= IFF_SUPP_NOFCS;
-
-	strlcpy(netdev->name, "fcoe%d", IFNAMSIZ-1);
-	netdev->mtu = FCOE_MTU;
-	SET_NETDEV_DEV(netdev, &pf->pdev->dev);
-	SET_NETDEV_DEVTYPE(netdev, &fcoe_netdev_type);
-	/* set different dev_port value 1 for FCoE netdev than the default
-	 * zero dev_port value for PF netdev, this helps biosdevname user
-	 * tool to differentiate them correctly while both attached to the
-	 * same PCI function.
-	 */
-	netdev->dev_port = 1;
-	spin_lock_bh(&vsi->mac_filter_hash_lock);
-	i40e_add_filter(vsi, hw->mac.san_addr, 0);
-	i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0);
-	i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0);
-	i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0);
-	spin_unlock_bh(&vsi->mac_filter_hash_lock);
-
-	/* use san mac */
-	ether_addr_copy(netdev->dev_addr, hw->mac.san_addr);
-	ether_addr_copy(netdev->perm_addr, hw->mac.san_addr);
-	/* fcoe netdev ops */
-	netdev->netdev_ops = &i40e_fcoe_netdev_ops;
-}
-
-/**
- * i40e_fcoe_vsi_setup - allocate and set up FCoE VSI
- * @pf: the PF that VSI is associated with
- *
- **/
-void i40e_fcoe_vsi_setup(struct i40e_pf *pf)
-{
-	struct i40e_vsi *vsi;
-	u16 seid;
-	int i;
-
-	if (!(pf->flags & I40E_FLAG_FCOE_ENABLED))
-		return;
-
-	for (i = 0; i < pf->num_alloc_vsi; i++) {
-		vsi = pf->vsi[i];
-		if (vsi && vsi->type == I40E_VSI_FCOE) {
-			dev_warn(&pf->pdev->dev,
-				 "FCoE VSI already created\n");
-			return;
-		}
-	}
-
-	seid = pf->vsi[pf->lan_vsi]->seid;
-	vsi = i40e_vsi_setup(pf, I40E_VSI_FCOE, seid, 0);
-	if (vsi) {
-		dev_dbg(&pf->pdev->dev,
-			"Successfully created FCoE VSI seid %d id %d uplink_seid %d PF seid %d\n",
-			vsi->seid, vsi->id, vsi->uplink_seid, seid);
-	} else {
-		dev_info(&pf->pdev->dev, "Failed to create FCoE VSI\n");
-	}
-}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.h b/drivers/net/ethernet/intel/i40e/i40e_fcoe.h
deleted file mode 100644
index a93174ddeaba..000000000000
--- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*******************************************************************************
- *
- * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 - 2014 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- ******************************************************************************/
-
-#ifndef _I40E_FCOE_H_
-#define _I40E_FCOE_H_
-
-/* FCoE HW context helper macros */
-#define I40E_DDP_CONTEXT_DESC(R, i)     \
-	(&(((struct i40e_fcoe_ddp_context_desc *)((R)->desc))[i]))
-
-#define I40E_QUEUE_CONTEXT_DESC(R, i)   \
-	(&(((struct i40e_fcoe_queue_context_desc *)((R)->desc))[i]))
-
-#define I40E_FILTER_CONTEXT_DESC(R, i)  \
-	(&(((struct i40e_fcoe_filter_context_desc *)((R)->desc))[i]))
-
-/* receive queue descriptor filter status for FCoE */
-#define I40E_RX_DESC_FLTSTAT_FCMASK	0x3
-#define I40E_RX_DESC_FLTSTAT_NOMTCH	0x0	/* no ddp context match */
-#define I40E_RX_DESC_FLTSTAT_NODDP	0x1	/* no ddp due to error */
-#define I40E_RX_DESC_FLTSTAT_DDP	0x2	/* DDPed payload, post header */
-#define I40E_RX_DESC_FLTSTAT_FCPRSP	0x3	/* FCP_RSP */
-
-/* receive queue descriptor error codes for FCoE */
-#define I40E_RX_DESC_FCOE_ERROR_MASK		\
-	(I40E_RX_DESC_ERROR_L3L4E_PROT |	\
-	 I40E_RX_DESC_ERROR_L3L4E_FC |		\
-	 I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR |	\
-	 I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN)
-
-/* receive queue descriptor programming error */
-#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL(e)	\
-	(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT) & 0x1)
-
-#define I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)	\
-	(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT) & 0x1)
-
-#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT	\
-	BIT(I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT)
-#define I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT	\
-	BIT(I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT)
-
-#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL(e)	\
-	I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)
-#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT	\
-	I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT
-
-/* FCoE DDP related definitions */
-#define I40E_FCOE_MIN_XID	0x0000  /* the min xid supported by fcoe_sw */
-#define I40E_FCOE_MAX_XID	0x0FFF  /* the max xid supported by fcoe_sw */
-#define I40E_FCOE_DDP_BUFFCNT_MAX	512	/* 9 bits bufcnt */
-#define I40E_FCOE_DDP_PTR_ALIGN		16
-#define I40E_FCOE_DDP_PTR_MAX	(I40E_FCOE_DDP_BUFFCNT_MAX * sizeof(dma_addr_t))
-#define I40E_FCOE_DDP_BUF_MIN	4096
-#define I40E_FCOE_DDP_MAX	2048
-#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT	8
-
-/* supported netdev features for FCoE */
-#define I40E_FCOE_NETIF_FEATURES (NETIF_F_ALL_FCOE | \
-	NETIF_F_HW_VLAN_CTAG_TX | \
-	NETIF_F_HW_VLAN_CTAG_RX | \
-	NETIF_F_HW_VLAN_CTAG_FILTER)
-
-/* DDP context flags */
-enum i40e_fcoe_ddp_flags {
-	__I40E_FCOE_DDP_NONE = 1,
-	__I40E_FCOE_DDP_TARGET,
-	__I40E_FCOE_DDP_INITALIZED,
-	__I40E_FCOE_DDP_PROGRAMMED,
-	__I40E_FCOE_DDP_DONE,
-	__I40E_FCOE_DDP_ABORTED,
-	__I40E_FCOE_DDP_UNMAPPED,
-};
-
-/* DDP SW context struct */
-struct i40e_fcoe_ddp {
-	int len;
-	u16 xid;
-	u16 firstoff;
-	u16 lastsize;
-	u16 list_len;
-	u8 fcerr;
-	u8 prerr;
-	unsigned long flags;
-	unsigned int sgc;
-	struct scatterlist *sgl;
-	dma_addr_t udp;
-	u64 *udl;
-	struct dma_pool *pool;
-
-};
-
-struct i40e_fcoe_ddp_pool {
-	struct dma_pool *pool;
-};
-
-struct i40e_fcoe {
-	unsigned long mode;
-	atomic_t refcnt;
-	struct i40e_fcoe_ddp_pool __percpu *ddp_pool;
-	struct i40e_fcoe_ddp ddp[I40E_FCOE_DDP_MAX];
-};
-
-#endif /* _I40E_FCOE_H_ */
-- 
2.14.3

^ permalink raw reply related

* [net-next 6/9] i40e: track filter type statistics when deleting invalid filters
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Jacob Keller <jacob.e.keller@intel.com>

When hardware has trouble with a particular filter, we delete it from
the list. Unfortunately, we did not properly update the per-filter
statistic when doing so.

Create a helper function to handle this, and properly reduce the
necessary counter so that it tracks the number of active filters
properly.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 56 ++++++++++++++++++++++++-----
 1 file changed, 48 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 146969891579..848c8f1acbbf 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -8135,6 +8135,51 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf)
 	return fcnt_prog;
 }
 
+/**
+ * i40e_delete_invalid_filter - Delete an invalid FDIR filter
+ * @pf: board private structure
+ * @filter: FDir filter to remove
+ */
+static void i40e_delete_invalid_filter(struct i40e_pf *pf,
+				       struct i40e_fdir_filter *filter)
+{
+	/* Update counters */
+	pf->fdir_pf_active_filters--;
+	pf->fd_inv = 0;
+
+	switch (filter->flow_type) {
+	case TCP_V4_FLOW:
+		pf->fd_tcp4_filter_cnt--;
+		break;
+	case UDP_V4_FLOW:
+		pf->fd_udp4_filter_cnt--;
+		break;
+	case SCTP_V4_FLOW:
+		pf->fd_sctp4_filter_cnt--;
+		break;
+	case IP_USER_FLOW:
+		switch (filter->ip4_proto) {
+		case IPPROTO_TCP:
+			pf->fd_tcp4_filter_cnt--;
+			break;
+		case IPPROTO_UDP:
+			pf->fd_udp4_filter_cnt--;
+			break;
+		case IPPROTO_SCTP:
+			pf->fd_sctp4_filter_cnt--;
+			break;
+		case IPPROTO_IP:
+			pf->fd_ip4_filter_cnt--;
+			break;
+		}
+		break;
+	}
+
+	/* Remove the filter from the list and free memory */
+	hlist_del(&filter->fdir_node);
+	kfree(filter);
+}
+
 /**
  * i40e_fdir_check_and_reenable - Function to reenabe FD ATR or SB if disabled
  * @pf: board private structure
@@ -8179,14 +8224,9 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
 	/* if hw had a problem adding a filter, delete it */
 	if (pf->fd_inv > 0) {
 		hlist_for_each_entry_safe(filter, node,
-					  &pf->fdir_filter_list, fdir_node) {
-			if (filter->fd_id == pf->fd_inv) {
-				hlist_del(&filter->fdir_node);
-				kfree(filter);
-				pf->fdir_pf_active_filters--;
-				pf->fd_inv = 0;
-			}
-		}
+					  &pf->fdir_filter_list, fdir_node)
+			if (filter->fd_id == pf->fd_inv)
+				i40e_delete_invalid_filter(pf, filter);
 	}
 }
 
-- 
2.14.3

^ permalink raw reply related

* [net-next 5/9] i40e: Fix permission check for VF MAC filters
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Filip Sadowski, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Filip Sadowski <filip.sadowski@intel.com>

When VF requests adding of MAC filters the checking is done against number
of already present MAC filters not adding them at the same time. It makes
it possible to add a bunch of filters at once possibly exceeding
acceptable limit of I40E_VC_MAX_MAC_ADDR_PER_VF filters.

This happens because when checking vf->num_mac, we do not check how many
filters are being requested at once. Modify the check function to ensure
that it knows how many filters are being requested. This allows the
check to ensure that the total number of filters in a single request
does not cause us to go over the limit.

Additionally, move the check to within the lock to ensure that the
vf->num_mac is checked while holding the lock to maintain consistency.
We could have simply moved the call to i40e_vf_check_permission to
within the loop, but this could cause a request to be non-atomic, and
add some but not all the addresses, while reporting an error code. We
want to avoid this behavior so that users are not confused about which
filters have or have not been added.

Signed-off-by: Filip Sadowski <filip.sadowski@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 79 ++++++++++++++--------
 1 file changed, 51 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 520d86357c69..321ab4badb68 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -2368,25 +2368,47 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 /**
  * i40e_check_vf_permission
  * @vf: pointer to the VF info
- * @macaddr: pointer to the MAC Address being checked
+ * @al: MAC address list from virtchnl
  *
- * Check if the VF has permission to add or delete unicast MAC address
- * filters and return error code -EPERM if not.  Then check if the
- * address filter requested is broadcast or zero and if so return
- * an invalid MAC address error code.
+ * Check that the given list of MAC addresses is allowed. Will return -EPERM
+ * if any address in the list is not valid. Checks the following conditions:
+ *
+ * 1) broadcast and zero addresses are never valid
+ * 2) unicast addresses are not allowed if the VMM has administratively set
+ *    the VF MAC address, unless the VF is marked as privileged.
+ * 3) There is enough space to add all the addresses.
+ *
+ * Note that to guarantee consistency, it is expected this function be called
+ * while holding the mac_filter_hash_lock, as otherwise the current number of
+ * addresses might not be accurate.
  **/
-static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
+static inline int i40e_check_vf_permission(struct i40e_vf *vf,
+					   struct virtchnl_ether_addr_list *al)
 {
 	struct i40e_pf *pf = vf->pf;
-	int ret = 0;
+	int i;
+
+	/* If this VF is not privileged, then we can't add more than a limited
+	 * number of addresses. Check to make sure that the additions do not
+	 * push us over the limit.
+	 */
+	if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
+	    (vf->num_mac + al->num_elements) > I40E_VC_MAX_MAC_ADDR_PER_VF) {
+		dev_err(&pf->pdev->dev,
+			"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
+		return -EPERM;
+	}
+
+	for (i = 0; i < al->num_elements; i++) {
+		u8 *addr = al->list[i].addr;
+
+		if (is_broadcast_ether_addr(addr) ||
+		    is_zero_ether_addr(addr)) {
+			dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n",
+				addr);
+			return I40E_ERR_INVALID_MAC_ADDR;
+		}
 
-	if (is_broadcast_ether_addr(macaddr) ||
-		   is_zero_ether_addr(macaddr)) {
-		dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n", macaddr);
-		ret = I40E_ERR_INVALID_MAC_ADDR;
-	} else if (vf->pf_set_mac && !is_multicast_ether_addr(macaddr) &&
-		   !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
-		   !ether_addr_equal(macaddr, vf->default_lan_addr.addr)) {
 		/* If the host VMM administrator has set the VF MAC address
 		 * administratively via the ndo_set_vf_mac command then deny
 		 * permission to the VF to add or delete unicast MAC addresses.
@@ -2394,16 +2416,16 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
 		 * The VF may request to set the MAC address filter already
 		 * assigned to it so do not return an error in that case.
 		 */
-		dev_err(&pf->pdev->dev,
-			"VF attempting to override administratively set MAC address, reload the VF driver to resume normal operation\n");
-		ret = -EPERM;
-	} else if ((vf->num_mac >= I40E_VC_MAX_MAC_ADDR_PER_VF) &&
-		   !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
-		dev_err(&pf->pdev->dev,
-			"VF is not trusted, switch the VF to trusted to add more functionality\n");
-		ret = -EPERM;
+		if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
+		    !is_multicast_ether_addr(addr) && vf->pf_set_mac &&
+		    !ether_addr_equal(addr, vf->default_lan_addr.addr)) {
+			dev_err(&pf->pdev->dev,
+				"VF attempting to override administratively set MAC address, reload the VF driver to resume normal operation\n");
+			return -EPERM;
+		}
 	}
-	return ret;
+
+	return 0;
 }
 
 /**
@@ -2430,11 +2452,6 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 		goto error_param;
 	}
 
-	for (i = 0; i < al->num_elements; i++) {
-		ret = i40e_check_vf_permission(vf, al->list[i].addr);
-		if (ret)
-			goto error_param;
-	}
 	vsi = pf->vsi[vf->lan_vsi_idx];
 
 	/* Lock once, because all function inside for loop accesses VSI's
@@ -2442,6 +2459,12 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 	 */
 	spin_lock_bh(&vsi->mac_filter_hash_lock);
 
+	ret = i40e_check_vf_permission(vf, al);
+	if (ret) {
+		spin_unlock_bh(&vsi->mac_filter_hash_lock);
+		goto error_param;
+	}
+
 	/* add new addresses to the list */
 	for (i = 0; i < al->num_elements; i++) {
 		struct i40e_mac_filter *f;
-- 
2.14.3

^ permalink raw reply related

* [net-next 3/9] i40e: Fix attach VF to VM issue
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem
  Cc: Paweł Jabłoński, netdev, nhorman, sassmann,
	jogreene, Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Paweł Jabłoński <pawel.jablonski@intel.com>

Fix for "Resource temporarily unavailable" problem when virsh is
trying to attach a device to VM. When the VF driver is loaded on
host and virsh is trying to attach it to the VM and set a MAC
address, it ends with a race condition between i40e_reset_vf and
i40e_ndo_set_vf_mac functions. The bug is fixed by adding polling
in i40e_ndo_set_vf_mac function For when the VF is in Reset mode.

Signed-off-by: Paweł Jabłoński <pawel.jablonski@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index e23975c67417..520d86357c69 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -3741,6 +3741,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
 	int ret = 0;
 	struct hlist_node *h;
 	int bkt;
+	u8 i;
 
 	/* validate the request */
 	if (vf_id >= pf->num_alloc_vfs) {
@@ -3752,6 +3753,16 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
 
 	vf = &(pf->vf[vf_id]);
 	vsi = pf->vsi[vf->lan_vsi_idx];
+
+	/* When the VF is resetting wait until it is done.
+	 * It can take up to 200 milliseconds,
+	 * but wait for up to 300 milliseconds to be safe.
+	 */
+	for (i = 0; i < 15; i++) {
+		if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states))
+			break;
+		msleep(20);
+	}
 	if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
 		dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n",
 			vf_id);
-- 
2.14.3

^ permalink raw reply related

* [net-next 4/9] i40e: Cleanup i40e_vlan_rx_register
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Jacob Keller <jacob.e.keller@intel.com>

We used to use the function i40e_vlan_rx_register as a way to hook
into the now defunct .ndo_vlan_rx_register netdev hook. This was
removed but we kept the function around because we still used it
internally to control enabling or disabling of VLAN stripping.

As pointed out in upstream review, VLAN stripping is only used in a
single location and the previous function is quite small, just inline
it into i40e_restore_vlan() rather than carrying the function
separately.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 21 ++++-----------------
 1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index be9a1467a1a1..146969891579 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -2718,22 +2718,6 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi)
 	}
 }
 
-/**
- * i40e_vlan_rx_register - Setup or shutdown vlan offload
- * @netdev: network interface to be adjusted
- * @features: netdev features to test if VLAN offload is enabled or not
- **/
-static void i40e_vlan_rx_register(struct net_device *netdev, u32 features)
-{
-	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_vsi *vsi = np->vsi;
-
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		i40e_vlan_stripping_enable(vsi);
-	else
-		i40e_vlan_stripping_disable(vsi);
-}
-
 /**
  * i40e_add_vlan_all_mac - Add a MAC/VLAN filter for each existing MAC address
  * @vsi: the vsi being configured
@@ -2909,7 +2893,10 @@ static void i40e_restore_vlan(struct i40e_vsi *vsi)
 	if (!vsi->netdev)
 		return;
 
-	i40e_vlan_rx_register(vsi->netdev, vsi->netdev->features);
+	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+		i40e_vlan_stripping_enable(vsi);
+	else
+		i40e_vlan_stripping_disable(vsi);
 
 	for_each_set_bit(vid, vsi->active_vlans, VLAN_N_VID)
 		i40e_vlan_rx_add_vid(vsi->netdev, htons(ETH_P_8021Q),
-- 
2.14.3

^ permalink raw reply related

* [net-next 9/9] i40e: restore TCPv4 input set when re-enabling ATR
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Jacob Keller <jacob.e.keller@intel.com>

When we re-enable ATR we need to restore the input set for TCPv4
filters, in order for ATR to function correctly. We already do this for
the normal case of re-enabling ATR when disabling ntuple support.
However, when re-enabling ATR after the last TCPv4 filter is removed (but
when ntuple support is still active), we did not restore the TCPv4
filter input set.

This can cause problems if the TCPv4 filters from FDir had changed the
input set, as ATR will no longer behave as expected.

When clearing the ATR auto-disable flag, make sure we restore the TCPv4
input set to avoid this.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index beb854208047..b78c06a1f82c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -8156,6 +8156,15 @@ static void i40e_reenable_fdir_sb(struct i40e_pf *pf)
 static void i40e_reenable_fdir_atr(struct i40e_pf *pf)
 {
 	if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
+		/* ATR uses the same filtering logic as SB rules. It only
+		 * functions properly if the input set mask is at the default
+		 * settings. It is safe to restore the default input set
+		 * because there are no active TCPv4 filter rules.
+		 */
+		i40e_write_fd_input_set(pf, I40E_FILTER_PCTYPE_NONF_IPV4_TCP,
+					I40E_L3_SRC_MASK | I40E_L3_DST_MASK |
+					I40E_L4_SRC_MASK | I40E_L4_DST_MASK);
+
 		pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
 		if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
 		    (I40E_DEBUG_FD & pf->hw.debug_mask))
-- 
2.14.3

^ permalink raw reply related

* [net-next 7/9] i40e: factor out re-enable functions for ATR and SB
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Jacob Keller <jacob.e.keller@intel.com>

A future patch needs to expand on the logic for re-enabling ATR. Doing
so would cause some code to break the 80-character line limit.

To reduce the level of indentation, factor out helper functions for
re-enabling ATR and SB rules.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 48 +++++++++++++++++++----------
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 848c8f1acbbf..beb854208047 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -8135,6 +8135,34 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf)
 	return fcnt_prog;
 }
 
+/**
+ * i40e_reenable_fdir_sb - Restore FDir SB capability
+ * @pf: board private structure
+ **/
+static void i40e_reenable_fdir_sb(struct i40e_pf *pf)
+{
+	if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
+		pf->flags &= ~I40E_FLAG_FD_SB_AUTO_DISABLED;
+		if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
+		    (I40E_DEBUG_FD & pf->hw.debug_mask))
+			dev_info(&pf->pdev->dev, "FD Sideband/ntuple is being enabled since we have space in the table now\n");
+	}
+}
+
+/**
+ * i40e_reenable_fdir_atr - Restore FDir ATR capability
+ * @pf: board private structure
+ **/
+static void i40e_reenable_fdir_atr(struct i40e_pf *pf)
+{
+	if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
+		pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
+		if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+		    (I40E_DEBUG_FD & pf->hw.debug_mask))
+			dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table and there are no conflicting ntuple rules\n");
+	}
+}
+
 /**
  * i40e_delete_invalid_filter - Delete an invalid FDIR filter
  * @pf: board private structure
@@ -8198,28 +8226,16 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
 	fcnt_avail = pf->fdir_pf_filter_count;
 	if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) ||
 	    (pf->fd_add_err == 0) ||
-	    (i40e_get_current_atr_cnt(pf) < pf->fd_atr_cnt)) {
-		if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
-			pf->flags &= ~I40E_FLAG_FD_SB_AUTO_DISABLED;
-			if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
-			    (I40E_DEBUG_FD & pf->hw.debug_mask))
-				dev_info(&pf->pdev->dev, "FD Sideband/ntuple is being enabled since we have space in the table now\n");
-		}
-	}
+	    (i40e_get_current_atr_cnt(pf) < pf->fd_atr_cnt))
+		i40e_reenable_fdir_sb(pf);
 
 	/* We should wait for even more space before re-enabling ATR.
 	 * Additionally, we cannot enable ATR as long as we still have TCP SB
 	 * rules active.
 	 */
 	if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) &&
-	    (pf->fd_tcp4_filter_cnt == 0)) {
-		if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
-			pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
-			if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
-			    (I40E_DEBUG_FD & pf->hw.debug_mask))
-				dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table and there are no conflicting ntuple rules\n");
-		}
-	}
+	    (pf->fd_tcp4_filter_cnt == 0))
+		i40e_reenable_fdir_atr(pf);
 
 	/* if hw had a problem adding a filter, delete it */
 	if (pf->fd_inv > 0) {
-- 
2.14.3

^ permalink raw reply related

* [net-next 8/9] i40e: fix for wrong partition id calculation on OCP mezz cards
From: Jeff Kirsher @ 2018-03-14 20:44 UTC (permalink / raw)
  To: davem; +Cc: Mariusz Stachura, netdev, nhorman, sassmann, jogreene,
	Jeff Kirsher
In-Reply-To: <20180314204448.13878-1-jeffrey.t.kirsher@intel.com>

From: Mariusz Stachura <mariusz.stachura@intel.com>

This patch overwrites number of ports for X722 devices with support
for OCP PHY mezzanine.
The old method with checking if port is disabled in the PRTGEN_CNF
register cannot be used in this case. When the OCP is removed, ports
were seen as disabled, which resulted in wrong calculation of partition
id, that caused WoL to be disabled on certain ports.

Signed-off-by: Mariusz Stachura <mariusz.stachura@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_common.c | 23 ++++++++++++++++++++++-
 drivers/net/ethernet/intel/i40e/i40e_type.h   |  3 +++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index ef5a868aae46..242c4c789e8d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -3200,9 +3200,10 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
 	u32 valid_functions, num_functions;
 	u32 number, logical_id, phys_id;
 	struct i40e_hw_capabilities *p;
+	u16 id, ocp_cfg_word0;
+	i40e_status status;
 	u8 major_rev;
 	u32 i = 0;
-	u16 id;
 
 	cap = (struct i40e_aqc_list_capabilities_element_resp *) buff;
 
@@ -3389,6 +3390,26 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
 			hw->num_ports++;
 	}
 
+	/* OCP cards case: if a mezz is removed the Ethernet port is at
+	 * disabled state in PRTGEN_CNF register. Additional NVM read is
+	 * needed in order to check if we are dealing with OCP card.
+	 * Those cards have 4 PFs at minimum, so using PRTGEN_CNF for counting
+	 * physical ports results in wrong partition id calculation and thus
+	 * not supporting WoL.
+	 */
+	if (hw->mac.type == I40E_MAC_X722) {
+		if (!i40e_acquire_nvm(hw, I40E_RESOURCE_READ)) {
+			status = i40e_aq_read_nvm(hw, I40E_SR_EMP_MODULE_PTR,
+						  2 * I40E_SR_OCP_CFG_WORD0,
+						  sizeof(ocp_cfg_word0),
+						  &ocp_cfg_word0, true, NULL);
+			if (!status &&
+			    (ocp_cfg_word0 & I40E_SR_OCP_ENABLED))
+				hw->num_ports = 4;
+			i40e_release_nvm(hw);
+		}
+	}
+
 	valid_functions = p->valid_functions;
 	num_functions = 0;
 	while (valid_functions) {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index b0eed8c0b2f2..69ea15892a5b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -1336,6 +1336,9 @@ struct i40e_hw_port_stats {
 #define I40E_SR_PCIE_ALT_MODULE_MAX_SIZE	1024
 #define I40E_SR_CONTROL_WORD_1_SHIFT		0x06
 #define I40E_SR_CONTROL_WORD_1_MASK	(0x03 << I40E_SR_CONTROL_WORD_1_SHIFT)
+#define I40E_PTR_TYPE				BIT(15)
+#define I40E_SR_OCP_CFG_WORD0			0x2B
+#define I40E_SR_OCP_ENABLED			BIT(15)
 
 /* Shadow RAM related */
 #define I40E_SR_SECTOR_SIZE_IN_WORDS	0x800
-- 
2.14.3

^ permalink raw reply related

* sctp: use proc_remove_subtree()
From: Al Viro @ 2018-03-14 20:46 UTC (permalink / raw)
  To: netdev; +Cc: linux-sctp

use proc_remove_subtree() for subtree removal, both on setup failure
halfway through and on teardown.  No need to make simple things
complex...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/net/sctp/sctp.h |  9 +--------
 net/sctp/proc.c         | 90 +++++++++++++++++++++---------------------------------------------------------------------
 net/sctp/protocol.c     | 57 ++++++---------------------------------------------------
 3 files changed, 28 insertions(+), 128 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index f7ae6b0a21d0..3f90134008e9 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -180,14 +180,7 @@ struct sctp_transport *sctp_epaddr_lookup_transport(
 /*
  * sctp/proc.c
  */
-int sctp_snmp_proc_init(struct net *net);
-void sctp_snmp_proc_exit(struct net *net);
-int sctp_eps_proc_init(struct net *net);
-void sctp_eps_proc_exit(struct net *net);
-int sctp_assocs_proc_init(struct net *net);
-void sctp_assocs_proc_exit(struct net *net);
-int sctp_remaddr_proc_init(struct net *net);
-void sctp_remaddr_proc_exit(struct net *net);
+int __net_init sctp_proc_init(struct net *net);
 
 /*
  * sctp/offload.c
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 537545ebcb0e..17d0155d9de3 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -101,25 +101,6 @@ static const struct file_operations sctp_snmp_seq_fops = {
 	.release = single_release_net,
 };
 
-/* Set up the proc fs entry for 'snmp' object. */
-int __net_init sctp_snmp_proc_init(struct net *net)
-{
-	struct proc_dir_entry *p;
-
-	p = proc_create("snmp", S_IRUGO, net->sctp.proc_net_sctp,
-			&sctp_snmp_seq_fops);
-	if (!p)
-		return -ENOMEM;
-
-	return 0;
-}
-
-/* Cleanup the proc fs entry for 'snmp' object. */
-void sctp_snmp_proc_exit(struct net *net)
-{
-	remove_proc_entry("snmp", net->sctp.proc_net_sctp);
-}
-
 /* Dump local addresses of an association/endpoint. */
 static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
 {
@@ -259,25 +240,6 @@ static const struct file_operations sctp_eps_seq_fops = {
 	.release = seq_release_net,
 };
 
-/* Set up the proc fs entry for 'eps' object. */
-int __net_init sctp_eps_proc_init(struct net *net)
-{
-	struct proc_dir_entry *p;
-
-	p = proc_create("eps", S_IRUGO, net->sctp.proc_net_sctp,
-			&sctp_eps_seq_fops);
-	if (!p)
-		return -ENOMEM;
-
-	return 0;
-}
-
-/* Cleanup the proc fs entry for 'eps' object. */
-void sctp_eps_proc_exit(struct net *net)
-{
-	remove_proc_entry("eps", net->sctp.proc_net_sctp);
-}
-
 struct sctp_ht_iter {
 	struct seq_net_private p;
 	struct rhashtable_iter hti;
@@ -390,25 +352,6 @@ static const struct file_operations sctp_assocs_seq_fops = {
 	.release = seq_release_net,
 };
 
-/* Set up the proc fs entry for 'assocs' object. */
-int __net_init sctp_assocs_proc_init(struct net *net)
-{
-	struct proc_dir_entry *p;
-
-	p = proc_create("assocs", S_IRUGO, net->sctp.proc_net_sctp,
-			&sctp_assocs_seq_fops);
-	if (!p)
-		return -ENOMEM;
-
-	return 0;
-}
-
-/* Cleanup the proc fs entry for 'assocs' object. */
-void sctp_assocs_proc_exit(struct net *net)
-{
-	remove_proc_entry("assocs", net->sctp.proc_net_sctp);
-}
-
 static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
 {
 	struct sctp_association *assoc;
@@ -488,12 +431,6 @@ static const struct seq_operations sctp_remaddr_ops = {
 	.show  = sctp_remaddr_seq_show,
 };
 
-/* Cleanup the proc fs entry for 'remaddr' object. */
-void sctp_remaddr_proc_exit(struct net *net)
-{
-	remove_proc_entry("remaddr", net->sctp.proc_net_sctp);
-}
-
 static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
 {
 	return seq_open_net(inode, file, &sctp_remaddr_ops,
@@ -507,13 +444,28 @@ static const struct file_operations sctp_remaddr_seq_fops = {
 	.release = seq_release_net,
 };
 
-int __net_init sctp_remaddr_proc_init(struct net *net)
+/* Set up the proc fs entry for the SCTP protocol. */
+int __net_init sctp_proc_init(struct net *net)
 {
-	struct proc_dir_entry *p;
-
-	p = proc_create("remaddr", S_IRUGO, net->sctp.proc_net_sctp,
-			&sctp_remaddr_seq_fops);
-	if (!p)
+	net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
+	if (!net->sctp.proc_net_sctp)
 		return -ENOMEM;
+	if (!proc_create("snmp", S_IRUGO, net->sctp.proc_net_sctp,
+			&sctp_snmp_seq_fops))
+		goto cleanup;
+	if (!proc_create("eps", S_IRUGO, net->sctp.proc_net_sctp,
+			&sctp_eps_seq_fops))
+		goto cleanup;
+	if (!proc_create("assocs", S_IRUGO, net->sctp.proc_net_sctp,
+			&sctp_assocs_seq_fops))
+		goto cleanup;
+	if (!proc_create("remaddr", S_IRUGO, net->sctp.proc_net_sctp,
+			&sctp_remaddr_seq_fops))
+		goto cleanup;
 	return 0;
+
+cleanup:
+	remove_proc_subtree("sctp", net->proc_net);
+	net->sctp.proc_net_sctp = NULL;
+	return -ENOMEM;
 }
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 91813e686c67..aea493649f3f 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -80,56 +80,6 @@ long sysctl_sctp_mem[3];
 int sysctl_sctp_rmem[3];
 int sysctl_sctp_wmem[3];
 
-/* Set up the proc fs entry for the SCTP protocol. */
-static int __net_init sctp_proc_init(struct net *net)
-{
-#ifdef CONFIG_PROC_FS
-	net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
-	if (!net->sctp.proc_net_sctp)
-		goto out_proc_net_sctp;
-	if (sctp_snmp_proc_init(net))
-		goto out_snmp_proc_init;
-	if (sctp_eps_proc_init(net))
-		goto out_eps_proc_init;
-	if (sctp_assocs_proc_init(net))
-		goto out_assocs_proc_init;
-	if (sctp_remaddr_proc_init(net))
-		goto out_remaddr_proc_init;
-
-	return 0;
-
-out_remaddr_proc_init:
-	sctp_assocs_proc_exit(net);
-out_assocs_proc_init:
-	sctp_eps_proc_exit(net);
-out_eps_proc_init:
-	sctp_snmp_proc_exit(net);
-out_snmp_proc_init:
-	remove_proc_entry("sctp", net->proc_net);
-	net->sctp.proc_net_sctp = NULL;
-out_proc_net_sctp:
-	return -ENOMEM;
-#endif /* CONFIG_PROC_FS */
-	return 0;
-}
-
-/* Clean up the proc fs entry for the SCTP protocol.
- * Note: Do not make this __exit as it is used in the init error
- * path.
- */
-static void sctp_proc_exit(struct net *net)
-{
-#ifdef CONFIG_PROC_FS
-	sctp_snmp_proc_exit(net);
-	sctp_eps_proc_exit(net);
-	sctp_assocs_proc_exit(net);
-	sctp_remaddr_proc_exit(net);
-
-	remove_proc_entry("sctp", net->proc_net);
-	net->sctp.proc_net_sctp = NULL;
-#endif
-}
-
 /* Private helper to extract ipv4 address and stash them in
  * the protocol structure.
  */
@@ -1285,10 +1235,12 @@ static int __net_init sctp_defaults_init(struct net *net)
 	if (status)
 		goto err_init_mibs;
 
+#ifdef CONFIG_PROC_FS
 	/* Initialize proc fs directory.  */
 	status = sctp_proc_init(net);
 	if (status)
 		goto err_init_proc;
+#endif
 
 	sctp_dbg_objcnt_init(net);
 
@@ -1322,7 +1274,10 @@ static void __net_exit sctp_defaults_exit(struct net *net)
 
 	sctp_dbg_objcnt_exit(net);
 
-	sctp_proc_exit(net);
+#ifdef CONFIG_PROC_FS
+	remove_proc_subtree("sctp", net->proc_net);
+	net->sctp.proc_net_sctp = NULL;
+#endif
 	cleanup_sctp_mibs(net);
 	sctp_sysctl_net_unregister(net);
 }

^ permalink raw reply related

* Re: sctp: use proc_remove_subtree()
From: Al Viro @ 2018-03-14 20:51 UTC (permalink / raw)
  To: netdev; +Cc: linux-sctp
In-Reply-To: <20180314204621.GY30522@ZenIV.linux.org.uk>

On Wed, Mar 14, 2018 at 08:46:21PM +0000, Al Viro wrote:
> use proc_remove_subtree() for subtree removal, both on setup failure
> halfway through and on teardown.  No need to make simple things
> complex...

... and sctp_dbg_objcnt_exit() can be removed as well - remove_proc_subtree()
will get that sucker automatically.  Either a trivial addition, or equally
trivial followup...

^ permalink raw reply

* Re: [PATCH] brcmfmac: drop Inter-Access Point Protocol packets by default
From: Arend van Spriel @ 2018-03-14 20:55 UTC (permalink / raw)
  To: Kalle Valo, Rafał Miłecki
  Cc: Rafał Miłecki, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Pieter-Paul Giesberts, James Hughes,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	brcm80211-dev-list.pdl-dY08KVG/lbpWk0Htik3J/w,
	brcm80211-dev-list-+wT8y+m8/X5BDgjK7y7TUQ,
	netdev-u79uwXL29TY76Z2rM5mHXA, Linus Lüssing, Felix Fietkau,
	bridge-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
In-Reply-To: <877eqe63kr.fsf-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

On 3/14/2018 5:10 PM, Kalle Valo wrote:
> Rafał Miłecki <rafal-g1n6cQUeyibVItvQsEIGlw@public.gmane.org> writes:
>
>>>> +	unsigned char *eth_data = skb_mac_header(skb) + ETH_HLEN;
>>>> +#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
>>>
>>> #ifndef?
>>
>> I followed what is used in the include/linux/etherdevice.h. Is that a
>> good exceuse? Could it be there any some good reason for #if defined()?
>
> Don't know, maybe just a matter of taste? But it would be nice to know
> the background behind #ifdef vs #if defined(), never figured it out why
> two different forms.

Well. In this case you could use either one, but if you have more 
conditions #if defined() is bit more efficient:

#ifdef A
#ifdef B
#endif
#endif

vs.

#if defined(A) && defined(B)

Regards,
Arend

^ permalink raw reply

* [PATCH] net: ethernet: arc: Fix a potential memory leak if an optional regulator is deferred
From: Christophe JAILLET @ 2018-03-14 21:09 UTC (permalink / raw)
  To: heiko, branislav, davem
  Cc: netdev, linux-arm-kernel, linux-rockchip, linux-kernel,
	kernel-janitors, Christophe JAILLET

If the optional regulator is deferrred, we must release some resources.
They will be re-allocated when the probe function will be called again.

Fixes: 6eacf31139bf ("ethernet: arc: Add support for Rockchip SoC layer device tree bindings")
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
---
 drivers/net/ethernet/arc/emac_rockchip.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
index 16f9bee992fe..8ee9dfd0e363 100644
--- a/drivers/net/ethernet/arc/emac_rockchip.c
+++ b/drivers/net/ethernet/arc/emac_rockchip.c
@@ -169,8 +169,10 @@ static int emac_rockchip_probe(struct platform_device *pdev)
 	/* Optional regulator for PHY */
 	priv->regulator = devm_regulator_get_optional(dev, "phy");
 	if (IS_ERR(priv->regulator)) {
-		if (PTR_ERR(priv->regulator) == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
+		if (PTR_ERR(priv->regulator) == -EPROBE_DEFER) {
+			ret = -EPROBE_DEFER;
+			goto out_clk_disable;
+		}
 		dev_err(dev, "no regulator found\n");
 		priv->regulator = NULL;
 	}
-- 
2.14.1

^ permalink raw reply related

* Re: WARNING in __local_bh_enable_ip (2)
From: Eric Dumazet @ 2018-03-14 21:28 UTC (permalink / raw)
  To: syzbot, davem, linux-kernel, linux-rdma, netdev, rds-devel,
	santosh.shilimkar, syzkaller-bugs
In-Reply-To: <001a113de654ad181e056764f936@google.com>



On 03/14/2018 01:11 PM, syzbot wrote:
> Hello,
> 
> syzbot hit the following crash on net-next commit
> be9fc0971a5c27b791608cf9705a04fe96dbd395 (Tue Mar 13 11:44:53 2018 +0000)
> net: fix sysctl_fb_tunnels_only_for_init_net link error
> 
> So far this crash happened 2 times on net-next.
> Unfortunately, I don't have any reproducer for this crash yet.
> Raw console output is attached.
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached.
> 
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+c68e51bb5e699d3f8d91@syzkaller.appspotmail.com
> It will help syzbot understand when the bug is fixed. See footer for 
> details.
> If you forward the report, please keep this part and the footer.
> 
> ------------[ cut here ]------------
> IRQs not enabled as expected
> WARNING: CPU: 1 PID: 21587 at kernel/softirq.c:162 
> __local_bh_enable_ip+0x1bb/0x230 kernel/softirq.c:162
> Kernel panic - not syncing: panic_on_warn set ...
> 
> CPU: 1 PID: 21587 Comm: syz-executor6 Not tainted 4.16.0-rc4+ #264
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS 
> Google 01/01/2011
> Call Trace:
>   __dump_stack lib/dump_stack.c:17 [inline]
>   dump_stack+0x194/0x24d lib/dump_stack.c:53
>   panic+0x1e4/0x41c kernel/panic.c:183
>   __warn+0x1dc/0x200 kernel/panic.c:547
> syz-executor7: vmalloc: allocation failure: 17045651456 bytes, 
> mode:0x14080c0(GFP_KERNEL|__GFP_ZERO), nodemask=(null)
>   report_bug+0x211/0x2d0 lib/bug.c:184
>   fixup_bug.part.11+0x37/0x80 arch/x86/kernel/traps.c:178
>   fixup_bug arch/x86/kernel/traps.c:247 [inline]
>   do_error_trap+0x2d7/0x3e0 arch/x86/kernel/traps.c:296
> syz-executor7 cpuset=
> /
>   do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:315
>   mems_allowed=0
>   invalid_op+0x1b/0x40 arch/x86/entry/entry_64.S:986
> RIP: 0010:__local_bh_enable_ip+0x1bb/0x230 kernel/softirq.c:162
> RSP: 0018:ffff8801c95f71e0 EFLAGS: 00010082
> RAX: dffffc0000000008 RBX: 0000000000000201 RCX: ffffffff815abf2e
> RDX: 00000000000037b0 RSI: ffffc900045ec000 RDI: 1ffff100392bedc1
> RBP: ffff8801c95f71f8 R08: 0000000000000000 R09: 1ffff100392bed93
> R10: ffff8801c95f70d8 R11: 0000000000000002 R12: ffffffff85638c44
> R13: ffff8801bb9fc080 R14: ffff8801c95f7290 R15: 1ffff100392bee4a
>   __raw_spin_unlock_bh include/linux/spinlock_api_smp.h:176 [inline]
>   _raw_spin_unlock_bh+0x30/0x40 kernel/locking/spinlock.c:200
>   spin_unlock_bh include/linux/spinlock.h:355 [inline]
>   rds_tcp_conn_free+0xa4/0x2d0 net/rds/tcp.c:281
>   __rds_conn_create+0x148f/0x1b60 net/rds/connection.c:277
>   rds_conn_create_outgoing+0x3f/0x50 net/rds/connection.c:309
>   rds_sendmsg+0xe63/0x2590 net/rds/send.c:1156
>   sock_sendmsg_nosec net/socket.c:629 [inline]
>   sock_sendmsg+0xca/0x110 net/socket.c:639
>   ___sys_sendmsg+0x767/0x8b0 net/socket.c:2047
>   __sys_sendmsg+0xe5/0x210 net/socket.c:2081
>   SYSC_sendmsg net/socket.c:2092 [inline]
>   SyS_sendmsg+0x2d/0x50 net/socket.c:2088
>   do_syscall_64+0x281/0x940 arch/x86/entry/common.c:287
>   entry_SYSCALL_64_after_hwframe+0x42/0xb7
> RIP: 0033:0x453e69
> RSP: 002b:00007f102cbd0c68 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
> RAX: ffffffffffffffda RBX: 00007f102cbd16d4 RCX: 0000000000453e69
> RDX: 0000000000000000 RSI: 0000000020001580 RDI: 0000000000000014
> RBP: 000000000072bf58 R08: 0000000000000000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff
> R13: 00000000000004b9 R14: 00000000006f71f8 R15: 0000000000000001
> CPU: 0 PID: 21594 Comm: syz-executor7 Not tainted 4.16.0-rc4+ #264
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS 
> Google 01/01/2011
> Call Trace:
>   __dump_stack lib/dump_stack.c:17 [inline]
>   dump_stack+0x194/0x24d lib/dump_stack.c:53
>   warn_alloc+0x19a/0x2b0 mm/page_alloc.c:3310
>   __vmalloc_node_range+0x4f0/0x650 mm/vmalloc.c:1775
>   __vmalloc_node mm/vmalloc.c:1804 [inline]
>   __vmalloc_node_flags_caller+0x50/0x60 mm/vmalloc.c:1826
>   kvmalloc_node+0x82/0xd0 mm/util.c:428
>   kvmalloc include/linux/mm.h:541 [inline]
>   kvmalloc_array include/linux/mm.h:557 [inline]
>   xt_alloc_entry_offsets+0x21/0x30 net/netfilter/x_tables.c:778
>   translate_table+0x235/0x1690 net/ipv6/netfilter/ip6_tables.c:703
>   do_replace net/ipv6/netfilter/ip6_tables.c:1164 [inline]
>   do_ip6t_set_ctl+0x370/0x5f0 net/ipv6/netfilter/ip6_tables.c:1690
>   nf_sockopt net/netfilter/nf_sockopt.c:106 [inline]
>   nf_setsockopt+0x67/0xc0 net/netfilter/nf_sockopt.c:115
>   ipv6_setsockopt+0x10b/0x130 net/ipv6/ipv6_sockglue.c:927
>   tcp_setsockopt+0x82/0xd0 net/ipv4/tcp.c:2878
>   sock_common_setsockopt+0x95/0xd0 net/core/sock.c:2980
>   SYSC_setsockopt net/socket.c:1850 [inline]
>   SyS_setsockopt+0x189/0x360 net/socket.c:1829
>   do_syscall_64+0x281/0x940 arch/x86/entry/common.c:287
>   entry_SYSCALL_64_after_hwframe+0x42/0xb7
> RIP: 0033:0x453e69
> RSP: 002b:00007f0cd3439c68 EFLAGS: 00000246 ORIG_RAX: 0000000000000036
> RAX: ffffffffffffffda RBX: 00007f0cd343a6d4 RCX: 0000000000453e69
> RDX: 0000000000000040 RSI: 0000000000000029 RDI: 0000000000000014
> RBP: 000000000072bea0 R08: 0000000000000004 R09: 0000000000000000
> R10: 0000000020001fde R11: 0000000000000246 R12: 00000000ffffffff
> R13: 0000000000000520 R14: 00000000006f7ba0 R15: 0000000000000000
> Dumping ftrace buffer:
>     (ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..
> 
> 
> ---
> This bug is generated by a dumb bot. It may contain errors.
> See https://goo.gl/tpsmEJ for details.
> Direct all questions to syzkaller@googlegroups.com.
> 
> syzbot will keep track of this bug report.
> If you forgot to add the Reported-by tag, once the fix for this bug is 
> merged
> into any tree, please reply to this email with:
> #syz fix: exact-commit-title
> To mark this as a duplicate of another syzbot report, please reply with:
> #syz dup: exact-subject-of-another-report
> If it's a one-off invalid bug report, please reply with:
> #syz invalid
> Note: if the crash happens again, it will cause creation of a new bug 
> report.
> Note: all commands must start from beginning of the line in the email body.


spin_lock_bh(&rds_tcp_conn_lock);/spin_unlock_bh(&rds_tcp_conn_lock); 
in rds_tcp_conn_free()

is in conflict with the spin_lock_irqsave(&rds_conn_lock, flags);
in __rds_conn_create()

Hard to understand why RDS is messing with hard irqs really.

^ permalink raw reply

* Re: WARNING in __local_bh_enable_ip (2)
From: Sowmini Varadhan @ 2018-03-14 21:33 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: syzbot, davem, linux-kernel, linux-rdma, netdev, rds-devel,
	santosh.shilimkar, syzkaller-bugs
In-Reply-To: <1686ceff-9b7e-592e-8607-b3b8add6a6a3@gmail.com>

On (03/14/18 14:28), Eric Dumazet wrote:
> 
> 
> spin_lock_bh(&rds_tcp_conn_lock);/spin_unlock_bh(&rds_tcp_conn_lock); in
> rds_tcp_conn_free()
> 
> is in conflict with the spin_lock_irqsave(&rds_conn_lock, flags);
> in __rds_conn_create()

yes I was going to look into this and fix it later.

> Hard to understand why RDS is messing with hard irqs really.

some of it comes from the rds_rdma history: some parts of
the common rds and rds_rdma module get called in various
driver contexts for infiniband.

--Sowmini

^ permalink raw reply

* [PATCH v2] vhost: add vsock compat ioctl
From: Sonny Rao @ 2018-03-14 21:36 UTC (permalink / raw)
  To: kvm
  Cc: Stefan Hajnoczi, Michael S . Tsirkin, Jason Wang, virtualization,
	netdev, linux-kernel

This will allow usage of vsock from 32-bit binaries on a 64-bit
kernel.

Signed-off-by: Sonny Rao <sonnyrao@chromium.org>
---
 drivers/vhost/vsock.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 0d14e2ff19f16..ee0c385d9fe54 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -699,12 +699,23 @@ static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl,
 	}
 }
 
+#ifdef CONFIG_COMPAT
+static long vhost_vsock_dev_compat_ioctl(struct file *f, unsigned int ioctl,
+					 unsigned long arg)
+{
+	return vhost_vsock_dev_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
+}
+#endif
+
 static const struct file_operations vhost_vsock_fops = {
 	.owner          = THIS_MODULE,
 	.open           = vhost_vsock_dev_open,
 	.release        = vhost_vsock_dev_release,
 	.llseek		= noop_llseek,
 	.unlocked_ioctl = vhost_vsock_dev_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = vhost_vsock_dev_compat_ioctl,
+#endif
 };
 
 static struct miscdevice vhost_vsock_misc = {
-- 
2.13.5

^ permalink raw reply related

* Re: [PATCH 7/7] ixgbevf: eliminate duplicate barriers on weakly-ordered archs
From: Alexander Duyck @ 2018-03-14 21:49 UTC (permalink / raw)
  To: Sinan Kaya
  Cc: Timur Tabi, Netdev, sulrich, linux-arm-msm, linux-arm-kernel,
	Jeff Kirsher, intel-wired-lan, LKML
In-Reply-To: <2a4f4dec64b7462ae64152f6c2df9754@codeaurora.org>

On Wed, Mar 14, 2018 at 5:13 AM,  <okaya@codeaurora.org> wrote:
> On 2018-03-14 01:08, Timur Tabi wrote:
>>
>> On 3/13/18 10:20 PM, Sinan Kaya wrote:
>>>
>>> +/* Assumes caller has executed a write barrier to order memory and
>>> device
>>> + * requests.
>>> + */
>>>   static inline void ixgbevf_write_tail(struct ixgbevf_ring *ring, u32
>>> value)
>>>   {
>>> -       writel(value, ring->tail);
>>> +       writel_relaxed(value, ring->tail);
>>>   }
>>
>>
>> Why not put the wmb() in this function, or just get rid of the wmb()
>> in the rest of the file and keep this as writel?  That way, you can
>> avoid the comment and the risk that comes with it.
>
>
>
> Sure, both solutions will work. I want to see what the maintainer prefers. I
> can repost accordingly.

Actually I would argue this whole patch set is pointless. For starters
why is it we are only updating the Intel Ethernet drivers here? This
seems like something that is going to impact the whole kernel tree
since many of us have been writing drivers for some time assuming x86
style behavior.

It doesn't make sense to be optimizing the drivers for one subset of
architectures. The scope of the work needed to update the drivers for
this would be ridiculous. Also I don't see how this could be expected
to work on any other architecture when we pretty much need to have a
wmb() before calling the writel on x86 to deal with accesses between
coherent and non-coherent memory. It seems to me more like somebody
added what they considered to be an optimization somewhere that is a
workaround for a poorly written driver. Either that or the barrier is
serving a different purpose then the one we were using.

It would make more sense to put in the effort making writel and
writel_relaxed consistent between architectures before we go through
and start modifying driver code to support different architectures.

^ permalink raw reply

* [PATCH net-next v2 0/2] skbuff: Fix applications not being woken for errors
From: Vinicius Costa Gomes @ 2018-03-14 21:54 UTC (permalink / raw)
  To: netdev; +Cc: Vinicius Costa Gomes, randy.e.witt, davem, eric.dumazet

Hi,

Changes from v1:
 - Fixed comments from Willem de Bruijn, about the order of the
 options passed to getopt();
 - Added Reviewed-by and Fixes tags to patch (2);

Changes from the RFC:
 - tweaked commit messages;

Original cover letter:

This is actually a "bug report"-RFC instead of the more usual "new
feature"-RFC.

We are developing an application that uses TX hardware timestamping to
make some measurements, and during development Randy Witt initially
reported that the application poll() never unblocked when TX hardware
timestamping was enabled.

After some investigation, it turned out the problem wasn't only
exclusive to hardware timestamping, and could be reproduced with
software timestamping.

Applying patch (1), and running txtimestamp like this, for example:

$ ./txtimestamp -u -4 192.168.1.71 -c 1000 -D -l 1000 -F

('-u' to use UDP only, '-4' for ipv4 only, '-c 1000' to send 1000
packets for each test, '-D' to remove the delay between packets, '-l
1000' to set the payload to 1000 bytes, '-F' for configuring poll() to
wait forever)

will cause the application to become stuck in the poll() call in most
of the times. (Note: I couldn't reproduce the issue running against an
address that is routed through loopback.)

Another interesting fact is that if the POLLIN event is added to the
poll() .events, poll() no longer becomes stuck, and more interestingly
the returned event in .revents is only POLLERR.

After a few debugging sessions, we got to 'sock_queue_err_skb()' and
how it notifies applications of the error just enqueued. Changing it
to use 'sk->sk_error_report()', fixes the issue for hardware and
software timestamping. That is patch (2).

The "solution" proposed in patch (2) looks like too big a hammer, if
it's not, then it seems that this problem existed since a long time
ago (pre git) and was uncommon for folks to reach the necessary
conditions to trigger it (my hypothesis is that only triggers when the
error is reported from a different task context than the application).

Am I missing something here?

Cheers,
--

Vinicius Costa Gomes (2):
  selftests/txtimestamp: Add more configurable parameters
  skbuff: Fix not waking applications when errors are enqueued

 net/core/skbuff.c                                   |  2 +-
 .../selftests/networking/timestamping/txtimestamp.c | 21 ++++++++++++++++++---
 2 files changed, 19 insertions(+), 4 deletions(-)

--
2.16.2

^ permalink raw reply

* [PATCH net-next v2 2/2] skbuff: Fix not waking applications when errors are enqueued
From: Vinicius Costa Gomes @ 2018-03-14 21:54 UTC (permalink / raw)
  To: netdev; +Cc: Vinicius Costa Gomes, randy.e.witt, davem, eric.dumazet
In-Reply-To: <20180314215437.14726-1-vinicius.gomes@intel.com>

When errors are enqueued to the error queue via sock_queue_err_skb()
function, it is possible that the waiting application is not notified.

Calling 'sk->sk_data_ready()' would not notify applications that
selected only POLLERR events in poll() (for example).

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Randy E. Witt <randy.e.witt@intel.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
 net/core/skbuff.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 715c13495ba6..6def3534f509 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4181,7 +4181,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
 
 	skb_queue_tail(&sk->sk_error_queue, skb);
 	if (!sock_flag(sk, SOCK_DEAD))
-		sk->sk_data_ready(sk);
+		sk->sk_error_report(sk);
 	return 0;
 }
 EXPORT_SYMBOL(sock_queue_err_skb);
-- 
2.16.2

^ permalink raw reply related

* [PATCH net-next v2 1/2] selftests/txtimestamp: Add more configurable parameters
From: Vinicius Costa Gomes @ 2018-03-14 21:54 UTC (permalink / raw)
  To: netdev; +Cc: Vinicius Costa Gomes, randy.e.witt, davem, eric.dumazet
In-Reply-To: <20180314215437.14726-1-vinicius.gomes@intel.com>

Add a way to configure if poll() should wait forever for an event, the
number of packets that should be sent for each and if there should be
any delay between packets.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
 .../selftests/networking/timestamping/txtimestamp.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/networking/timestamping/txtimestamp.c b/tools/testing/selftests/networking/timestamping/txtimestamp.c
index 5df07047ca86..81a98a240456 100644
--- a/tools/testing/selftests/networking/timestamping/txtimestamp.c
+++ b/tools/testing/selftests/networking/timestamping/txtimestamp.c
@@ -68,9 +68,11 @@ static int cfg_num_pkts = 4;
 static int do_ipv4 = 1;
 static int do_ipv6 = 1;
 static int cfg_payload_len = 10;
+static int cfg_poll_timeout = 100;
 static bool cfg_show_payload;
 static bool cfg_do_pktinfo;
 static bool cfg_loop_nodata;
+static bool cfg_no_delay;
 static uint16_t dest_port = 9000;
 
 static struct sockaddr_in daddr;
@@ -171,7 +173,7 @@ static void __poll(int fd)
 
 	memset(&pollfd, 0, sizeof(pollfd));
 	pollfd.fd = fd;
-	ret = poll(&pollfd, 1, 100);
+	ret = poll(&pollfd, 1, cfg_poll_timeout);
 	if (ret != 1)
 		error(1, errno, "poll");
 }
@@ -371,7 +373,8 @@ static void do_test(int family, unsigned int opt)
 			error(1, errno, "send");
 
 		/* wait for all errors to be queued, else ACKs arrive OOO */
-		usleep(50 * 1000);
+		if (!cfg_no_delay)
+			usleep(50 * 1000);
 
 		__poll(fd);
 
@@ -392,6 +395,9 @@ static void __attribute__((noreturn)) usage(const char *filepath)
 			"  -4:   only IPv4\n"
 			"  -6:   only IPv6\n"
 			"  -h:   show this message\n"
+			"  -c N: number of packets for each test\n"
+			"  -D:   no delay between packets\n"
+			"  -F:   poll() waits forever for an event\n"
 			"  -I:   request PKTINFO\n"
 			"  -l N: send N bytes at a time\n"
 			"  -n:   set no-payload option\n"
@@ -409,7 +415,7 @@ static void parse_opt(int argc, char **argv)
 	int proto_count = 0;
 	char c;
 
-	while ((c = getopt(argc, argv, "46hIl:np:rRux")) != -1) {
+	while ((c = getopt(argc, argv, "46c:DFhIl:np:rRux")) != -1) {
 		switch (c) {
 		case '4':
 			do_ipv6 = 0;
@@ -417,6 +423,15 @@ static void parse_opt(int argc, char **argv)
 		case '6':
 			do_ipv4 = 0;
 			break;
+		case 'c':
+			cfg_num_pkts = strtoul(optarg, NULL, 10);
+			break;
+		case 'D':
+			cfg_no_delay = true;
+			break;
+		case 'F':
+			cfg_poll_timeout = -1;
+			break;
 		case 'I':
 			cfg_do_pktinfo = true;
 			break;
-- 
2.16.2

^ permalink raw reply related

* Re: [Intel-wired-lan] [PATCH 03/15] ice: Start hardware initialization
From: Venkataramanan, Anirudh @ 2018-03-14 22:05 UTC (permalink / raw)
  To: shannon.nelson@oracle.com, intel-wired-lan@lists.osuosl.org
  Cc: netdev@vger.kernel.org
In-Reply-To: <657f1de9-9727-6b01-1f79-957db6ef8852@oracle.com>

[-- Attachment #1: Type: text/plain, Size: 32347 bytes --]

On Mon, 2018-03-12 at 19:05 -0700, Shannon Nelson wrote:
> On 3/9/2018 9:21 AM, Anirudh Venkataramanan wrote:
> > This patch implements multiple pieces of the initialization flow
> > as follows:
> > 
> > 1) A reset is issued to ensure a clean device state, followed
> >     by initialization of admin queue interface.
> > 
> > 2) Once the admin queue interface is up, clear the PF config
> >     and transition the device to non-PXE mode.
> > 
> > 3) Get the NVM configuration stored in the device's non-volatile
> >     memory (NVM) using ice_init_nvm.
> > 
> > Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel
> > .com>
> > ---
> >   drivers/net/ethernet/intel/ice/Makefile         |   3 +-
> >   drivers/net/ethernet/intel/ice/ice.h            |   2 +
> >   drivers/net/ethernet/intel/ice/ice_adminq_cmd.h |  79 +++++
> >   drivers/net/ethernet/intel/ice/ice_common.c     | 410
> > ++++++++++++++++++++++++
> >   drivers/net/ethernet/intel/ice/ice_common.h     |  11 +
> >   drivers/net/ethernet/intel/ice/ice_controlq.h   |   3 +
> >   drivers/net/ethernet/intel/ice/ice_hw_autogen.h |  30 ++
> >   drivers/net/ethernet/intel/ice/ice_main.c       |  31 ++
> >   drivers/net/ethernet/intel/ice/ice_nvm.c        | 245
> > ++++++++++++++
> >   drivers/net/ethernet/intel/ice/ice_osdep.h      |   1 +
> >   drivers/net/ethernet/intel/ice/ice_status.h     |   5 +
> >   drivers/net/ethernet/intel/ice/ice_type.h       |  49 +++
> >   12 files changed, 868 insertions(+), 1 deletion(-)
> >   create mode 100644 drivers/net/ethernet/intel/ice/ice_nvm.c
> > 
> > diff --git a/drivers/net/ethernet/intel/ice/Makefile
> > b/drivers/net/ethernet/intel/ice/Makefile
> > index eebf619e84a8..373d481dbb25 100644
> > --- a/drivers/net/ethernet/intel/ice/Makefile
> > +++ b/drivers/net/ethernet/intel/ice/Makefile
> > @@ -26,4 +26,5 @@ obj-$(CONFIG_ICE) += ice.o
> >   
> >   ice-y := ice_main.o	\
> >   	 ice_controlq.o	\
> > -	 ice_common.o
> > +	 ice_common.o	\
> > +	 ice_nvm.o
> > diff --git a/drivers/net/ethernet/intel/ice/ice.h
> > b/drivers/net/ethernet/intel/ice/ice.h
> > index ea2fb63bb095..ab2800c31906 100644
> > --- a/drivers/net/ethernet/intel/ice/ice.h
> > +++ b/drivers/net/ethernet/intel/ice/ice.h
> > @@ -30,8 +30,10 @@
> >   #include <linux/bitmap.h>
> >   #include "ice_devids.h"
> >   #include "ice_type.h"
> > +#include "ice_common.h"
> >   
> >   #define ICE_BAR0		0
> > +#define ICE_AQ_LEN		64
> >   
> >   #define ICE_DFLT_NETIF_M (NETIF_MSG_DRV | NETIF_MSG_PROBE |
> > NETIF_MSG_LINK)
> >   
> > diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> > b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> > index 885fa3c6fec4..05b22a1ffd70 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> > +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> > @@ -50,6 +50,67 @@ struct ice_aqc_q_shutdown {
> >   	u8 reserved[12];
> >   };
> >   
> > +/* Request resource ownership (direct 0x0008)
> > + * Release resource ownership (direct 0x0009)
> > + */
> > +struct ice_aqc_req_res {
> > +	__le16 res_id;
> > +#define ICE_AQC_RES_ID_NVM		1
> > +#define ICE_AQC_RES_ID_SDP		2
> > +#define ICE_AQC_RES_ID_CHNG_LOCK	3
> > +#define ICE_AQC_RES_ID_GLBL_LOCK	4
> > +	__le16 access_type;
> > +#define ICE_AQC_RES_ACCESS_READ		1
> > +#define ICE_AQC_RES_ACCESS_WRITE	2
> > +
> > +	/* Upon successful completion, FW writes this value and
> > driver is
> > +	 * expected to release resource before timeout. This value
> > is provided
> > +	 * in milliseconds.
> > +	 */
> > +	__le32 timeout;
> > +#define ICE_AQ_RES_NVM_READ_DFLT_TIMEOUT_MS	3000
> > +#define ICE_AQ_RES_NVM_WRITE_DFLT_TIMEOUT_MS	180000
> > +#define ICE_AQ_RES_CHNG_LOCK_DFLT_TIMEOUT_MS	1000
> > +#define ICE_AQ_RES_GLBL_LOCK_DFLT_TIMEOUT_MS	3000
> > +	/* For SDP: pin id of the SDP */
> > +	__le32 res_number;
> > +	/* Status is only used for ICE_AQC_RES_ID_GLBL_LOCK */
> > +	__le16 status;
> > +#define ICE_AQ_RES_GLBL_SUCCESS		0
> > +#define ICE_AQ_RES_GLBL_IN_PROG		1
> > +#define ICE_AQ_RES_GLBL_DONE		2
> > +	u8 reserved[2];
> 
> Since these structs all become part of the descriptor's param union, 
> perhaps adding reserved space to the end is not necessary.
> 
> > +};
> > +
> > +/* Clear PXE Command and response (direct 0x0110) */
> > +struct ice_aqc_clear_pxe {
> > +	u8 rx_cnt;
> > +#define ICE_AQC_CLEAR_PXE_RX_CNT		0x2
> > +	u8 reserved[15];
> > +};
> > +
> > +/* NVM Read command (indirect 0x0701)
> > + * NVM Erase commands (direct 0x0702)
> > + * NVM Update commands (indirect 0x0703)
> > + */
> > +struct ice_aqc_nvm {
> > +	u8	cmd_flags;
> > +#define ICE_AQC_NVM_LAST_CMD		BIT(0)
> > +#define ICE_AQC_NVM_PCIR_REQ		BIT(0)	/* Used
> > by NVM Update reply */
> > +#define ICE_AQC_NVM_PRESERVATION_S	1
> > +#define ICE_AQC_NVM_PRESERVATION_M	(3 <<
> > CSR_AQ_NVM_PRESERVATION_S)
> > +#define ICE_AQC_NVM_NO_PRESERVATION	(0 <<
> > CSR_AQ_NVM_PRESERVATION_S)
> > +#define ICE_AQC_NVM_PRESERVE_ALL	BIT(1)
> > +#define ICE_AQC_NVM_PRESERVE_SELECTED	(3 <<
> > CSR_AQ_NVM_PRESERVATION_S)
> > +#define ICE_AQC_NVM_FLASH_ONLY		BIT(7)
> > +	u8	module_typeid;
> > +	__le16	length;
> > +#define ICE_AQC_NVM_ERASE_LEN	0xFFFF
> > +	__le32	offset;
> > +	__le32	addr_high;
> > +	__le32	addr_low;
> > +};
> > +
> >   /**
> >    * struct ice_aq_desc - Admin Queue (AQ) descriptor
> >    * @flags: ICE_AQ_FLAG_* flags
> > @@ -79,6 +140,9 @@ struct ice_aq_desc {
> >   		struct ice_aqc_generic generic;
> >   		struct ice_aqc_get_ver get_ver;
> >   		struct ice_aqc_q_shutdown q_shutdown;
> > +		struct ice_aqc_req_res res_owner;
> > +		struct ice_aqc_clear_pxe clear_pxe;
> > +		struct ice_aqc_nvm nvm;
> >   	} params;
> >   };
> >   
> > @@ -96,6 +160,8 @@ struct ice_aq_desc {
> >   /* error codes */
> >   enum ice_aq_err {
> >   	ICE_AQ_RC_OK		= 0,  /* success */
> > +	ICE_AQ_RC_EBUSY		= 12, /* Device or resource
> > busy */
> > +	ICE_AQ_RC_EEXIST	= 13, /* object already exists */
> 
> Are we eventually going to get an ENOTTY error value?  :-)
> 
> >   };
> >   
> >   /* Admin Queue command opcodes */
> > @@ -103,6 +169,19 @@ enum ice_adminq_opc {
> >   	/* AQ commands */
> >   	ice_aqc_opc_get_ver				=
> > 0x0001,
> >   	ice_aqc_opc_q_shutdown				=
> > 0x0003,
> > +
> > +	/* resource ownership */
> > +	ice_aqc_opc_req_res				=
> > 0x0008,
> > +	ice_aqc_opc_release_res				=
> > 0x0009,
> > +
> > +	/* PXE */
> > +	ice_aqc_opc_clear_pxe_mode			=
> > 0x0110,
> > +
> > +	ice_aqc_opc_clear_pf_cfg			= 0x02A4,
> > +
> > +	/* NVM commands */
> > +	ice_aqc_opc_nvm_read				=
> > 0x0701,
> > +
> >   };
> >   
> >   #endif /* _ICE_ADMINQ_CMD_H_ */
> > diff --git a/drivers/net/ethernet/intel/ice/ice_common.c
> > b/drivers/net/ethernet/intel/ice/ice_common.c
> > index d980f0518744..eb3e06488705 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_common.c
> > +++ b/drivers/net/ethernet/intel/ice/ice_common.c
> > @@ -18,6 +18,224 @@
> >   #include "ice_common.h"
> >   #include "ice_adminq_cmd.h"
> >   
> > +#define ICE_PF_RESET_WAIT_COUNT	200
> > +
> > +/**
> > + * ice_set_mac_type - Sets MAC type
> > + * @hw: pointer to the HW structure
> > + *
> > + * This function sets the MAC type of the adapter based on the
> > + * vendor ID and device ID stored in the hw structure.
> > + */
> > +static enum ice_status ice_set_mac_type(struct ice_hw *hw)
> > +{
> > +	if (hw->vendor_id != PCI_VENDOR_ID_INTEL)
> > +		return ICE_ERR_DEVICE_NOT_SUPPORTED;
> > +
> > +	hw->mac_type = ICE_MAC_GENERIC;
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ice_clear_pf_cfg - Clear PF configuration
> > + * @hw: pointer to the hardware structure
> > + */
> > +enum ice_status ice_clear_pf_cfg(struct ice_hw *hw)
> > +{
> > +	struct ice_aq_desc desc;
> > +
> > +	ice_fill_dflt_direct_cmd_desc(&desc,
> > ice_aqc_opc_clear_pf_cfg);
> > +
> > +	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
> > +}
> > +
> > +/**
> > + * ice_init_hw - main hardware initialization routine
> > + * @hw: pointer to the hardware structure
> > + */
> > +enum ice_status ice_init_hw(struct ice_hw *hw)
> > +{
> > +	enum ice_status status;
> > +
> > +	/* Set MAC type based on DeviceID */
> > +	status = ice_set_mac_type(hw);
> > +	if (status)
> > +		return status;
> > +
> > +	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
> > +			 PF_FUNC_RID_FUNC_NUM_M) >>
> > +		PF_FUNC_RID_FUNC_NUM_S;
> > +
> > +	status = ice_reset(hw, ICE_RESET_PFR);
> > +	if (status)
> > +		return status;
> > +
> > +	status = ice_init_all_ctrlq(hw);
> > +	if (status)
> > +		goto err_unroll_cqinit;
> > +
> > +	status = ice_clear_pf_cfg(hw);
> > +	if (status)
> > +		goto err_unroll_cqinit;
> > +
> > +	ice_clear_pxe_mode(hw);
> > +
> > +	status = ice_init_nvm(hw);
> > +	if (status)
> > +		goto err_unroll_cqinit;
> > +
> > +	return 0;
> > +
> > +err_unroll_cqinit:
> > +	ice_shutdown_all_ctrlq(hw);
> > +	return status;
> > +}
> > +
> > +/**
> > + * ice_deinit_hw - unroll initialization operations done by
> > ice_init_hw
> > + * @hw: pointer to the hardware structure
> > + */
> > +void ice_deinit_hw(struct ice_hw *hw)
> > +{
> > +	ice_shutdown_all_ctrlq(hw);
> > +}
> > +
> > +/**
> > + * ice_check_reset - Check to see if a global reset is complete
> > + * @hw: pointer to the hardware structure
> > + */
> > +enum ice_status ice_check_reset(struct ice_hw *hw)
> > +{
> > +	u32 cnt, reg = 0, grst_delay;
> > +
> > +	/* Poll for Device Active state in case a recent CORER,
> > GLOBR,
> > +	 * or EMPR has occurred. The grst delay value is in 100ms
> > units.
> > +	 * Add 1sec for outstanding AQ commands that can take a
> > long time.
> > +	 */
> > +	grst_delay = ((rd32(hw, GLGEN_RSTCTL) &
> > GLGEN_RSTCTL_GRSTDEL_M) >>
> > +		      GLGEN_RSTCTL_GRSTDEL_S) + 10;
> 
> Will this be long enough for any longer-running async completion 
> commands, maybe for NVM?  Or will that matter?
> 
> > +
> > +	for (cnt = 0; cnt < grst_delay; cnt++) {
> > +		mdelay(100);
> > +		reg = rd32(hw, GLGEN_RSTAT);
> > +		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
> > +			break;
> > +	}
> > +
> > +	if (cnt == grst_delay) {
> > +		ice_debug(hw, ICE_DBG_INIT,
> > +			  "Global reset polling failed to
> > complete.\n");
> > +		return ICE_ERR_RESET_FAILED;
> > +	}
> > +
> > +#define ICE_RESET_DONE_MASK	(GLNVM_ULD_CORER_DONE_M | \
> > +				 GLNVM_ULD_GLOBR_DONE_M)
> > +
> > +	/* Device is Active; check Global Reset processes are done
> > */
> > +	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
> > +		reg = rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK;
> > +		if (reg == ICE_RESET_DONE_MASK) {
> > +			ice_debug(hw, ICE_DBG_INIT,
> > +				  "Global reset processes done.
> > %d\n", cnt);
> > +			break;
> > +		}
> > +		mdelay(10);
> > +	}
> > +
> > +	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
> > +		ice_debug(hw, ICE_DBG_INIT,
> > +			  "Wait for Reset Done timed out.
> > GLNVM_ULD = 0x%x\n",
> > +			  reg);
> > +		return ICE_ERR_RESET_FAILED;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ice_pf_reset - Reset the PF
> > + * @hw: pointer to the hardware structure
> > + *
> > + * If a global reset has been triggered, this function checks
> > + * for its completion and then issues the PF reset
> > + */
> > +static enum ice_status ice_pf_reset(struct ice_hw *hw)
> > +{
> > +	u32 cnt, reg;
> > +
> > +	/* If at function entry a global reset was already in
> > progress, i.e.
> > +	 * state is not 'device active' or any of the reset done
> > bits are not
> > +	 * set in GLNVM_ULD, there is no need for a PF Reset; poll
> > until the
> > +	 * global reset is done.
> > +	 */
> > +	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
> > +	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^
> > ICE_RESET_DONE_MASK) {
> > +		/* poll on global reset currently in progress
> > until done */
> > +		if (ice_check_reset(hw))
> > +			return ICE_ERR_RESET_FAILED;
> > +
> > +		return 0;
> > +	}
> > +
> > +	/* Reset the PF */
> > +	reg = rd32(hw, PFGEN_CTRL);
> > +
> > +	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
> > +
> > +	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
> > +		reg = rd32(hw, PFGEN_CTRL);
> > +		if (!(reg & PFGEN_CTRL_PFSWR_M))
> > +			break;
> > +
> > +		mdelay(1);
> > +	}
> > +
> > +	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
> > +		ice_debug(hw, ICE_DBG_INIT,
> > +			  "PF reset polling failed to
> > complete.\n");
> > +		return ICE_ERR_RESET_FAILED;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ice_reset - Perform different types of reset
> > + * @hw: pointer to the hardware structure
> > + * @req: reset request
> > + *
> > + * This function triggers a reset as specified by the req
> > parameter.
> > + *
> > + * Note:
> > + * If anything other than a PF reset is triggered, PXE mode is
> > restored.
> > + * This has to be cleared using ice_clear_pxe_mode again, once the
> > AQ
> > + * interface has been restored in the rebuild flow.
> > + */
> > +enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req
> > req)
> > +{
> > +	u32 val = 0;
> > +
> > +	switch (req) {
> > +	case ICE_RESET_PFR:
> > +		return ice_pf_reset(hw);
> > +	case ICE_RESET_CORER:
> > +		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
> > +		val = GLGEN_RTRIG_CORER_M;
> > +		break;
> > +	case ICE_RESET_GLOBR:
> > +		ice_debug(hw, ICE_DBG_INIT, "GlobalR
> > requested\n");
> > +		val = GLGEN_RTRIG_GLOBR_M;
> > +		break;
> > +	}
> > +
> > +	val |= rd32(hw, GLGEN_RTRIG);
> > +	wr32(hw, GLGEN_RTRIG, val);
> > +	ice_flush(hw);
> > +
> > +	/* wait for the FW to be ready */
> > +	return ice_check_reset(hw);
> > +}
> > +
> >   /**
> >    * ice_debug_cq
> >    * @hw: pointer to the hardware structure
> > @@ -142,3 +360,195 @@ enum ice_status ice_aq_q_shutdown(struct
> > ice_hw *hw, bool unloading)
> >   
> >   	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
> >   }
> > +
> > +/**
> > + * ice_aq_req_res
> > + * @hw: pointer to the hw struct
> > + * @res: resource id
> > + * @access: access type
> > + * @sdp_number: resource number
> > + * @timeout: the maximum time in ms that the driver may hold the
> > resource
> > + * @cd: pointer to command details structure or NULL
> > + *
> > + * requests common resource using the admin queue commands
> > (0x0008)
> > + */
> > +static enum ice_status
> > +ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
> > +	       enum ice_aq_res_access_type access, u8 sdp_number,
> > u32 *timeout,
> > +	       struct ice_sq_cd *cd)
> > +{
> > +	struct ice_aqc_req_res *cmd_resp;
> > +	struct ice_aq_desc desc;
> > +	enum ice_status status;
> > +
> > +	cmd_resp = &desc.params.res_owner;
> > +
> > +	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
> > +
> > +	cmd_resp->res_id = cpu_to_le16(res);
> > +	cmd_resp->access_type = cpu_to_le16(access);
> > +	cmd_resp->res_number = cpu_to_le32(sdp_number);
> > +
> > +	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
> > +	/* The completion specifies the maximum time in ms that
> > the driver
> > +	 * may hold the resource in the Timeout field.
> > +	 * If the resource is held by someone else, the command
> > completes with
> > +	 * busy return value and the timeout field indicates the
> > maximum time
> > +	 * the current owner of the resource has to free it.
> > +	 */
> > +	if (!status || hw->adminq.sq_last_status ==
> > ICE_AQ_RC_EBUSY)
> > +		*timeout = le32_to_cpu(cmd_resp->timeout);
> > +
> > +	return status;
> > +}
> > +
> > +/**
> > + * ice_aq_release_res
> > + * @hw: pointer to the hw struct
> > + * @res: resource id
> > + * @sdp_number: resource number
> > + * @cd: pointer to command details structure or NULL
> > + *
> > + * release common resource using the admin queue commands (0x0009)
> > + */
> > +static enum ice_status
> > +ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8
> > sdp_number,
> > +		   struct ice_sq_cd *cd)
> > +{
> > +	struct ice_aqc_req_res *cmd;
> > +	struct ice_aq_desc desc;
> > +
> > +	cmd = &desc.params.res_owner;
> > +
> > +	ice_fill_dflt_direct_cmd_desc(&desc,
> > ice_aqc_opc_release_res);
> > +
> > +	cmd->res_id = cpu_to_le16(res);
> > +	cmd->res_number = cpu_to_le32(sdp_number);
> > +
> > +	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
> > +}
> > +
> > +/**
> > + * ice_acquire_res
> > + * @hw: pointer to the HW structure
> > + * @res: resource id
> > + * @access: access type (read or write)
> > + *
> > + * This function will attempt to acquire the ownership of a
> > resource.
> > + */
> > +enum ice_status
> > +ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
> > +		enum ice_aq_res_access_type access)
> > +{
> > +#define ICE_RES_POLLING_DELAY_MS	10
> > +	u32 delay = ICE_RES_POLLING_DELAY_MS;
> > +	enum ice_status status;
> > +	u32 time_left = 0;
> > +	u32 timeout;
> > +
> > +	status = ice_aq_req_res(hw, res, access, 0, &time_left,
> > NULL);
> > +
> > +	/* An admin queue return code of ICE_AQ_RC_EEXIST means
> > that another
> > +	 * driver has previously acquired the resource and
> > performed any
> > +	 * necessary updates; in this case the caller does not
> > obtain the
> > +	 * resource and has no further work to do.
> > +	 */
> > +	if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) {
> > +		status = ICE_ERR_AQ_NO_WORK;
> > +		goto ice_acquire_res_exit;
> > +	}
> > +
> > +	if (status)
> > +		ice_debug(hw, ICE_DBG_RES,
> > +			  "resource %d acquire type %d failed.\n",
> > res, access);
> > +
> > +	/* If necessary, poll until the current lock owner
> > timeouts */
> > +	timeout = time_left;
> > +	while (status && timeout && time_left) {
> > +		mdelay(delay);
> > +		timeout = (timeout > delay) ? timeout - delay : 0;
> > +		status = ice_aq_req_res(hw, res, access, 0,
> > &time_left, NULL);
> > +
> > +		if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST)
> > {
> > +			/* lock free, but no work to do */
> > +			status = ICE_ERR_AQ_NO_WORK;
> > +			break;
> > +		}
> > +
> > +		if (!status)
> > +			/* lock acquired */
> > +			break;
> > +	}
> > +	if (status && status != ICE_ERR_AQ_NO_WORK)
> > +		ice_debug(hw, ICE_DBG_RES, "resource acquire timed
> > out.\n");
> > +
> > +ice_acquire_res_exit:
> > +	if (status == ICE_ERR_AQ_NO_WORK) {
> > +		if (access == ICE_RES_WRITE)
> > +			ice_debug(hw, ICE_DBG_RES,
> > +				  "resource indicates no work to
> > do.\n");
> > +		else
> > +			ice_debug(hw, ICE_DBG_RES,
> > +				  "Warning: ICE_ERR_AQ_NO_WORK not
> > expected\n");
> > +	}
> > +	return status;
> > +}
> > +
> > +/**
> > + * ice_release_res
> > + * @hw: pointer to the HW structure
> > + * @res: resource id
> > + *
> > + * This function will release a resource using the proper Admin
> > Command.
> > + */
> > +void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
> > +{
> > +	enum ice_status status;
> > +	u32 total_delay = 0;
> > +
> > +	status = ice_aq_release_res(hw, res, 0, NULL);
> > +
> > +	/* there are some rare cases when trying to release the
> > resource
> > +	 * results in an admin Q timeout, so handle them correctly
> > +	 */
> > +	while ((status == ICE_ERR_AQ_TIMEOUT) &&
> > +	       (total_delay < hw->adminq.sq_cmd_timeout)) {
> > +		mdelay(1);
> > +		status = ice_aq_release_res(hw, res, 0, NULL);
> > +		total_delay++;
> > +	}
> > +}
> > +
> > +/**
> > + * ice_aq_clear_pxe_mode
> > + * @hw: pointer to the hw struct
> > + *
> > + * Tell the firmware that the driver is taking over from PXE
> > (0x0110).
> > + */
> > +static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw)
> > +{
> > +	struct ice_aq_desc desc;
> > +	enum ice_status status;
> > +
> > +	ice_fill_dflt_direct_cmd_desc(&desc,
> > ice_aqc_opc_clear_pxe_mode);
> > +	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
> > +
> > +	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
> > +
> > +	wr32(hw, GLLAN_RCTL_0, 0x1);
> 
> So you can do this write regardless of the send_cmd() status?
> 
> > +
> > +	return status;
> > +}
> > +
> > +/**
> > + * ice_clear_pxe_mode - clear pxe operations mode
> > + * @hw: pointer to the hw struct
> > + *
> > + * Make sure all PXE mode settings are cleared, including things
> > + * like descriptor fetch/write-back mode.
> > + */
> > +void ice_clear_pxe_mode(struct ice_hw *hw)
> > +{
> > +	if (ice_check_sq_alive(hw, &hw->adminq))
> > +		ice_aq_clear_pxe_mode(hw);
> > +}
> > diff --git a/drivers/net/ethernet/intel/ice/ice_common.h
> > b/drivers/net/ethernet/intel/ice/ice_common.h
> > index 1e3caecc38c6..0876fd98090a 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_common.h
> > +++ b/drivers/net/ethernet/intel/ice/ice_common.h
> > @@ -23,12 +23,22 @@
> >   
> >   void ice_debug_cq(struct ice_hw *hw, u32 mask, void *desc, void
> > *buf,
> >   		  u16 buf_len);
> > +enum ice_status ice_init_hw(struct ice_hw *hw);
> > +void ice_deinit_hw(struct ice_hw *hw);
> > +enum ice_status ice_check_reset(struct ice_hw *hw);
> > +enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req
> > req);
> >   enum ice_status ice_init_all_ctrlq(struct ice_hw *hw);
> >   void ice_shutdown_all_ctrlq(struct ice_hw *hw);
> >   enum ice_status
> > +ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
> > +		enum ice_aq_res_access_type access);
> > +void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res);
> > +enum ice_status ice_init_nvm(struct ice_hw *hw);
> > +enum ice_status
> >   ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
> >   		struct ice_aq_desc *desc, void *buf, u16
> > buf_size,
> >   		struct ice_sq_cd *cd);
> > +void ice_clear_pxe_mode(struct ice_hw *hw);
> >   bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info
> > *cq);
> >   enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool
> > unloading);
> >   void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16
> > opcode);
> > @@ -36,4 +46,5 @@ enum ice_status
> >   ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc,
> >   		void *buf, u16 buf_size, struct ice_sq_cd *cd);
> >   enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct
> > ice_sq_cd *cd);
> > +enum ice_status ice_clear_pf_cfg(struct ice_hw *hw);
> >   #endif /* _ICE_COMMON_H_ */
> > diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.h
> > b/drivers/net/ethernet/intel/ice/ice_controlq.h
> > index 143578d02aec..835c035419a3 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_controlq.h
> > +++ b/drivers/net/ethernet/intel/ice/ice_controlq.h
> > @@ -20,6 +20,9 @@
> >   
> >   #include "ice_adminq_cmd.h"
> >   
> > +/* Maximum buffer lengths for all control queue types */
> > +#define ICE_AQ_MAX_BUF_LEN 4096
> > +
> >   #define ICE_CTL_Q_DESC(R, i) \
> >   	(&(((struct ice_aq_desc *)((R).desc_buf.va))[i]))
> >   
> > diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
> > b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
> > index 3d6bb273e4c8..e258a12099b8 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
> > +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
> > @@ -42,5 +42,35 @@
> >   #define PF_FW_ATQLEN_ATQENABLE_S	31
> >   #define PF_FW_ATQLEN_ATQENABLE_M	BIT(PF_FW_ATQLEN_ATQENABL
> > E_S)
> >   #define PF_FW_ATQT			0x00080400
> > +#define GLGEN_RSTAT			0x000B8188
> > +#define GLGEN_RSTAT_DEVSTATE_S		0
> > +#define GLGEN_RSTAT_DEVSTATE_M		ICE_M(0x3,
> > GLGEN_RSTAT_DEVSTATE_S)
> > +#define GLGEN_RSTCTL			0x000B8180
> > +#define GLGEN_RSTCTL_GRSTDEL_S		0
> > +#define GLGEN_RSTCTL_GRSTDEL_M		ICE_M(0x3F,
> > GLGEN_RSTCTL_GRSTDEL_S)
> > +#define GLGEN_RTRIG			0x000B8190
> > +#define GLGEN_RTRIG_CORER_S		0
> > +#define GLGEN_RTRIG_CORER_M		BIT(GLGEN_RTRIG_CORER_S
> > )
> > +#define GLGEN_RTRIG_GLOBR_S		1
> > +#define GLGEN_RTRIG_GLOBR_M		BIT(GLGEN_RTRIG_GLOBR_S
> > )
> > +#define GLGEN_STAT			0x000B612C
> > +#define PFGEN_CTRL			0x00091000
> > +#define PFGEN_CTRL_PFSWR_S		0
> > +#define PFGEN_CTRL_PFSWR_M		BIT(PFGEN_CTRL_PFSWR_S)
> > +#define GLLAN_RCTL_0			0x002941F8
> > +#define GLNVM_FLA			0x000B6108
> > +#define GLNVM_FLA_LOCKED_S		6
> > +#define GLNVM_FLA_LOCKED_M		BIT(GLNVM_FLA_LOCKED_S)
> > +#define GLNVM_GENS			0x000B6100
> > +#define GLNVM_GENS_SR_SIZE_S		5
> > +#define GLNVM_GENS_SR_SIZE_M		ICE_M(0x7,
> > GLNVM_GENS_SR_SIZE_S)
> > +#define GLNVM_ULD			0x000B6008
> > +#define GLNVM_ULD_CORER_DONE_S		3
> > +#define GLNVM_ULD_CORER_DONE_M		BIT(GLNVM_ULD_CORER_
> > DONE_S)
> > +#define GLNVM_ULD_GLOBR_DONE_S		4
> > +#define GLNVM_ULD_GLOBR_DONE_M		BIT(GLNVM_ULD_GLOBR_
> > DONE_S)
> > +#define PF_FUNC_RID			0x0009E880
> > +#define PF_FUNC_RID_FUNC_NUM_S		0
> > +#define PF_FUNC_RID_FUNC_NUM_M		ICE_M(0x7,
> > PF_FUNC_RID_FUNC_NUM_S)
> >   
> >   #endif /* _ICE_HW_AUTOGEN_H_ */
> > diff --git a/drivers/net/ethernet/intel/ice/ice_main.c
> > b/drivers/net/ethernet/intel/ice/ice_main.c
> > index 408ae90d6562..2ee4a0547ba3 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_main.c
> > +++ b/drivers/net/ethernet/intel/ice/ice_main.c
> > @@ -40,6 +40,18 @@ MODULE_PARM_DESC(debug, "netif level
> > (0=none,...,16=all), hw debug_mask (0x8XXXX
> >   MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all)");
> >   #endif /* !CONFIG_DYNAMIC_DEBUG */
> >   
> > +/**
> > + * ice_set_ctrlq_len - helper function to set controlq length
> > + * @hw: pointer to the hw instance
> > + */
> > +static void ice_set_ctrlq_len(struct ice_hw *hw)
> > +{
> > +	hw->adminq.num_rq_entries = ICE_AQ_LEN;
> > +	hw->adminq.num_sq_entries = ICE_AQ_LEN;
> > +	hw->adminq.rq_buf_size = ICE_AQ_MAX_BUF_LEN;
> > +	hw->adminq.sq_buf_size = ICE_AQ_MAX_BUF_LEN;
> > +}
> > +
> >   /**
> >    * ice_probe - Device initialization routine
> >    * @pdev: PCI device information struct
> > @@ -95,6 +107,8 @@ static int ice_probe(struct pci_dev *pdev,
> >   	hw->subsystem_device_id = pdev->subsystem_device;
> >   	hw->bus.device = PCI_SLOT(pdev->devfn);
> >   	hw->bus.func = PCI_FUNC(pdev->devfn);
> > +	ice_set_ctrlq_len(hw);
> > +
> >   	pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M);
> >   
> >   #ifndef CONFIG_DYNAMIC_DEBUG
> > @@ -102,7 +116,22 @@ static int ice_probe(struct pci_dev *pdev,
> >   		hw->debug_mask = debug;
> >   #endif
> >   
> > +	err = ice_init_hw(hw);
> > +	if (err) {
> > +		dev_err(&pdev->dev, "ice_init_hw failed: %d\n",
> > err);
> > +		err = -EIO;
> > +		goto err_exit_unroll;
> > +	}
> > +
> > +	dev_info(&pdev->dev, "firmware %d.%d.%05d api %d.%d\n",
> > +		 hw->fw_maj_ver, hw->fw_min_ver, hw->fw_build,
> > +		 hw->api_maj_ver, hw->api_min_ver);
> > +
> >   	return 0;
> > +
> > +err_exit_unroll:
> > +	pci_disable_pcie_error_reporting(pdev);
> > +	return err;
> >   }
> >   
> >   /**
> > @@ -117,6 +146,8 @@ static void ice_remove(struct pci_dev *pdev)
> >   		return;
> >   
> >   	set_bit(__ICE_DOWN, pf->state);
> > +
> > +	ice_deinit_hw(&pf->hw);
> >   	pci_disable_pcie_error_reporting(pdev);
> >   }
> >   
> > diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c
> > b/drivers/net/ethernet/intel/ice/ice_nvm.c
> > new file mode 100644
> > index 000000000000..565910f01290
> > --- /dev/null
> > +++ b/drivers/net/ethernet/intel/ice/ice_nvm.c
> > @@ -0,0 +1,245 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/* Intel(R) Ethernet Connection E800 Series Linux Driver
> > + * Copyright (c) 2018, Intel Corporation.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > modify it
> > + * under the terms and conditions of the GNU General Public
> > License,
> > + * version 2, as published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope it will be useful, but
> > WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of
> > MERCHANTABILITY or
> > + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> > License for
> > + * more details.
> > + *
> > + * The full GNU General Public License is included in this
> > distribution in
> > + * the file called "COPYING".
> > + */
> > +
> > +#include "ice_common.h"
> > +
> > +/**
> > + * ice_aq_read_nvm
> > + * @hw: pointer to the hw struct
> > + * @module_typeid: module pointer location in words from the NVM
> > beginning
> > + * @offset: byte offset from the module beginning
> > + * @length: length of the section to be read (in bytes from the
> > offset)
> > + * @data: command buffer (size [bytes] = length)
> > + * @last_command: tells if this is the last command in a series
> > + * @cd: pointer to command details structure or NULL
> > + *
> > + * Read the NVM using the admin queue commands (0x0701)
> > + */
> > +static enum ice_status
> > +ice_aq_read_nvm(struct ice_hw *hw, u8 module_typeid, u32 offset,
> > u16 length,
> > +		void *data, bool last_command, struct ice_sq_cd
> > *cd)
> > +{
> > +	struct ice_aq_desc desc;
> > +	struct ice_aqc_nvm *cmd;
> > +
> > +	cmd = &desc.params.nvm;
> > +
> > +	/* In offset the highest byte must be zeroed. */
> > +	if (offset & 0xFF000000)
> > +		return ICE_ERR_PARAM;
> > +
> > +	ice_fill_dflt_direct_cmd_desc(&desc,
> > ice_aqc_opc_nvm_read);
> > +
> > +	/* If this is the last command in a series, set the proper
> > flag. */
> > +	if (last_command)
> > +		cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD;
> > +	cmd->module_typeid = module_typeid;
> > +	cmd->offset = cpu_to_le32(offset);
> > +	cmd->length = cpu_to_le16(length);
> > +
> > +	return ice_aq_send_cmd(hw, &desc, data, length, cd);
> > +}
> > +
> > +/**
> > + * ice_check_sr_access_params - verify params for Shadow RAM R/W
> > operations.
> > + * @hw: pointer to the HW structure
> > + * @offset: offset in words from module start
> > + * @words: number of words to access
> > + */
> > +static enum ice_status
> > +ice_check_sr_access_params(struct ice_hw *hw, u32 offset, u16
> > words)
> > +{
> > +	if ((offset + words) > hw->nvm.sr_words) {
> > +		ice_debug(hw, ICE_DBG_NVM,
> > +			  "NVM error: offset beyond SR lmt.\n");
> > +		return ICE_ERR_PARAM;
> > +	}
> > +
> > +	if (words > ICE_SR_SECTOR_SIZE_IN_WORDS) {
> > +		/* We can access only up to 4KB (one sector), in
> > one AQ write */
> > +		ice_debug(hw, ICE_DBG_NVM,
> > +			  "NVM error: tried to access %d words,
> > limit is %d.\n",
> > +			  words, ICE_SR_SECTOR_SIZE_IN_WORDS);
> > +		return ICE_ERR_PARAM;
> > +	}
> > +
> > +	if (((offset + (words - 1)) / ICE_SR_SECTOR_SIZE_IN_WORDS)
> > !=
> > +	    (offset / ICE_SR_SECTOR_SIZE_IN_WORDS)) {
> > +		/* A single access cannot spread over two sectors
> > */
> > +		ice_debug(hw, ICE_DBG_NVM,
> > +			  "NVM error: cannot spread over two
> > sectors.\n");
> > +		return ICE_ERR_PARAM;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ice_read_sr_aq - Read Shadow RAM.
> > + * @hw: pointer to the HW structure
> > + * @offset: offset in words from module start
> > + * @words: number of words to read
> > + * @data: buffer for words reads from Shadow RAM
> > + * @last_command: tells the AdminQ that this is the last command
> > + *
> > + * Reads 16-bit word buffers from the Shadow RAM using the admin
> > command.
> > + */
> > +static enum ice_status
> > +ice_read_sr_aq(struct ice_hw *hw, u32 offset, u16 words, u16
> > *data,
> > +	       bool last_command)
> > +{
> > +	enum ice_status status;
> > +
> > +	status = ice_check_sr_access_params(hw, offset, words);
> > +	if (!status)
> > +		status = ice_aq_read_nvm(hw, 0, 2 * offset, 2 *
> > words, data,
> 
> Why the doubling of offset and words?  If this is some general 
> adjustment made for the AQ interface, it should be made in 
> ice_aq_read_nvm().  If not, then some explanation is needed here.

ice_read_sr_aq expects a word offset and size in words. The
ice_aq_read_nvm interface expects offset and size in bytes. The
doubling is a conversion from word offset/size to byte offset/size. 

> 
> sln
> 

[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 3302 bytes --]

^ permalink raw reply

* Re: [Intel-wired-lan] [PATCH 02/15] ice: Add support for control queues
From: Jeff Kirsher @ 2018-03-14 22:16 UTC (permalink / raw)
  To: Shannon Nelson, Anirudh Venkataramanan, intel-wired-lan; +Cc: netdev
In-Reply-To: <af3a595f-a9ab-8706-3d94-151a92d5d63a@oracle.com>

[-- Attachment #1: Type: text/plain, Size: 6831 bytes --]

On Mon, 2018-03-12 at 19:05 -0700, Shannon Nelson wrote:
> On 3/9/2018 9:21 AM, Anirudh Venkataramanan wrote:
> > A control queue is a hardware interface which is used by the driver
> > to interact with other subsystems (like firmware, PHY, etc.). It is
> > implemented as a producer-consumer ring. More specifically, an
> > "admin queue" is a type of control queue used to interact with the
> > firmware.
> > 
> > This patch introduces data structures and functions to initialize
> > and teardown control/admin queues. Once the admin queue is
> > initialized,
> > the driver uses it to get the firmware version.
> > 
> > Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel
> > .com>
> > ---
> >    drivers/net/ethernet/intel/ice/Makefile         |   4 +-
> >    drivers/net/ethernet/intel/ice/ice.h            |   1 +
> >    drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 108 +++
> >    drivers/net/ethernet/intel/ice/ice_common.c     | 144 ++++
> >    drivers/net/ethernet/intel/ice/ice_common.h     |  39 +
> >    drivers/net/ethernet/intel/ice/ice_controlq.c   | 979
> > ++++++++++++++++++++++++
> >    drivers/net/ethernet/intel/ice/ice_controlq.h   |  97 +++
> >    drivers/net/ethernet/intel/ice/ice_hw_autogen.h |  46 ++
> >    drivers/net/ethernet/intel/ice/ice_main.c       |  11 +-
> >    drivers/net/ethernet/intel/ice/ice_osdep.h      |  86 +++
> >    drivers/net/ethernet/intel/ice/ice_status.h     |  35 +
> >    drivers/net/ethernet/intel/ice/ice_type.h       |  22 +
> >    12 files changed, 1570 insertions(+), 2 deletions(-)
> >    create mode 100644
> > drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> >    create mode 100644 drivers/net/ethernet/intel/ice/ice_common.c
> >    create mode 100644 drivers/net/ethernet/intel/ice/ice_common.h
> >    create mode 100644 drivers/net/ethernet/intel/ice/ice_controlq.c
> >    create mode 100644 drivers/net/ethernet/intel/ice/ice_controlq.h
> >    create mode 100644
> > drivers/net/ethernet/intel/ice/ice_hw_autogen.h
> >    create mode 100644 drivers/net/ethernet/intel/ice/ice_osdep.h
> >    create mode 100644 drivers/net/ethernet/intel/ice/ice_status.h
> > 
> > diff --git a/drivers/net/ethernet/intel/ice/Makefile
> > b/drivers/net/ethernet/intel/ice/Makefile
> > index 2a177ea21b74..eebf619e84a8 100644
> > --- a/drivers/net/ethernet/intel/ice/Makefile
> > +++ b/drivers/net/ethernet/intel/ice/Makefile
> > @@ -24,4 +24,6 @@
> >    
> >    obj-$(CONFIG_ICE) += ice.o
> >    
> > -ice-y := ice_main.o
> > +ice-y := ice_main.o  \
> > +      ice_controlq.o \
> > +      ice_common.o
> > diff --git a/drivers/net/ethernet/intel/ice/ice.h
> > b/drivers/net/ethernet/intel/ice/ice.h
> > index d781027330cc..ea2fb63bb095 100644
> > --- a/drivers/net/ethernet/intel/ice/ice.h
> > +++ b/drivers/net/ethernet/intel/ice/ice.h
> > @@ -26,6 +26,7 @@
> >    #include <linux/compiler.h>
> >    #include <linux/pci.h>
> >    #include <linux/aer.h>
> > +#include <linux/delay.h>
> >    #include <linux/bitmap.h>
> >    #include "ice_devids.h"
> >    #include "ice_type.h"
> > diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> > b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> > new file mode 100644
> > index 000000000000..885fa3c6fec4
> > --- /dev/null
> > +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> > @@ -0,0 +1,108 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/* Intel(R) Ethernet Connection E800 Series Linux Driver
> > + * Copyright (c) 2018, Intel Corporation.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > modify it
> > + * under the terms and conditions of the GNU General Public
> > License,
> > + * version 2, as published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope it will be useful, but
> > WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of
> > MERCHANTABILITY or
> > + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> > License for
> > + * more details.
> > + *
> > + * The full GNU General Public License is included in this
> > distribution in
> > + * the file called "COPYING".
> > + */
> > +
> > +#ifndef _ICE_ADMINQ_CMD_H_
> > +#define _ICE_ADMINQ_CMD_H_
> > +
> > +/* This header file defines the Admin Queue commands, error codes
> > and
> > + * descriptor format.  It is shared between Firmware and Software.
> > + */
> > +
> > +struct ice_aqc_generic {
> > +     __le32 param0;
> > +     __le32 param1;
> > +     __le32 addr_high;
> > +     __le32 addr_low;
> > +};
> > +
> > +/* Get version (direct 0x0001) */
> > +struct ice_aqc_get_ver {
> > +     __le32 rom_ver;
> > +     __le32 fw_build;
> > +     u8 fw_branch;
> > +     u8 fw_major;
> > +     u8 fw_minor;
> > +     u8 fw_patch;
> > +     u8 api_branch;
> > +     u8 api_major;
> > +     u8 api_minor;
> > +     u8 api_patch;
> > +};
> > +
> > +/* Queue Shutdown (direct 0x0003) */
> > +struct ice_aqc_q_shutdown {
> > +#define ICE_AQC_DRIVER_UNLOADING     BIT(0)
> > +     __le32 driver_unloading;
> > +     u8 reserved[12];
> > +};
> > +
> > +/**
> > + * struct ice_aq_desc - Admin Queue (AQ) descriptor
> > + * @flags: ICE_AQ_FLAG_* flags
> > + * @opcode: AQ command opcode
> > + * @datalen: length in bytes of indirect/external data buffer
> > + * @retval: return value from firmware
> > + * @cookie_h: opaque data high-half
> > + * @cookie_l: opaque data low-half
> > + * @params: command-specific parameters
> > + *
> > + * Descriptor format for commands the driver posts on the Admin
> > Transmit Queue
> > + * (ATQ).  The firmware writes back onto the command descriptor
> > and returns
> > + * the result of the command.  Asynchronous events that are not an
> > immediate
> > + * result of the command are written to the Admin Receive Queue
> > (ARQ) using
> > + * the same descriptor format.  Descriptors are in little-endian
> > notation with
> > + * 32-bit words.
> > + */
> > +struct ice_aq_desc {
> > +     __le16 flags;
> > +     __le16 opcode;
> > +     __le16 datalen;
> > +     __le16 retval;
> > +     __le32 cookie_high;
> > +     __le32 cookie_low;
> > +     union {
> > +             u8 raw[16];
> > +             struct ice_aqc_generic generic;
> > +             struct ice_aqc_get_ver get_ver;
> > +             struct ice_aqc_q_shutdown q_shutdown;
> > +     } params;
> > +};
> 
> You might put a compile-time size check on this struct - it helped
> many 
> times in i40e development.

We have taken appropriate actions to prevent the issues had with i40e
so that the ice driver should not need the same checks that i40e
required.  Also there are Linux kernel macros that are more appropriate
 for build-time checks.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH] can: enable multi-queue for SocketCAN devices
From: Marc Kleine-Budde @ 2018-03-14 22:17 UTC (permalink / raw)
  To: Jonas Mark (BT-FIR/ENG1), Wolfgang Grandegger
  Cc: linux-can@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, hs@denx.de,
	ZHU Yi (BT-FIR/ENG1-Zhu)
In-Reply-To: <1e51047cd14048e99989ffcf9e10ffa8@de.bosch.com>


[-- Attachment #1.1: Type: text/plain, Size: 1827 bytes --]

On 03/14/2018 05:51 PM, Jonas Mark (BT-FIR/ENG1) wrote:
>> That doesn't matter. It would be the first driver that makes use of the
>> feature, so we can learn from it. And you might get a free review of
>> your driver.
> 
> Of course we would be happy if somebody was volunteering to review
> our driver for free.

If my time permits, I'll throw some eyeballs on the driver.

> The driver consists of two layers because the HW is accessed via SPI.

Normal SPI?

> So there is a SPI driver of 1000 lines. On top of that is the CAN
> driver and it has 600 lines. Because the HW does more than just
> CAN there is another driver which implements a char device with
> additional 300 lines.
> 
> Are there still volunteers?

The SPI and the CAN driver would be the most interesting ones.

>>> Our motivation to separate this patch from the proprietary SocketCAN
>>> driver
>>
>> Looking at your email address I assume your employer sells devices with
>> this hardware and the driver. So someone has to provide the sources for
>> it anyways to fulfil the GPL license requirements. :)
> 
> I will have to check but I am pretty confident that we would be willing
> to publish the driver on these mailing lists as well. We will anyhow
> ship the source code (or a written offer) with every distribution.

Sure - can I find your devices used and low priced on ebay :) ?

> If you are really serious about the review I will get the process
> rolling for an early publication of our driver.

Yes, please go ahead!

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH 0/2] net: phy: relax error checking when creating sysfs link netdev->phydev
From: Grygorii Strashko @ 2018-03-14 22:26 UTC (permalink / raw)
  To: David S. Miller, netdev, Andrew Lunn, Florian Fainelli,
	Greg Kroah-Hartman
  Cc: Sekhar Nori, linux-kernel, linux-omap, Grygorii Strashko

Some ethernet drivers (like TI CPSW) may connect and manage >1 Net PHYs per
one netdevice, as result such drivers will produce warning during system
boot and fail to connect second phy to netdevice when PHYLIB framework
will try to create sysfs link netdev->phydev for second PHY
in phy_attach_direct(), because sysfs link with the same name has been
created already for the first PHY.
As result, second CPSW external port will became unusable.
This issue was introduced by commits:
5568363f0cb3 ("net: phy: Create sysfs reciprocal links for attached_dev/phydev"
a3995460491d ("net: phy: Relax error checking on sysfs_create_link()"

Patch 1: exports sysfs_create_link_nowarn() function as preparation for Patch 2.
Patch 2: relaxes error checking when PHYLIB framework is creating sysfs
link netdev->phydev in phy_attach_direct(), suppress warning by using
sysfs_create_link_nowarn() and adds debug message instead.

This is stable material 4.13+.

Cc: Florian Fainelli <f.fainelli@gmail.com>
Grygorii Strashko (2):
  sysfs: symlink: export sysfs_create_link_nowarn()
  net: phy: relax error checking when creating sysfs link netdev->phydev

 drivers/net/phy/phy_device.c | 15 +++++++++++----
 fs/sysfs/symlink.c           |  1 +
 2 files changed, 12 insertions(+), 4 deletions(-)

-- 
2.10.5

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox