i40e: Adds FCoE related code to i40e core driver
authorVasu Dev <vasu.dev@intel.com>
Fri, 1 Aug 2014 20:27:03 +0000 (13:27 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 3 Aug 2014 02:41:13 +0000 (19:41 -0700)
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 <vasu.dev@intel.com>
Tested-by: Jack Morgan<jack.morgan@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_fcoe.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_osdep.h
drivers/net/ethernet/intel/i40e/i40e_prototype.h
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40e/i40e_txrx.h
drivers/net/ethernet/intel/i40e/i40e_type.h

index 29cd81ae29f43e0abd801084b7f10b0f7d6a8871..801da392a20e23dc84e176579720f0a106695776 100644 (file)
@@ -54,6 +54,9 @@
 #include <linux/ptp_clock_kernel.h>
 #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"
 #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,
index f4e502a305ffa5791cae9d9bc0826bbcf8af3748..a010584d896254e3e1751913e11ae87152a02364 100644 (file)
@@ -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
index 9eaed04618a368fd26a9274dd97c178964421f87..5a0cabeb35ed7f21e37a523a1418981fb23d0836 100644 (file)
@@ -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
 }
 
 /**
index 9c93ff28d4aab24ab8062561fe34e6fb38db154f..681a9e81ff512aa874406d6e549485815c29a55d 100644 (file)
@@ -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;
index 8574eeefefc726ef5de68edd7c57bd80f93f5b3d..6938fc1ad877bc08bf3b67ea3ae3e7f79ac0943e 100644 (file)
@@ -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 */
index 821fcc1adb85384f305019d0c93bcefd7ff3792e..6ac8487f9a51160ebb869564d1a2f43170f3bffb 100644 (file)
@@ -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);
 
index ecd0f0b663c97a3871edfb0c7e0bb738c02cf688..045b5c4b98b38ba74ef68104828351f2a8fdc67c 100644 (file)
@@ -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_ */
index a91d7e1a5b5b9b41799cc29a489072042f23949a..8cd4390a28427c18cfc7d529fca5d9ef73071ae6 100644 (file)
@@ -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,
index d26d6836689da4d3febaf686d76fe1fd58bb6e02..a51aa37b7b5af10a5204c1ef8329ce9229b1ce57 100644 (file)
@@ -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;
index c1c356984b170cbefa5763202c60a0727cb870a1..73f4fa4256974ed68479e5f6bebd44ee5d50d6bc 100644 (file)
@@ -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_ */
index 8bb9049191cb2f363fc0ec04f792865edcd78061..ce04d9093db63b99c46a0e055525a347a5f2d48a 100644 (file)
@@ -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,