From c27936e7b2d57af2965a78973430383be98fe88a Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Tue, 3 Jun 2014 23:50:16 +0000 Subject: i40e: debugfs fix to dump remote LLDPDU Fix the debugfs command "lldp get remote" that dumped the local LLDPDU instead of peer's LLDPDU. Change-ID: I0702eacdafd54478c18f20cab3a7fa5dc1b3182d Signed-off-by: Neerav Parikh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet/intel/i40e/i40e_debugfs.c') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index cffdfc21290f..910b01b90cdc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1830,7 +1830,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, ret = i40e_aq_get_lldp_mib(&pf->hw, I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE, - I40E_AQ_LLDP_MIB_LOCAL, + I40E_AQ_LLDP_MIB_REMOTE, buff, I40E_LLDPDU_SIZE, &llen, &rlen, NULL); if (ret) { -- cgit v1.2.3 From e17ff05c5d9ee64550030d03e63719e6dc62d729 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 4 Jun 2014 04:22:48 +0000 Subject: i40e: Add debugfs hooks to print current total FD filter count "fd current cnt" can be used to print the total filters consumed by this interface, this includes guaranteed and best effort filters. Change-ID: I2c417810c4999ce1388d2ea26f8e69679ba33966 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/ethernet/intel/i40e/i40e_debugfs.c') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 910b01b90cdc..ec07332e109e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1743,6 +1743,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp, i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, false); } else if (strncmp(cmd_buf, "fd-atr on", 9) == 0) { i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, true); + } else if (strncmp(cmd_buf, "fd current cnt", 14) == 0) { + dev_info(&pf->pdev->dev, "FD current total filter count for this interface: %d\n", + i40e_get_current_fd_count(pf)); } else if (strncmp(cmd_buf, "lldp", 4) == 0) { if (strncmp(&cmd_buf[5], "stop", 4) == 0) { int ret; @@ -1962,6 +1965,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, dev_info(&pf->pdev->dev, " rem fd_filter \n"); dev_info(&pf->pdev->dev, " fd-atr off\n"); dev_info(&pf->pdev->dev, " fd-atr on\n"); + dev_info(&pf->pdev->dev, " fd current cnt"); dev_info(&pf->pdev->dev, " lldp start\n"); dev_info(&pf->pdev->dev, " lldp stop\n"); dev_info(&pf->pdev->dev, " lldp get local\n"); -- cgit v1.2.3 From efe1ac25d084fd56c5b809634a0444606c2a5cd3 Mon Sep 17 00:00:00 2001 From: Toralf Förster Date: Tue, 20 May 2014 08:23:00 +0000 Subject: i40e: fix format mismatch in drivers/net/ethernet/intel/i40e/i40e_debugfs.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spotted by cppcheck Signed-off-by: Toralf Förster Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/intel/i40e/i40e_debugfs.c') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index ec07332e109e..9eaed04618a3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1238,7 +1238,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } else if (strncmp(cmd_buf, "add pvid", 8) == 0) { i40e_status ret; u16 vid; - int v; + unsigned int v; cnt = sscanf(&cmd_buf[8], "%i %u", &vsi_seid, &v); if (cnt != 2) { @@ -1254,7 +1254,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, goto command_write_done; } - vid = (unsigned)v; + vid = v; ret = i40e_vsi_add_pvid(vsi, vid); if (!ret) dev_info(&pf->pdev->dev, -- cgit v1.2.3 From 38e004388692f049908636a7944f6cd57d28bd77 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 1 Aug 2014 13:27:03 -0700 Subject: i40e: Adds FCoE related code to i40e core driver Adds FCoE specific code to existing i40e core driver to:- 1. have separate FCoE VSI with additional FCoE queues pairs. 2. have FCoE related hash defines. 3. have additional FCoE related stats code. 4. export and then re-use existing functions required by FCoE build. Signed-off-by: Vasu Dev Tested-by: Jack Morgan Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/i40e/i40e.h | 62 ++++++ drivers/net/ethernet/intel/i40e/i40e_common.c | 27 +++ drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 19 ++ drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 35 +++ drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 9 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 268 +++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_osdep.h | 3 + drivers/net/ethernet/intel/i40e/i40e_prototype.h | 3 + drivers/net/ethernet/intel/i40e/i40e_txrx.c | 37 +++- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 9 + drivers/net/ethernet/intel/i40e/i40e_type.h | 138 ++++++++++++ 11 files changed, 599 insertions(+), 11 deletions(-) (limited to 'drivers/net/ethernet/intel/i40e/i40e_debugfs.c') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 29cd81ae29f4..801da392a20e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -54,6 +54,9 @@ #include #include "i40e_type.h" #include "i40e_prototype.h" +#ifdef I40E_FCOE +#include "i40e_fcoe.h" +#endif #include "i40e_virtchnl.h" #include "i40e_virtchnl_pf.h" #include "i40e_txrx.h" @@ -79,6 +82,10 @@ #define I40E_MAX_QUEUES_PER_TC 64 /* should be a power of 2 */ #define I40E_FDIR_RING 0 #define I40E_FDIR_RING_COUNT 32 +#ifdef I40E_FCOE +#define I40E_DEFAULT_FCOE 8 /* default number of QPs for FCoE */ +#define I40E_MINIMUM_FCOE 1 /* minimum number of QPs for FCoE */ +#endif /* I40E_FCOE */ #define I40E_MAX_AQ_BUF_SIZE 4096 #define I40E_AQ_LEN 32 #define I40E_AQ_WORK_LIMIT 16 @@ -225,6 +232,10 @@ struct i40e_pf { u16 num_vmdq_msix; /* num queue vectors per vmdq pool */ u16 num_req_vfs; /* num vfs requested for this vf */ u16 num_vf_qps; /* num queue pairs per vf */ +#ifdef I40E_FCOE + u16 num_fcoe_qps; /* num fcoe queues this pf has set up */ + u16 num_fcoe_msix; /* num queue vectors per fcoe pool */ +#endif /* I40E_FCOE */ u16 num_lan_qps; /* num lan queues this pf has set up */ u16 num_lan_msix; /* num queue vectors for the base pf vsi */ int queues_left; /* queues left unclaimed */ @@ -265,6 +276,9 @@ struct i40e_pf { #define I40E_FLAG_VMDQ_ENABLED (u64)(1 << 7) #define I40E_FLAG_FDIR_REQUIRES_REINIT (u64)(1 << 8) #define I40E_FLAG_NEED_LINK_UPDATE (u64)(1 << 9) +#ifdef I40E_FCOE +#define I40E_FLAG_FCOE_ENABLED (u64)(1 << 11) +#endif /* I40E_FCOE */ #define I40E_FLAG_IN_NETPOLL (u64)(1 << 12) #define I40E_FLAG_16BYTE_RX_DESC_ENABLED (u64)(1 << 13) #define I40E_FLAG_CLEAN_ADMINQ (u64)(1 << 14) @@ -286,6 +300,10 @@ struct i40e_pf { /* tracks features that get auto disabled by errors */ u64 auto_disable_flags; +#ifdef I40E_FCOE + struct i40e_fcoe fcoe; + +#endif /* I40E_FCOE */ bool stat_offsets_loaded; struct i40e_hw_port_stats stats; struct i40e_hw_port_stats stats_offsets; @@ -408,6 +426,11 @@ struct i40e_vsi { struct rtnl_link_stats64 net_stats_offsets; struct i40e_eth_stats eth_stats; struct i40e_eth_stats eth_stats_offsets; +#ifdef I40E_FCOE + struct i40e_fcoe_stats fcoe_stats; + struct i40e_fcoe_stats fcoe_stats_offsets; + bool fcoe_stat_offsets_loaded; +#endif u32 tx_restart; u32 tx_busy; u32 rx_buf_failed; @@ -598,6 +621,11 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, int i40e_vsi_release(struct i40e_vsi *vsi); struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type, struct i40e_vsi *start_vsi); +#ifdef I40E_FCOE +void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, + struct i40e_vsi_context *ctxt, + u8 enabled_tc, bool is_add); +#endif int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable); int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count); struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid, @@ -624,7 +652,21 @@ void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector); void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector); void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf); void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf); +#ifdef I40E_FCOE +struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( + struct net_device *netdev, + struct rtnl_link_stats64 *storage); +int i40e_set_mac(struct net_device *netdev, void *p); +void i40e_set_rx_mode(struct net_device *netdev); +#endif int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); +#ifdef I40E_FCOE +void i40e_tx_timeout(struct net_device *netdev); +int i40e_vlan_rx_add_vid(struct net_device *netdev, + __always_unused __be16 proto, u16 vid); +int i40e_vlan_rx_kill_vid(struct net_device *netdev, + __always_unused __be16 proto, u16 vid); +#endif int i40e_vsi_open(struct i40e_vsi *vsi); void i40e_vlan_stripping_disable(struct i40e_vsi *vsi); int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid); @@ -634,6 +676,26 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, bool is_vf, bool is_netdev); +#ifdef I40E_FCOE +int i40e_open(struct net_device *netdev); +int i40e_close(struct net_device *netdev); +int i40e_setup_tc(struct net_device *netdev, u8 tc); +void i40e_netpoll(struct net_device *netdev); +int i40e_fcoe_enable(struct net_device *netdev); +int i40e_fcoe_disable(struct net_device *netdev); +int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt); +u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf); +void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi); +void i40e_fcoe_vsi_setup(struct i40e_pf *pf); +int i40e_init_pf_fcoe(struct i40e_pf *pf); +int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi); +void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi); +int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring, + union i40e_rx_desc *rx_desc, + struct sk_buff *skb); +void i40e_fcoe_handle_status(struct i40e_ring *rx_ring, + union i40e_rx_desc *rx_desc, u8 prog_id); +#endif /* I40E_FCOE */ void i40e_vlan_stripping_enable(struct i40e_vsi *vsi); #ifdef CONFIG_I40E_DCB void i40e_dcbnl_flush_apps(struct i40e_pf *pf, diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index f4e502a305ff..a010584d8962 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -709,6 +709,33 @@ void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable) wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), reg_val); } +#ifdef I40E_FCOE + +/** + * i40e_get_san_mac_addr - get SAN MAC address + * @hw: pointer to the HW structure + * @mac_addr: pointer to SAN MAC address + * + * Reads the adapter's SAN MAC address from NVM + **/ +i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr) +{ + struct i40e_aqc_mac_address_read_data addrs; + i40e_status status; + u16 flags = 0; + + status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL); + if (status) + return status; + + if (flags & I40E_AQC_SAN_ADDR_VALID) + memcpy(mac_addr, &addrs.pf_san_mac, sizeof(addrs.pf_san_mac)); + else + status = I40E_ERR_INVALID_MAC_ADDR; + + return status; +} +#endif /** * i40e_get_media_type - Gets media type diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 9eaed04618a3..5a0cabeb35ed 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -697,6 +697,25 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) vsi->bw_ets_limit_credits[i], vsi->bw_ets_max_quanta[i]); } +#ifdef I40E_FCOE + if (vsi->type == I40E_VSI_FCOE) { + dev_info(&pf->pdev->dev, + " fcoe_stats: rx_packets = %llu, rx_dwords = %llu, rx_dropped = %llu\n", + vsi->fcoe_stats.rx_fcoe_packets, + vsi->fcoe_stats.rx_fcoe_dwords, + vsi->fcoe_stats.rx_fcoe_dropped); + dev_info(&pf->pdev->dev, + " fcoe_stats: tx_packets = %llu, tx_dwords = %llu\n", + vsi->fcoe_stats.tx_fcoe_packets, + vsi->fcoe_stats.tx_fcoe_dwords); + dev_info(&pf->pdev->dev, + " fcoe_stats: bad_crc = %llu, last_error = %llu\n", + vsi->fcoe_stats.fcoe_bad_fccrc, + vsi->fcoe_stats.fcoe_last_error); + dev_info(&pf->pdev->dev, " fcoe_stats: ddp_count = %llu\n", + vsi->fcoe_stats.fcoe_ddp_count); + } +#endif } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 9c93ff28d4aa..681a9e81ff51 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -155,6 +155,19 @@ static struct i40e_stats i40e_gstrings_stats[] = { I40E_PF_STAT("rx_lpi_count", stats.rx_lpi_count), }; +#ifdef I40E_FCOE +static const struct i40e_stats i40e_gstrings_fcoe_stats[] = { + I40E_VSI_STAT("fcoe_bad_fccrc", fcoe_stats.fcoe_bad_fccrc), + I40E_VSI_STAT("rx_fcoe_dropped", fcoe_stats.rx_fcoe_dropped), + I40E_VSI_STAT("rx_fcoe_packets", fcoe_stats.rx_fcoe_packets), + I40E_VSI_STAT("rx_fcoe_dwords", fcoe_stats.rx_fcoe_dwords), + I40E_VSI_STAT("fcoe_ddp_count", fcoe_stats.fcoe_ddp_count), + I40E_VSI_STAT("fcoe_last_error", fcoe_stats.fcoe_last_error), + I40E_VSI_STAT("tx_fcoe_packets", fcoe_stats.tx_fcoe_packets), + I40E_VSI_STAT("tx_fcoe_dwords", fcoe_stats.tx_fcoe_dwords), +}; + +#endif /* I40E_FCOE */ #define I40E_QUEUE_STATS_LEN(n) \ (((struct i40e_netdev_priv *)netdev_priv((n)))->vsi->num_queue_pairs \ * 2 /* Tx and Rx together */ \ @@ -162,9 +175,17 @@ static struct i40e_stats i40e_gstrings_stats[] = { #define I40E_GLOBAL_STATS_LEN ARRAY_SIZE(i40e_gstrings_stats) #define I40E_NETDEV_STATS_LEN ARRAY_SIZE(i40e_gstrings_net_stats) #define I40E_MISC_STATS_LEN ARRAY_SIZE(i40e_gstrings_misc_stats) +#ifdef I40E_FCOE +#define I40E_FCOE_STATS_LEN ARRAY_SIZE(i40e_gstrings_fcoe_stats) +#define I40E_VSI_STATS_LEN(n) (I40E_NETDEV_STATS_LEN + \ + I40E_FCOE_STATS_LEN + \ + I40E_MISC_STATS_LEN + \ + I40E_QUEUE_STATS_LEN((n))) +#else #define I40E_VSI_STATS_LEN(n) (I40E_NETDEV_STATS_LEN + \ I40E_MISC_STATS_LEN + \ I40E_QUEUE_STATS_LEN((n))) +#endif /* I40E_FCOE */ #define I40E_PFC_STATS_LEN ( \ (FIELD_SIZEOF(struct i40e_pf, stats.priority_xoff_rx) + \ FIELD_SIZEOF(struct i40e_pf, stats.priority_xon_rx) + \ @@ -1112,6 +1133,13 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, data[i++] = (i40e_gstrings_misc_stats[j].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } +#ifdef I40E_FCOE + for (j = 0; j < I40E_FCOE_STATS_LEN; j++) { + p = (char *)vsi + i40e_gstrings_fcoe_stats[j].stat_offset; + data[i++] = (i40e_gstrings_fcoe_stats[j].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } +#endif rcu_read_lock(); for (j = 0; j < vsi->num_queue_pairs; j++) { tx_ring = ACCESS_ONCE(vsi->tx_rings[j]); @@ -1193,6 +1221,13 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset, i40e_gstrings_misc_stats[i].stat_string); p += ETH_GSTRING_LEN; } +#ifdef I40E_FCOE + for (i = 0; i < I40E_FCOE_STATS_LEN; i++) { + snprintf(p, ETH_GSTRING_LEN, "%s", + i40e_gstrings_fcoe_stats[i].stat_string); + p += ETH_GSTRING_LEN; + } +#endif for (i = 0; i < vsi->num_queue_pairs; i++) { snprintf(p, ETH_GSTRING_LEN, "tx-%u.tx_packets", i); p += ETH_GSTRING_LEN; diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 8574eeefefc7..6938fc1ad877 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -1363,8 +1363,6 @@ static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb, struct i40e_vsi *vsi = np->vsi; struct i40e_ring *tx_ring = vsi->tx_rings[skb->queue_mapping]; struct i40e_tx_buffer *first; - __be16 protocol = skb->protocol; - u32 tx_flags = 0; u8 hdr_len = 0; u8 sof = 0; @@ -1384,13 +1382,8 @@ static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb, /* record the location of the first descriptor for this packet */ first = &tx_ring->tx_bi[tx_ring->next_to_use]; - if (protocol == htons(ETH_P_8021Q)) { - struct vlan_ethhdr *veth = (struct vlan_ethhdr *)eth_hdr(skb); - - protocol = veth->h_vlan_encapsulated_proto; - } /* FIP is a regular L2 traffic w/o offload */ - if (protocol == htons(ETH_P_FIP)) + if (skb->protocol == htons(ETH_P_FIP)) goto out_send; /* check sof and eof, only supports FC Class 2 or 3 */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 821fcc1adb85..6ac8487f9a51 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -269,7 +269,11 @@ static void i40e_service_event_schedule(struct i40e_pf *pf) * device is munged, not just the one netdev port, so go for the full * reset. **/ +#ifdef I40E_FCOE +void i40e_tx_timeout(struct net_device *netdev) +#else static void i40e_tx_timeout(struct net_device *netdev) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; @@ -349,9 +353,15 @@ struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi) * Returns the address of the device statistics structure. * The statistics are actually updated from the service task. **/ +#ifdef I40E_FCOE +struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( + struct net_device *netdev, + struct rtnl_link_stats64 *stats) +#else static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( struct net_device *netdev, struct rtnl_link_stats64 *stats) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_ring *tx_ring, *rx_ring; @@ -636,6 +646,55 @@ static void i40e_update_veb_stats(struct i40e_veb *veb) veb->stat_offsets_loaded = true; } +#ifdef I40E_FCOE +/** + * i40e_update_fcoe_stats - Update FCoE-specific ethernet statistics counters. + * @vsi: the VSI that is capable of doing FCoE + **/ +static void i40e_update_fcoe_stats(struct i40e_vsi *vsi) +{ + struct i40e_pf *pf = vsi->back; + struct i40e_hw *hw = &pf->hw; + struct i40e_fcoe_stats *ofs; + struct i40e_fcoe_stats *fs; /* device's eth stats */ + int idx; + + if (vsi->type != I40E_VSI_FCOE) + return; + + idx = (pf->pf_seid - I40E_BASE_PF_SEID) + I40E_FCOE_PF_STAT_OFFSET; + fs = &vsi->fcoe_stats; + ofs = &vsi->fcoe_stats_offsets; + + i40e_stat_update32(hw, I40E_GL_FCOEPRC(idx), + vsi->fcoe_stat_offsets_loaded, + &ofs->rx_fcoe_packets, &fs->rx_fcoe_packets); + i40e_stat_update48(hw, I40E_GL_FCOEDWRCH(idx), I40E_GL_FCOEDWRCL(idx), + vsi->fcoe_stat_offsets_loaded, + &ofs->rx_fcoe_dwords, &fs->rx_fcoe_dwords); + i40e_stat_update32(hw, I40E_GL_FCOERPDC(idx), + vsi->fcoe_stat_offsets_loaded, + &ofs->rx_fcoe_dropped, &fs->rx_fcoe_dropped); + i40e_stat_update32(hw, I40E_GL_FCOEPTC(idx), + vsi->fcoe_stat_offsets_loaded, + &ofs->tx_fcoe_packets, &fs->tx_fcoe_packets); + i40e_stat_update48(hw, I40E_GL_FCOEDWTCH(idx), I40E_GL_FCOEDWTCL(idx), + vsi->fcoe_stat_offsets_loaded, + &ofs->tx_fcoe_dwords, &fs->tx_fcoe_dwords); + i40e_stat_update32(hw, I40E_GL_FCOECRC(idx), + vsi->fcoe_stat_offsets_loaded, + &ofs->fcoe_bad_fccrc, &fs->fcoe_bad_fccrc); + i40e_stat_update32(hw, I40E_GL_FCOELAST(idx), + vsi->fcoe_stat_offsets_loaded, + &ofs->fcoe_last_error, &fs->fcoe_last_error); + i40e_stat_update32(hw, I40E_GL_FCOEDDPC(idx), + vsi->fcoe_stat_offsets_loaded, + &ofs->fcoe_ddp_count, &fs->fcoe_ddp_count); + + vsi->fcoe_stat_offsets_loaded = true; +} + +#endif /** * i40e_update_link_xoff_rx - Update XOFF received in link flow control mode * @pf: the corresponding PF @@ -1064,6 +1123,9 @@ void i40e_update_stats(struct i40e_vsi *vsi) i40e_update_pf_stats(pf); i40e_update_vsi_stats(vsi); +#ifdef I40E_FCOE + i40e_update_fcoe_stats(vsi); +#endif } /** @@ -1315,7 +1377,11 @@ void i40e_del_filter(struct i40e_vsi *vsi, * * Returns 0 on success, negative on failure **/ +#ifdef I40E_FCOE +int i40e_set_mac(struct net_device *netdev, void *p) +#else static int i40e_set_mac(struct net_device *netdev, void *p) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; @@ -1376,10 +1442,17 @@ static int i40e_set_mac(struct net_device *netdev, void *p) * * Setup VSI queue mapping for enabled traffic classes. **/ +#ifdef I40E_FCOE +void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, + struct i40e_vsi_context *ctxt, + u8 enabled_tc, + bool is_add) +#else static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt, u8 enabled_tc, bool is_add) +#endif { struct i40e_pf *pf = vsi->back; u16 sections = 0; @@ -1425,6 +1498,11 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, case I40E_VSI_MAIN: qcount = min_t(int, pf->rss_size, num_tc_qps); break; +#ifdef I40E_FCOE + case I40E_VSI_FCOE: + qcount = num_tc_qps; + break; +#endif case I40E_VSI_FDIR: case I40E_VSI_SRIOV: case I40E_VSI_VMDQ2: @@ -1491,7 +1569,11 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, * i40e_set_rx_mode - NDO callback to set the netdev filters * @netdev: network interface device structure **/ +#ifdef I40E_FCOE +void i40e_set_rx_mode(struct net_device *netdev) +#else static void i40e_set_rx_mode(struct net_device *netdev) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_mac_filter *f, *ftmp; @@ -2069,8 +2151,13 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) * * net_device_ops implementation for adding vlan ids **/ +#ifdef I40E_FCOE +int i40e_vlan_rx_add_vid(struct net_device *netdev, + __always_unused __be16 proto, u16 vid) +#else static int i40e_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; @@ -2103,8 +2190,13 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev, * * net_device_ops implementation for removing vlan ids **/ +#ifdef I40E_FCOE +int i40e_vlan_rx_kill_vid(struct net_device *netdev, + __always_unused __be16 proto, u16 vid) +#else static int i40e_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; @@ -2236,6 +2328,9 @@ static int i40e_vsi_setup_rx_resources(struct i40e_vsi *vsi) for (i = 0; i < vsi->num_queue_pairs && !err; i++) err = i40e_setup_rx_descriptors(vsi->rx_rings[i]); +#ifdef I40E_FCOE + i40e_fcoe_setup_ddp_resources(vsi); +#endif return err; } @@ -2255,6 +2350,9 @@ static void i40e_vsi_free_rx_resources(struct i40e_vsi *vsi) for (i = 0; i < vsi->num_queue_pairs; i++) if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc) i40e_free_rx_resources(vsi->rx_rings[i]); +#ifdef I40E_FCOE + i40e_fcoe_free_ddp_resources(vsi); +#endif } /** @@ -2296,6 +2394,9 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring) tx_ctx.qlen = ring->count; tx_ctx.fd_ena = !!(vsi->back->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED)); +#ifdef I40E_FCOE + tx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE); +#endif tx_ctx.timesync_ena = !!(vsi->back->flags & I40E_FLAG_PTP); /* FDIR VSI tx ring can still use RS bit and writebacks */ if (vsi->type != I40E_VSI_FDIR) @@ -2408,6 +2509,9 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) rx_ctx.crcstrip = 1; rx_ctx.l2tsel = 1; rx_ctx.showiv = 1; +#ifdef I40E_FCOE + rx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE); +#endif /* set the prefena field to 1 because the manual says to */ rx_ctx.prefena = 1; @@ -2492,6 +2596,17 @@ static int i40e_vsi_configure_rx(struct i40e_vsi *vsi) break; } +#ifdef I40E_FCOE + /* setup rx buffer for FCoE */ + if ((vsi->type == I40E_VSI_FCOE) && + (vsi->back->flags & I40E_FLAG_FCOE_ENABLED)) { + vsi->rx_hdr_len = 0; + vsi->rx_buf_len = I40E_RXBUFFER_3072; + vsi->max_frame = I40E_RXBUFFER_3072; + vsi->dtype = I40E_RX_DTYPE_NO_SPLIT; + } + +#endif /* I40E_FCOE */ /* round up for the chip's needs */ vsi->rx_hdr_len = ALIGN(vsi->rx_hdr_len, (1 << I40E_RXQ_CTX_HBUFF_SHIFT)); @@ -3252,7 +3367,11 @@ static int i40e_vsi_request_irq(struct i40e_vsi *vsi, char *basename) * This is used by netconsole to send skbs without having to re-enable * interrupts. It's not called while the normal interrupt routine is executing. **/ +#ifdef I40E_FCOE +void i40e_netpoll(struct net_device *netdev) +#else static void i40e_netpoll(struct net_device *netdev) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; @@ -4202,12 +4321,20 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf) continue; /* - Enable all TCs for the LAN VSI +#ifdef I40E_FCOE + * - For FCoE VSI only enable the TC configured + * as per the APP TLV +#endif * - For all others keep them at TC0 for now */ if (v == pf->lan_vsi) tc_map = i40e_pf_get_tc_map(pf); else tc_map = i40e_pf_get_default_tc(pf); +#ifdef I40E_FCOE + if (pf->vsi[v]->type == I40E_VSI_FCOE) + tc_map = i40e_get_fcoe_tc_map(pf); +#endif /* #ifdef I40E_FCOE */ ret = i40e_vsi_config_tc(pf->vsi[v], tc_map); if (ret) { @@ -4434,7 +4561,11 @@ void i40e_down(struct i40e_vsi *vsi) * @netdev: net device to configure * @tc: number of traffic classes to enable **/ +#ifdef I40E_FCOE +int i40e_setup_tc(struct net_device *netdev, u8 tc) +#else static int i40e_setup_tc(struct net_device *netdev, u8 tc) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; @@ -4499,7 +4630,11 @@ exit: * * Returns 0 on success, negative value on failure **/ +#ifdef I40E_FCOE +int i40e_open(struct net_device *netdev) +#else static int i40e_open(struct net_device *netdev) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; @@ -4635,7 +4770,11 @@ static void i40e_fdir_filter_exit(struct i40e_pf *pf) * * Returns 0, this is not allowed to fail **/ +#ifdef I40E_FCOE +int i40e_close(struct net_device *netdev) +#else static int i40e_close(struct net_device *netdev) +#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; @@ -5050,6 +5189,9 @@ static void i40e_vsi_link_event(struct i40e_vsi *vsi, bool link_up) switch (vsi->type) { case I40E_VSI_MAIN: +#ifdef I40E_FCOE + case I40E_VSI_FCOE: +#endif if (!vsi->netdev || !vsi->netdev_registered) break; @@ -5768,7 +5910,12 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) goto end_core_reset; } #endif /* CONFIG_I40E_DCB */ +#ifdef I40E_FCOE + ret = i40e_init_pf_fcoe(pf); + if (ret) + dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", ret); +#endif /* do basic switch setup */ ret = i40e_setup_pf_switch(pf, reinit); if (ret) @@ -6107,6 +6254,15 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi) I40E_REQ_DESCRIPTOR_MULTIPLE); break; +#ifdef I40E_FCOE + case I40E_VSI_FCOE: + vsi->alloc_queue_pairs = pf->num_fcoe_qps; + vsi->num_desc = ALIGN(I40E_DEFAULT_NUM_DESCRIPTORS, + I40E_REQ_DESCRIPTOR_MULTIPLE); + vsi->num_q_vectors = pf->num_fcoe_msix; + break; + +#endif /* I40E_FCOE */ default: WARN_ON(1); return -ENODATA; @@ -6418,6 +6574,9 @@ static int i40e_init_msix(struct i40e_pf *pf) * is governed by number of cpus in the system. * - assumes symmetric Tx/Rx pairing * - The number of VMDq pairs +#ifdef I40E_FCOE + * - The number of FCOE qps. +#endif * Once we count this up, try the request. * * If we can't get what we want, we'll simplify to nearly nothing @@ -6430,6 +6589,13 @@ static int i40e_init_msix(struct i40e_pf *pf) if (pf->flags & I40E_FLAG_FD_SB_ENABLED) v_budget++; +#ifdef I40E_FCOE + if (pf->flags & I40E_FLAG_FCOE_ENABLED) { + pf->num_fcoe_msix = pf->num_fcoe_qps; + v_budget += pf->num_fcoe_msix; + } + +#endif /* Scale down if necessary, and the rings will share vectors */ v_budget = min_t(int, v_budget, hw->func_caps.num_msix_vectors); @@ -6448,6 +6614,10 @@ static int i40e_init_msix(struct i40e_pf *pf) * of these features based on the policy and at the end disable * the features that did not get any vectors. */ +#ifdef I40E_FCOE + pf->num_fcoe_qps = 0; + pf->num_fcoe_msix = 0; +#endif pf->num_vmdq_msix = 0; } @@ -6478,9 +6648,24 @@ static int i40e_init_msix(struct i40e_pf *pf) pf->num_lan_msix = 1; break; case 3: +#ifdef I40E_FCOE + /* give one vector to FCoE */ + if (pf->flags & I40E_FLAG_FCOE_ENABLED) { + pf->num_lan_msix = 1; + pf->num_fcoe_msix = 1; + } +#else pf->num_lan_msix = 2; +#endif break; default: +#ifdef I40E_FCOE + /* give one vector to FCoE */ + if (pf->flags & I40E_FLAG_FCOE_ENABLED) { + pf->num_fcoe_msix = 1; + vec--; + } +#endif pf->num_lan_msix = min_t(int, (vec / 2), pf->num_lan_qps); pf->num_vmdq_vsis = min_t(int, (vec - pf->num_lan_msix), @@ -6494,6 +6679,13 @@ static int i40e_init_msix(struct i40e_pf *pf) dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n"); pf->flags &= ~I40E_FLAG_VMDQ_ENABLED; } +#ifdef I40E_FCOE + + if ((pf->flags & I40E_FLAG_FCOE_ENABLED) && (pf->num_fcoe_msix == 0)) { + dev_info(&pf->pdev->dev, "FCOE disabled, not enough MSI-X vectors\n"); + pf->flags &= ~I40E_FLAG_FCOE_ENABLED; + } +#endif return err; } @@ -6577,6 +6769,9 @@ static void i40e_init_interrupt_scheme(struct i40e_pf *pf) err = i40e_init_msix(pf); if (err) { pf->flags &= ~(I40E_FLAG_MSIX_ENABLED | +#ifdef I40E_FCOE + I40E_FLAG_FCOE_ENABLED | +#endif I40E_FLAG_RSS_ENABLED | I40E_FLAG_DCB_CAPABLE | I40E_FLAG_SRIOV_ENABLED | @@ -6814,6 +7009,12 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->num_vmdq_qps = I40E_DEFAULT_QUEUES_PER_VMDQ; } +#ifdef I40E_FCOE + err = i40e_init_pf_fcoe(pf); + if (err) + dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", err); + +#endif /* I40E_FCOE */ #ifdef CONFIG_PCI_IOV if (pf->hw.func_caps.num_vfs) { pf->num_vf_qps = I40E_DEFAULT_QUEUES_PER_VF; @@ -7141,6 +7342,10 @@ static const struct net_device_ops i40e_netdev_ops = { .ndo_poll_controller = i40e_netpoll, #endif .ndo_setup_tc = i40e_setup_tc, +#ifdef I40E_FCOE + .ndo_fcoe_enable = i40e_fcoe_enable, + .ndo_fcoe_disable = i40e_fcoe_disable, +#endif .ndo_set_features = i40e_set_features, .ndo_set_vf_mac = i40e_ndo_set_vf_mac, .ndo_set_vf_vlan = i40e_ndo_set_vf_port_vlan, @@ -7249,6 +7454,9 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) netdev->netdev_ops = &i40e_netdev_ops; netdev->watchdog_timeo = 5 * HZ; i40e_set_ethtool_ops(netdev); +#ifdef I40E_FCOE + i40e_fcoe_config_netdev(netdev, vsi); +#endif return 0; } @@ -7402,6 +7610,16 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, true); break; +#ifdef I40E_FCOE + case I40E_VSI_FCOE: + ret = i40e_fcoe_vsi_init(vsi, &ctxt); + if (ret) { + dev_info(&pf->pdev->dev, "failed to initialize FCoE VSI\n"); + return ret; + } + break; + +#endif /* I40E_FCOE */ default: return -ENODEV; } @@ -7760,6 +7978,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, /* setup the netdev if needed */ case I40E_VSI_MAIN: case I40E_VSI_VMDQ2: + case I40E_VSI_FCOE: ret = i40e_config_netdev(vsi); if (ret) goto err_netdev; @@ -8378,6 +8597,9 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) int queues_left; pf->num_lan_qps = 0; +#ifdef I40E_FCOE + pf->num_fcoe_qps = 0; +#endif /* Find the max queues to be put into basic use. We'll always be * using TC0, whether or not DCB is running, and TC0 will get the @@ -8393,6 +8615,9 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) /* make sure all the fancies are disabled */ pf->flags &= ~(I40E_FLAG_RSS_ENABLED | +#ifdef I40E_FCOE + I40E_FLAG_FCOE_ENABLED | +#endif I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED | I40E_FLAG_DCB_CAPABLE | @@ -8407,6 +8632,9 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) queues_left -= pf->num_lan_qps; pf->flags &= ~(I40E_FLAG_RSS_ENABLED | +#ifdef I40E_FCOE + I40E_FLAG_FCOE_ENABLED | +#endif I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED | I40E_FLAG_DCB_ENABLED | @@ -8422,6 +8650,22 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) queues_left -= pf->num_lan_qps; } +#ifdef I40E_FCOE + if (pf->flags & I40E_FLAG_FCOE_ENABLED) { + if (I40E_DEFAULT_FCOE <= queues_left) { + pf->num_fcoe_qps = I40E_DEFAULT_FCOE; + } else if (I40E_MINIMUM_FCOE <= queues_left) { + pf->num_fcoe_qps = I40E_MINIMUM_FCOE; + } else { + pf->num_fcoe_qps = 0; + pf->flags &= ~I40E_FLAG_FCOE_ENABLED; + dev_info(&pf->pdev->dev, "not enough queues for FCoE. FCoE feature will be disabled\n"); + } + + queues_left -= pf->num_fcoe_qps; + } + +#endif if (pf->flags & I40E_FLAG_FD_SB_ENABLED) { if (queues_left > 1) { queues_left -= 1; /* save 1 queue for FD */ @@ -8446,6 +8690,9 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) } pf->queues_left = queues_left; +#ifdef I40E_FCOE + dev_info(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps); +#endif } /** @@ -8512,6 +8759,10 @@ static void i40e_print_features(struct i40e_pf *pf) buf += sprintf(buf, "DCB "); if (pf->flags & I40E_FLAG_PTP) buf += sprintf(buf, "PTP "); +#ifdef I40E_FCOE + if (pf->flags & I40E_FLAG_FCOE_ENABLED) + buf += sprintf(buf, "FCOE "); +#endif BUG_ON(buf > (string + INFO_STRING_LEN)); dev_info(&pf->pdev->dev, "%s\n", string); @@ -8699,6 +8950,18 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_get_port_mac_addr(hw, hw->mac.port_addr); if (is_valid_ether_addr(hw->mac.port_addr)) pf->flags |= I40E_FLAG_PORT_ID_VALID; +#ifdef I40E_FCOE + err = i40e_get_san_mac_addr(hw, hw->mac.san_addr); + if (err) + dev_info(&pdev->dev, + "(non-fatal) SAN MAC retrieval failed: %d\n", err); + if (!is_valid_ether_addr(hw->mac.san_addr)) { + dev_warn(&pdev->dev, "invalid SAN MAC address %pM, falling back to LAN MAC\n", + hw->mac.san_addr); + ether_addr_copy(hw->mac.san_addr, hw->mac.addr); + } + dev_info(&pf->pdev->dev, "SAN MAC: %pM\n", hw->mac.san_addr); +#endif /* I40E_FCOE */ pci_set_drvdata(pdev, pf); pci_save_state(pdev); @@ -8815,6 +9078,11 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mod_timer(&pf->service_timer, round_jiffies(jiffies + pf->service_timer_period)); +#ifdef I40E_FCOE + /* create FCoE interface */ + i40e_fcoe_vsi_setup(pf); + +#endif /* Get the negotiated link width and speed from PCI config space */ pcie_capability_read_word(pf->pdev, PCI_EXP_LNKSTA, &link_status); diff --git a/drivers/net/ethernet/intel/i40e/i40e_osdep.h b/drivers/net/ethernet/intel/i40e/i40e_osdep.h index ecd0f0b663c9..045b5c4b98b3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_osdep.h +++ b/drivers/net/ethernet/intel/i40e/i40e_osdep.h @@ -78,4 +78,7 @@ do { \ } while (0) typedef enum i40e_status_code i40e_status; +#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) +#define I40E_FCOE +#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */ #endif /* _I40E_OSDEP_H_ */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index a91d7e1a5b5b..8cd4390a2842 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -237,6 +237,9 @@ i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr); i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr); i40e_status i40e_validate_mac_addr(u8 *mac_addr); void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable); +#ifdef I40E_FCOE +i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr); +#endif /* prototype for functions used for NVM access */ i40e_status i40e_init_nvm(struct i40e_hw *hw); i40e_status i40e_acquire_nvm(struct i40e_hw *hw, diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index d26d6836689d..a51aa37b7b5a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -896,6 +896,11 @@ static void i40e_clean_programming_status(struct i40e_ring *rx_ring, if (id == I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS) i40e_fd_handle_status(rx_ring, rx_desc, id); +#ifdef I40E_FCOE + else if ((id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) || + (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS)) + i40e_fcoe_handle_status(rx_ring, rx_desc, id); +#endif } /** @@ -1489,6 +1494,12 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) vlan_tag = rx_status & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT) ? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0; +#ifdef I40E_FCOE + if (!i40e_fcoe_handle_offload(rx_ring, rx_desc, skb)) { + dev_kfree_skb_any(skb); + goto next_desc; + } +#endif i40e_receive_skb(rx_ring, skb, vlan_tag); rx_ring->netdev->last_rx = jiffies; @@ -1719,9 +1730,15 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, * Returns error code indicate the frame should be dropped upon error and the * otherwise returns 0 to indicate the flags has been set properly. **/ +#ifdef I40E_FCOE +int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, + struct i40e_ring *tx_ring, + u32 *flags) +#else static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, struct i40e_ring *tx_ring, u32 *flags) +#endif { __be16 protocol = skb->protocol; u32 tx_flags = 0; @@ -1743,9 +1760,8 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, } /* Insert 802.1p priority into VLAN header */ - if ((tx_ring->vsi->back->flags & I40E_FLAG_DCB_ENABLED) && - ((tx_flags & (I40E_TX_FLAGS_HW_VLAN | I40E_TX_FLAGS_SW_VLAN)) || - (skb->priority != TC_PRIO_CONTROL))) { + if ((tx_flags & (I40E_TX_FLAGS_HW_VLAN | I40E_TX_FLAGS_SW_VLAN)) || + (skb->priority != TC_PRIO_CONTROL)) { tx_flags &= ~I40E_TX_FLAGS_VLAN_PRIO_MASK; tx_flags |= (skb->priority & 0x7) << I40E_TX_FLAGS_VLAN_PRIO_SHIFT; @@ -2018,9 +2034,15 @@ static void i40e_create_tx_ctx(struct i40e_ring *tx_ring, * @td_cmd: the command field in the descriptor * @td_offset: offset for checksum or crc **/ +#ifdef I40E_FCOE +void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, + struct i40e_tx_buffer *first, u32 tx_flags, + const u8 hdr_len, u32 td_cmd, u32 td_offset) +#else static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, struct i40e_tx_buffer *first, u32 tx_flags, const u8 hdr_len, u32 td_cmd, u32 td_offset) +#endif { unsigned int data_len = skb->data_len; unsigned int size = skb_headlen(skb); @@ -2197,7 +2219,11 @@ static inline int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size) * * Returns 0 if stop is not needed **/ +#ifdef I40E_FCOE +int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size) +#else static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size) +#endif { if (likely(I40E_DESC_UNUSED(tx_ring) >= size)) return 0; @@ -2213,8 +2239,13 @@ static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size) * there is not enough descriptors available in this ring since we need at least * one descriptor. **/ +#ifdef I40E_FCOE +int i40e_xmit_descriptor_count(struct sk_buff *skb, + struct i40e_ring *tx_ring) +#else static int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring) +#endif { unsigned int f; int count = 0; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index c1c356984b17..73f4fa425697 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -290,4 +290,13 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring); void i40e_free_tx_resources(struct i40e_ring *tx_ring); void i40e_free_rx_resources(struct i40e_ring *rx_ring); int i40e_napi_poll(struct napi_struct *napi, int budget); +#ifdef I40E_FCOE +void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, + struct i40e_tx_buffer *first, u32 tx_flags, + const u8 hdr_len, u32 td_cmd, u32 td_offset); +int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size); +int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring); +int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, + struct i40e_ring *tx_ring, u32 *flags); +#endif #endif /* _I40E_TXRX_H_ */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 8bb9049191cb..ce04d9093db6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1051,6 +1051,25 @@ struct i40e_eth_stats { u64 tx_errors; /* tepc */ }; +#ifdef I40E_FCOE +/* Statistics collected per function for FCoE */ +struct i40e_fcoe_stats { + u64 rx_fcoe_packets; /* fcoeprc */ + u64 rx_fcoe_dwords; /* focedwrc */ + u64 rx_fcoe_dropped; /* fcoerpdc */ + u64 tx_fcoe_packets; /* fcoeptc */ + u64 tx_fcoe_dwords; /* focedwtc */ + u64 fcoe_bad_fccrc; /* fcoecrc */ + u64 fcoe_last_error; /* fcoelast */ + u64 fcoe_ddp_count; /* fcoeddpc */ +}; + +/* offset to per function FCoE statistics block */ +#define I40E_FCOE_VF_STAT_OFFSET 0 +#define I40E_FCOE_PF_STAT_OFFSET 128 +#define I40E_FCOE_STAT_MAX (I40E_FCOE_PF_STAT_OFFSET + I40E_MAX_PF) + +#endif /* Statistics collected by the MAC */ struct i40e_hw_port_stats { /* eth stats collected by the port */ @@ -1131,6 +1150,125 @@ struct i40e_hw_port_stats { #define I40E_SRRD_SRCTL_ATTEMPTS 100000 +#ifdef I40E_FCOE +/* FCoE Tx context descriptor - Use the i40e_tx_context_desc struct */ + +enum i40E_fcoe_tx_ctx_desc_cmd_bits { + I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND = 0x00, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2 = 0x01, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3 = 0x05, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_OPCODE_ETSO_FC_CLASS2 = 0x02, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_OPCODE_ETSO_FC_CLASS3 = 0x06, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_FC_CLASS2 = 0x03, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_FC_CLASS3 = 0x07, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL = 0x08, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_CTX_INVL = 0x09, /* 4 BITS */ + I40E_FCOE_TX_CTX_DESC_RELOFF = 0x10, + I40E_FCOE_TX_CTX_DESC_CLRSEQ = 0x20, + I40E_FCOE_TX_CTX_DESC_DIFENA = 0x40, + I40E_FCOE_TX_CTX_DESC_IL2TAG2 = 0x80 +}; + +/* FCoE DDP Context descriptor */ +struct i40e_fcoe_ddp_context_desc { + __le64 rsvd; + __le64 type_cmd_foff_lsize; +}; + +#define I40E_FCOE_DDP_CTX_QW1_DTYPE_SHIFT 0 +#define I40E_FCOE_DDP_CTX_QW1_DTYPE_MASK (0xFULL << \ + I40E_FCOE_DDP_CTX_QW1_DTYPE_SHIFT) + +#define I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT 4 +#define I40E_FCOE_DDP_CTX_QW1_CMD_MASK (0xFULL << \ + I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT) + +enum i40e_fcoe_ddp_ctx_desc_cmd_bits { + I40E_FCOE_DDP_CTX_DESC_BSIZE_512B = 0x00, /* 2 BITS */ + I40E_FCOE_DDP_CTX_DESC_BSIZE_4K = 0x01, /* 2 BITS */ + I40E_FCOE_DDP_CTX_DESC_BSIZE_8K = 0x02, /* 2 BITS */ + I40E_FCOE_DDP_CTX_DESC_BSIZE_16K = 0x03, /* 2 BITS */ + I40E_FCOE_DDP_CTX_DESC_DIFENA = 0x04, /* 1 BIT */ + I40E_FCOE_DDP_CTX_DESC_LASTSEQH = 0x08, /* 1 BIT */ +}; + +#define I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT 16 +#define I40E_FCOE_DDP_CTX_QW1_FOFF_MASK (0x3FFFULL << \ + I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT) + +#define I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT 32 +#define I40E_FCOE_DDP_CTX_QW1_LSIZE_MASK (0x3FFFULL << \ + I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT) + +/* FCoE DDP/DWO Queue Context descriptor */ +struct i40e_fcoe_queue_context_desc { + __le64 dmaindx_fbase; /* 0:11 DMAINDX, 12:63 FBASE */ + __le64 flen_tph; /* 0:12 FLEN, 13:15 TPH */ +}; + +#define I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_SHIFT 0 +#define I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_MASK (0xFFFULL << \ + I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_SHIFT) + +#define I40E_FCOE_QUEUE_CTX_QW0_FBASE_SHIFT 12 +#define I40E_FCOE_QUEUE_CTX_QW0_FBASE_MASK (0xFFFFFFFFFFFFFULL << \ + I40E_FCOE_QUEUE_CTX_QW0_FBASE_SHIFT) + +#define I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT 0 +#define I40E_FCOE_QUEUE_CTX_QW1_FLEN_MASK (0x1FFFULL << \ + I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT) + +#define I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT 13 +#define I40E_FCOE_QUEUE_CTX_QW1_TPH_MASK (0x7ULL << \ + I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT) + +enum i40e_fcoe_queue_ctx_desc_tph_bits { + I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC = 0x1, + I40E_FCOE_QUEUE_CTX_DESC_TPHDATA = 0x2 +}; + +#define I40E_FCOE_QUEUE_CTX_QW1_RECIPE_SHIFT 30 +#define I40E_FCOE_QUEUE_CTX_QW1_RECIPE_MASK (0x3ULL << \ + I40E_FCOE_QUEUE_CTX_QW1_RECIPE_SHIFT) + +/* FCoE DDP/DWO Filter Context descriptor */ +struct i40e_fcoe_filter_context_desc { + __le32 param; + __le16 seqn; + + /* 48:51(0:3) RSVD, 52:63(4:15) DMAINDX */ + __le16 rsvd_dmaindx; + + /* 0:7 FLAGS, 8:52 RSVD, 53:63 LANQ */ + __le64 flags_rsvd_lanq; +}; + +#define I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT 4 +#define I40E_FCOE_FILTER_CTX_QW0_DMAINDX_MASK (0xFFF << \ + I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT) + +enum i40e_fcoe_filter_ctx_desc_flags_bits { + I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP = 0x00, + I40E_FCOE_FILTER_CTX_DESC_CTYP_DWO = 0x01, + I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT = 0x00, + I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP = 0x02, + I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2 = 0x00, + I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3 = 0x04 +}; + +#define I40E_FCOE_FILTER_CTX_QW1_FLAGS_SHIFT 0 +#define I40E_FCOE_FILTER_CTX_QW1_FLAGS_MASK (0xFFULL << \ + I40E_FCOE_FILTER_CTX_QW1_FLAGS_SHIFT) + +#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT 8 +#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_MASK (0x3FULL << \ + I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT) + +#define I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT 53 +#define I40E_FCOE_FILTER_CTX_QW1_LANQINDX_MASK (0x7FFULL << \ + I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT) + +#endif /* I40E_FCOE */ enum i40e_switch_element_types { I40E_SWITCH_ELEMENT_TYPE_MAC = 1, I40E_SWITCH_ELEMENT_TYPE_PF = 2, -- cgit v1.2.3