]> git.openfabrics.org - ~emulex/compat-rdma.git/commitdiff
linux-next-cherry-picks: Misc fixes for Chelsio T4/T5
authorKumar Sanghvi <kumaras@chelsio.com>
Tue, 24 Dec 2013 18:42:01 +0000 (00:12 +0530)
committerVipul Pandya <vipul@chelsio.com>
Thu, 26 Dec 2013 10:08:03 +0000 (02:08 -0800)
This patch brings-in the following linux-next commits:

d14807d cxgb4: Much cleaner implementation of is_t4()/is_t5()
16e4762 cxgb4: Add new scheme to update T4/T5 firmware
b6f8eae cxgb4: Reserve stid 0 for T4/T5 adapters
7c89e55 cxgb4: Include TCP as protocol when creating server filters
470c60c cxgb4: Assign filter server TIDs properly
15f63b7 cxgb4: Account for stid entries properly in case of IPv6
dcf7b6f cxgb4: Add API to correctly calculate tuple fields
a4ea025 RDMA/cxgb4: Calculate the filter server TID properly
8c04469 RDMA/cxgb4: Server filters are supported only for IPv4
41b4f86 RDMA/cxgb4: Use cxgb4_select_ntuple to correctly calculate ntuple fields

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
linux-next-cherry-picks/0001-cxgb4-Much-cleaner-implementation-of-is_t4-is_t5.patch [new file with mode: 0644]
linux-next-cherry-picks/0002-cxgb4-Add-new-scheme-to-update-T4-T5-firmware.patch [new file with mode: 0644]
linux-next-cherry-picks/0003-cxgb4-Reserve-stid-0-for-T4-T5-adapters.patch [new file with mode: 0644]
linux-next-cherry-picks/0004-cxgb4-Include-TCP-as-protocol-when-creating-server-f.patch [new file with mode: 0644]
linux-next-cherry-picks/0005-cxgb4-Assign-filter-server-TIDS-Account-for-stid.patch [new file with mode: 0644]
linux-next-cherry-picks/0006-cxgb4-Add-API-to-correctly-calculate-tuple-fields.patch [new file with mode: 0644]
linux-next-cherry-picks/0007-RDMA-cxgb4-Calculate-the-filter-server-TID-properly.patch [new file with mode: 0644]
linux-next-cherry-picks/0008-RDMA-cxgb4-Server-filters-are-supported-only-for-IPv.patch [new file with mode: 0644]
linux-next-cherry-picks/0009-RDMA-cxgb4-Use-cxgb4_select_ntuple-to-correctly-calc.patch [new file with mode: 0644]

diff --git a/linux-next-cherry-picks/0001-cxgb4-Much-cleaner-implementation-of-is_t4-is_t5.patch b/linux-next-cherry-picks/0001-cxgb4-Much-cleaner-implementation-of-is_t4-is_t5.patch
new file mode 100644 (file)
index 0000000..89938d1
--- /dev/null
@@ -0,0 +1,524 @@
+From d14807dd8e7eaa41a8fee5fc3acbdaf2a0258b76 Mon Sep 17 00:00:00 2001
+From: Hariprasad Shenai <hariprasad@chelsio.com>
+Date: Tue, 3 Dec 2013 17:05:56 +0530
+Subject: [PATCH] cxgb4: Much cleaner implementation of is_t4()/is_t5()
+
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4.h      |   45 ++++++++++++-----------
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |   40 ++++++++++----------
+ drivers/net/ethernet/chelsio/cxgb4/sge.c        |   12 +++---
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c      |   41 ++++++++++-----------
+ drivers/net/ethernet/chelsio/cxgb4/t4_regs.h    |    5 +++
+ 5 files changed, 73 insertions(+), 70 deletions(-)
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+index ecd2fb3..9710a16 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+@@ -240,6 +240,26 @@ struct pci_params {
+       unsigned char width;
+ };
++#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
++#define CHELSIO_CHIP_FPGA          0x100
++#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
++#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
++
++#define CHELSIO_T4            0x4
++#define CHELSIO_T5            0x5
++
++enum chip_type {
++      T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
++      T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
++      T4_FIRST_REV    = T4_A1,
++      T4_LAST_REV     = T4_A2,
++
++      T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
++      T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
++      T5_FIRST_REV    = T5_A0,
++      T5_LAST_REV     = T5_A1,
++};
++
+ struct adapter_params {
+       struct tp_params  tp;
+       struct vpd_params vpd;
+@@ -259,7 +279,7 @@ struct adapter_params {
+       unsigned char nports;             /* # of ethernet ports */
+       unsigned char portvec;
+-      unsigned char rev;                /* chip revision */
++      enum chip_type chip;               /* chip code */
+       unsigned char offload;
+       unsigned char bypass;
+@@ -512,25 +532,6 @@ struct sge {
+ struct l2t_data;
+-#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
+-#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
+-#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
+-
+-#define CHELSIO_T4            0x4
+-#define CHELSIO_T5            0x5
+-
+-enum chip_type {
+-      T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
+-      T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+-      T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+-      T4_FIRST_REV    = T4_A1,
+-      T4_LAST_REV     = T4_A3,
+-
+-      T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+-      T5_FIRST_REV    = T5_A1,
+-      T5_LAST_REV     = T5_A1,
+-};
+-
+ #ifdef CONFIG_PCI_IOV
+ /* T4 supports SRIOV on PF0-3 and T5 on PF0-7.  However, the Serial
+@@ -715,12 +716,12 @@ enum {
+ static inline int is_t5(enum chip_type chip)
+ {
+-      return (chip >= T5_FIRST_REV && chip <= T5_LAST_REV);
++      return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5;
+ }
+ static inline int is_t4(enum chip_type chip)
+ {
+-      return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
++      return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
+ }
+ static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index 8b929ee..35933cd 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -1083,7 +1083,7 @@ static int upgrade_fw(struct adapter *adap)
+       struct device *dev = adap->pdev_dev;
+       char *fw_file_name;
+-      switch (CHELSIO_CHIP_VERSION(adap->chip)) {
++      switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
+       case CHELSIO_T4:
+               fw_file_name = FW_FNAME;
+               exp_major = FW_VERSION_MAJOR;
+@@ -1093,7 +1093,7 @@ static int upgrade_fw(struct adapter *adap)
+               exp_major = FW_VERSION_MAJOR_T5;
+               break;
+       default:
+-              dev_err(dev, "Unsupported chip type, %x\n", adap->chip);
++              dev_err(dev, "Unsupported chip type, %x\n", adap->params.chip);
+               return -EINVAL;
+       }
+@@ -1415,7 +1415,7 @@ static int get_sset_count(struct net_device *dev, int sset)
+ static int get_regs_len(struct net_device *dev)
+ {
+       struct adapter *adap = netdev2adap(dev);
+-      if (is_t4(adap->chip))
++      if (is_t4(adap->params.chip))
+               return T4_REGMAP_SIZE;
+       else
+               return T5_REGMAP_SIZE;
+@@ -1499,7 +1499,7 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
+       data += sizeof(struct port_stats) / sizeof(u64);
+       collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
+       data += sizeof(struct queue_port_stats) / sizeof(u64);
+-      if (!is_t4(adapter->chip)) {
++      if (!is_t4(adapter->params.chip)) {
+               t4_write_reg(adapter, SGE_STAT_CFG, STATSOURCE_T5(7));
+               val1 = t4_read_reg(adapter, SGE_STAT_TOTAL);
+               val2 = t4_read_reg(adapter, SGE_STAT_MATCH);
+@@ -1521,8 +1521,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
+  */
+ static inline unsigned int mk_adap_vers(const struct adapter *ap)
+ {
+-      return CHELSIO_CHIP_VERSION(ap->chip) |
+-              (CHELSIO_CHIP_RELEASE(ap->chip) << 10) | (1 << 16);
++      return CHELSIO_CHIP_VERSION(ap->params.chip) |
++              (CHELSIO_CHIP_RELEASE(ap->params.chip) << 10) | (1 << 16);
+ }
+ static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start,
+@@ -2189,7 +2189,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
+       static const unsigned int *reg_ranges;
+       int arr_size = 0, buf_size = 0;
+-      if (is_t4(ap->chip)) {
++      if (is_t4(ap->params.chip)) {
+               reg_ranges = &t4_reg_ranges[0];
+               arr_size = ARRAY_SIZE(t4_reg_ranges);
+               buf_size = T4_REGMAP_SIZE;
+@@ -2967,7 +2967,7 @@ static int setup_debugfs(struct adapter *adap)
+               size = t4_read_reg(adap, MA_EDRAM1_BAR);
+               add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size));
+       }
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               size = t4_read_reg(adap, MA_EXT_MEMORY_BAR);
+               if (i & EXT_MEM_ENABLE)
+                       add_debugfs_mem(adap, "mc", MEM_MC,
+@@ -3419,7 +3419,7 @@ unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
+       v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+       v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               lp_count = G_LP_COUNT(v1);
+               hp_count = G_HP_COUNT(v1);
+       } else {
+@@ -3588,7 +3588,7 @@ static void drain_db_fifo(struct adapter *adap, int usecs)
+       do {
+               v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+               v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
+-              if (is_t4(adap->chip)) {
++              if (is_t4(adap->params.chip)) {
+                       lp_count = G_LP_COUNT(v1);
+                       hp_count = G_HP_COUNT(v1);
+               } else {
+@@ -3708,7 +3708,7 @@ static void process_db_drop(struct work_struct *work)
+       adap = container_of(work, struct adapter, db_drop_task);
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               disable_dbs(adap);
+               notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
+               drain_db_fifo(adap, 1);
+@@ -3753,7 +3753,7 @@ static void process_db_drop(struct work_struct *work)
+ void t4_db_full(struct adapter *adap)
+ {
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               t4_set_reg_field(adap, SGE_INT_ENABLE3,
+                                DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
+               queue_work(workq, &adap->db_full_task);
+@@ -3762,7 +3762,7 @@ void t4_db_full(struct adapter *adap)
+ void t4_db_dropped(struct adapter *adap)
+ {
+-      if (is_t4(adap->chip))
++      if (is_t4(adap->params.chip))
+               queue_work(workq, &adap->db_drop_task);
+ }
+@@ -3789,7 +3789,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
+       lli.nchan = adap->params.nports;
+       lli.nports = adap->params.nports;
+       lli.wr_cred = adap->params.ofldq_wr_cred;
+-      lli.adapter_type = adap->params.rev;
++      lli.adapter_type = adap->params.chip;
+       lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
+       lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
+                       t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
+@@ -4483,7 +4483,7 @@ static void setup_memwin(struct adapter *adap)
+       u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
+       bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               mem_win0_base = bar0 + MEMWIN0_BASE;
+               mem_win1_base = bar0 + MEMWIN1_BASE;
+               mem_win2_base = bar0 + MEMWIN2_BASE;
+@@ -4686,7 +4686,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
+        * then use that.  Otherwise, use the configuration file stored
+        * in the adapter flash ...
+        */
+-      switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
++      switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
+       case CHELSIO_T4:
+               fw_config_file = FW_CFNAME;
+               break;
+@@ -5787,7 +5787,7 @@ static void print_port_info(const struct net_device *dev)
+       netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
+                   adap->params.vpd.id,
+-                  CHELSIO_CHIP_RELEASE(adap->params.rev), buf,
++                  CHELSIO_CHIP_RELEASE(adap->params.chip), buf,
+                   is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
+                   (adap->flags & USING_MSIX) ? " MSI-X" :
+                   (adap->flags & USING_MSI) ? " MSI" : "");
+@@ -5910,7 +5910,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+       if (err)
+               goto out_unmap_bar0;
+-      if (!is_t4(adapter->chip)) {
++      if (!is_t4(adapter->params.chip)) {
+               s_qpp = QUEUESPERPAGEPF1 * adapter->fn;
+               qpp = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adapter,
+                     SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
+@@ -6064,7 +6064,7 @@ sriov:
+  out_free_dev:
+       free_some_resources(adapter);
+  out_unmap_bar:
+-      if (!is_t4(adapter->chip))
++      if (!is_t4(adapter->params.chip))
+               iounmap(adapter->bar2);
+  out_unmap_bar0:
+       iounmap(adapter->regs);
+@@ -6116,7 +6116,7 @@ static void remove_one(struct pci_dev *pdev)
+               free_some_resources(adapter);
+               iounmap(adapter->regs);
+-              if (!is_t4(adapter->chip))
++              if (!is_t4(adapter->params.chip))
+                       iounmap(adapter->bar2);
+               kfree(adapter);
+               pci_disable_pcie_error_reporting(pdev);
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
+index ac311f5..cc380c3 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
+@@ -509,7 +509,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
+       u32 val;
+       if (q->pend_cred >= 8) {
+               val = PIDX(q->pend_cred / 8);
+-              if (!is_t4(adap->chip))
++              if (!is_t4(adap->params.chip))
+                       val |= DBTYPE(1);
+               wmb();
+               t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) |
+@@ -847,7 +847,7 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
+       wmb();            /* write descriptors before telling HW */
+       spin_lock(&q->db_lock);
+       if (!q->db_disabled) {
+-              if (is_t4(adap->chip)) {
++              if (is_t4(adap->params.chip)) {
+                       t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
+                                    QID(q->cntxt_id) | PIDX(n));
+               } else {
+@@ -1596,7 +1596,7 @@ static noinline int handle_trace_pkt(struct adapter *adap,
+               return 0;
+       }
+-      if (is_t4(adap->chip))
++      if (is_t4(adap->params.chip))
+               __skb_pull(skb, sizeof(struct cpl_trace_pkt));
+       else
+               __skb_pull(skb, sizeof(struct cpl_t5_trace_pkt));
+@@ -1661,7 +1661,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
+       const struct cpl_rx_pkt *pkt;
+       struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
+       struct sge *s = &q->adap->sge;
+-      int cpl_trace_pkt = is_t4(q->adap->chip) ?
++      int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
+                           CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
+       if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
+@@ -2182,7 +2182,7 @@ err:
+ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
+ {
+       q->cntxt_id = id;
+-      if (!is_t4(adap->chip)) {
++      if (!is_t4(adap->params.chip)) {
+               unsigned int s_qpp;
+               unsigned short udb_density;
+               unsigned long qpshift;
+@@ -2641,7 +2641,7 @@ static int t4_sge_init_hard(struct adapter *adap)
+        * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
+        * and generate an interrupt when this occurs so we can recover.
+        */
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
+                                V_HP_INT_THRESH(M_HP_INT_THRESH) |
+                                V_LP_INT_THRESH(M_LP_INT_THRESH),
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+index 4cbb2f9..83b5e42 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+@@ -296,7 +296,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
+       u32 mc_bist_cmd, mc_bist_cmd_addr, mc_bist_cmd_len;
+       u32 mc_bist_status_rdata, mc_bist_data_pattern;
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               mc_bist_cmd = MC_BIST_CMD;
+               mc_bist_cmd_addr = MC_BIST_CMD_ADDR;
+               mc_bist_cmd_len = MC_BIST_CMD_LEN;
+@@ -349,7 +349,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
+       u32 edc_bist_cmd, edc_bist_cmd_addr, edc_bist_cmd_len;
+       u32 edc_bist_cmd_data_pattern, edc_bist_status_rdata;
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               edc_bist_cmd = EDC_REG(EDC_BIST_CMD, idx);
+               edc_bist_cmd_addr = EDC_REG(EDC_BIST_CMD_ADDR, idx);
+               edc_bist_cmd_len = EDC_REG(EDC_BIST_CMD_LEN, idx);
+@@ -402,7 +402,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
+ static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
+ {
+       int i;
+-      u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
++      u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
+       /*
+        * Setup offset into PCIE memory window.  Address must be a
+@@ -918,7 +918,7 @@ int t4_check_fw_version(struct adapter *adapter)
+       minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers);
+       micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers);
+-      switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
++      switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
+       case CHELSIO_T4:
+               exp_major = FW_VERSION_MAJOR;
+               exp_minor = FW_VERSION_MINOR;
+@@ -931,7 +931,7 @@ int t4_check_fw_version(struct adapter *adapter)
+               break;
+       default:
+               dev_err(adapter->pdev_dev, "Unsupported chip type, %x\n",
+-                      adapter->chip);
++                      adapter->params.chip);
+               return -EINVAL;
+       }
+@@ -1368,7 +1368,7 @@ static void pcie_intr_handler(struct adapter *adapter)
+                                   PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+                                   pcie_port_intr_info) +
+             t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
+-                                  is_t4(adapter->chip) ?
++                                  is_t4(adapter->params.chip) ?
+                                   pcie_intr_info : t5_pcie_intr_info);
+       if (fat)
+@@ -1782,7 +1782,7 @@ static void xgmac_intr_handler(struct adapter *adap, int port)
+ {
+       u32 v, int_cause_reg;
+-      if (is_t4(adap->chip))
++      if (is_t4(adap->params.chip))
+               int_cause_reg = PORT_REG(port, XGMAC_PORT_INT_CAUSE);
+       else
+               int_cause_reg = T5_PORT_REG(port, MAC_PORT_INT_CAUSE);
+@@ -2250,7 +2250,7 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
+ #define GET_STAT(name) \
+       t4_read_reg64(adap, \
+-      (is_t4(adap->chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
++      (is_t4(adap->params.chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
+       T5_PORT_REG(idx, MPS_PORT_STAT_##name##_L)))
+ #define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L)
+@@ -2332,7 +2332,7 @@ void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
+ {
+       u32 mag_id_reg_l, mag_id_reg_h, port_cfg_reg;
+-      if (is_t4(adap->chip)) {
++      if (is_t4(adap->params.chip)) {
+               mag_id_reg_l = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO);
+               mag_id_reg_h = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI);
+               port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
+@@ -2374,7 +2374,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
+       int i;
+       u32 port_cfg_reg;
+-      if (is_t4(adap->chip))
++      if (is_t4(adap->params.chip))
+               port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
+       else
+               port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2);
+@@ -2387,7 +2387,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
+               return -EINVAL;
+ #define EPIO_REG(name) \
+-      (is_t4(adap->chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
++      (is_t4(adap->params.chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
+       T5_PORT_REG(port, MAC_PORT_EPIO_##name))
+       t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32);
+@@ -2474,7 +2474,7 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
+ int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
+ {
+       int i, off;
+-      u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
++      u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
+       /* Align on a 2KB boundary.
+        */
+@@ -3306,7 +3306,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
+       int i, ret;
+       struct fw_vi_mac_cmd c;
+       struct fw_vi_mac_exact *p;
+-      unsigned int max_naddr = is_t4(adap->chip) ?
++      unsigned int max_naddr = is_t4(adap->params.chip) ?
+                                      NUM_MPS_CLS_SRAM_L_INSTANCES :
+                                      NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
+@@ -3368,7 +3368,7 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
+       int ret, mode;
+       struct fw_vi_mac_cmd c;
+       struct fw_vi_mac_exact *p = c.u.exact;
+-      unsigned int max_mac_addr = is_t4(adap->chip) ?
++      unsigned int max_mac_addr = is_t4(adap->params.chip) ?
+                                   NUM_MPS_CLS_SRAM_L_INSTANCES :
+                                   NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
+@@ -3699,13 +3699,14 @@ int t4_prep_adapter(struct adapter *adapter)
+ {
+       int ret, ver;
+       uint16_t device_id;
++      u32 pl_rev;
+       ret = t4_wait_dev_ready(adapter);
+       if (ret < 0)
+               return ret;
+       get_pci_mode(adapter, &adapter->params.pci);
+-      adapter->params.rev = t4_read_reg(adapter, PL_REV);
++      pl_rev = G_REV(t4_read_reg(adapter, PL_REV));
+       ret = get_flash_params(adapter);
+       if (ret < 0) {
+@@ -3717,14 +3718,13 @@ int t4_prep_adapter(struct adapter *adapter)
+        */
+       pci_read_config_word(adapter->pdev, PCI_DEVICE_ID, &device_id);
+       ver = device_id >> 12;
++      adapter->params.chip = 0;
+       switch (ver) {
+       case CHELSIO_T4:
+-              adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4,
+-                                                adapter->params.rev);
++              adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev);
+               break;
+       case CHELSIO_T5:
+-              adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5,
+-                                                adapter->params.rev);
++              adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev);
+               break;
+       default:
+               dev_err(adapter->pdev_dev, "Device %d is not supported\n",
+@@ -3732,9 +3732,6 @@ int t4_prep_adapter(struct adapter *adapter)
+               return -EINVAL;
+       }
+-      /* Reassign the updated revision field */
+-      adapter->params.rev = adapter->chip;
+-
+       init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
+       /*
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+index ef146c0..a7d8189 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+@@ -1092,6 +1092,11 @@
+ #define PL_REV 0x1943c
++#define S_REV    0
++#define M_REV    0xfU
++#define V_REV(x) ((x) << S_REV)
++#define G_REV(x) (((x) >> S_REV) & M_REV)
++
+ #define LE_DB_CONFIG 0x19c04
+ #define  HASHEN 0x00100000U
+-- 
+1.7.1
+
diff --git a/linux-next-cherry-picks/0002-cxgb4-Add-new-scheme-to-update-T4-T5-firmware.patch b/linux-next-cherry-picks/0002-cxgb4-Add-new-scheme-to-update-T4-T5-firmware.patch
new file mode 100644 (file)
index 0000000..c2214ab
--- /dev/null
@@ -0,0 +1,690 @@
+From 16e47624e76b43dbef5671af7b9e26589d7018b9 Mon Sep 17 00:00:00 2001
+From: Hariprasad Shenai <hariprasad@chelsio.com>
+Date: Tue, 3 Dec 2013 17:05:58 +0530
+Subject: [PATCH] cxgb4: Add new scheme to update T4/T5 firmware
+
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4.h      |   37 +++-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |  242 ++++++++++++-----------
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c      |  195 ++++++++++++------
+ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h   |    7 +-
+ 4 files changed, 290 insertions(+), 191 deletions(-)
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+index 9710a16..6c93088 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+@@ -49,13 +49,15 @@
+ #include <asm/io.h>
+ #include "cxgb4_uld.h"
+-#define FW_VERSION_MAJOR 1
+-#define FW_VERSION_MINOR 4
+-#define FW_VERSION_MICRO 0
++#define T4FW_VERSION_MAJOR 0x01
++#define T4FW_VERSION_MINOR 0x06
++#define T4FW_VERSION_MICRO 0x18
++#define T4FW_VERSION_BUILD 0x00
+-#define FW_VERSION_MAJOR_T5 0
+-#define FW_VERSION_MINOR_T5 0
+-#define FW_VERSION_MICRO_T5 0
++#define T5FW_VERSION_MAJOR 0x01
++#define T5FW_VERSION_MINOR 0x08
++#define T5FW_VERSION_MICRO 0x1C
++#define T5FW_VERSION_BUILD 0x00
+ #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
+@@ -287,6 +289,23 @@ struct adapter_params {
+       unsigned int ofldq_wr_cred;
+ };
++#include "t4fw_api.h"
++
++#define FW_VERSION(chip) ( \
++              FW_HDR_FW_VER_MAJOR_GET(chip##FW_VERSION_MAJOR) | \
++              FW_HDR_FW_VER_MINOR_GET(chip##FW_VERSION_MINOR) | \
++              FW_HDR_FW_VER_MICRO_GET(chip##FW_VERSION_MICRO) | \
++              FW_HDR_FW_VER_BUILD_GET(chip##FW_VERSION_BUILD))
++#define FW_INTFVER(chip, intf) (FW_HDR_INTFVER_##intf)
++
++struct fw_info {
++      u8 chip;
++      char *fs_name;
++      char *fw_mod_name;
++      struct fw_hdr fw_hdr;
++};
++
++
+ struct trace_params {
+       u32 data[TRACE_LEN / 4];
+       u32 mask[TRACE_LEN / 4];
+@@ -901,7 +920,11 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
+ int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
+ unsigned int t4_flash_cfg_addr(struct adapter *adapter);
+ int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
+-int t4_check_fw_version(struct adapter *adapter);
++int t4_get_fw_version(struct adapter *adapter, u32 *vers);
++int t4_get_tp_version(struct adapter *adapter, u32 *vers);
++int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
++             const u8 *fw_data, unsigned int fw_size,
++             struct fw_hdr *card_fw, enum dev_state state, int *reset);
+ int t4_prep_adapter(struct adapter *adapter);
+ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
+ void t4_fatal_err(struct adapter *adapter);
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index 35933cd..d6b12e0 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -276,9 +276,9 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
+       { 0, }
+ };
+-#define FW_FNAME "cxgb4/t4fw.bin"
++#define FW4_FNAME "cxgb4/t4fw.bin"
+ #define FW5_FNAME "cxgb4/t5fw.bin"
+-#define FW_CFNAME "cxgb4/t4-config.txt"
++#define FW4_CFNAME "cxgb4/t4-config.txt"
+ #define FW5_CFNAME "cxgb4/t5-config.txt"
+ MODULE_DESCRIPTION(DRV_DESC);
+@@ -286,7 +286,7 @@ MODULE_AUTHOR("Chelsio Communications");
+ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_VERSION(DRV_VERSION);
+ MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
+-MODULE_FIRMWARE(FW_FNAME);
++MODULE_FIRMWARE(FW4_FNAME);
+ MODULE_FIRMWARE(FW5_FNAME);
+ /*
+@@ -1071,72 +1071,6 @@ freeout:        t4_free_sge_resources(adap);
+ }
+ /*
+- * Returns 0 if new FW was successfully loaded, a positive errno if a load was
+- * started but failed, and a negative errno if flash load couldn't start.
+- */
+-static int upgrade_fw(struct adapter *adap)
+-{
+-      int ret;
+-      u32 vers, exp_major;
+-      const struct fw_hdr *hdr;
+-      const struct firmware *fw;
+-      struct device *dev = adap->pdev_dev;
+-      char *fw_file_name;
+-
+-      switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
+-      case CHELSIO_T4:
+-              fw_file_name = FW_FNAME;
+-              exp_major = FW_VERSION_MAJOR;
+-              break;
+-      case CHELSIO_T5:
+-              fw_file_name = FW5_FNAME;
+-              exp_major = FW_VERSION_MAJOR_T5;
+-              break;
+-      default:
+-              dev_err(dev, "Unsupported chip type, %x\n", adap->params.chip);
+-              return -EINVAL;
+-      }
+-
+-      ret = request_firmware(&fw, fw_file_name, dev);
+-      if (ret < 0) {
+-              dev_err(dev, "unable to load firmware image %s, error %d\n",
+-                      fw_file_name, ret);
+-              return ret;
+-      }
+-
+-      hdr = (const struct fw_hdr *)fw->data;
+-      vers = ntohl(hdr->fw_ver);
+-      if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) {
+-              ret = -EINVAL;              /* wrong major version, won't do */
+-              goto out;
+-      }
+-
+-      /*
+-       * If the flash FW is unusable or we found something newer, load it.
+-       */
+-      if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major ||
+-          vers > adap->params.fw_vers) {
+-              dev_info(dev, "upgrading firmware ...\n");
+-              ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size,
+-                                  /*force=*/false);
+-              if (!ret)
+-                      dev_info(dev,
+-                               "firmware upgraded to version %pI4 from %s\n",
+-                               &hdr->fw_ver, fw_file_name);
+-              else
+-                      dev_err(dev, "firmware upgrade failed! err=%d\n", -ret);
+-      } else {
+-              /*
+-               * Tell our caller that we didn't upgrade the firmware.
+-               */
+-              ret = -EINVAL;
+-      }
+-
+-out:  release_firmware(fw);
+-      return ret;
+-}
+-
+-/*
+  * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
+  * The allocated memory is cleared.
+  */
+@@ -4668,8 +4602,10 @@ static int adap_init0_config(struct adapter *adapter, int reset)
+       const struct firmware *cf;
+       unsigned long mtype = 0, maddr = 0;
+       u32 finiver, finicsum, cfcsum;
+-      int ret, using_flash;
++      int ret;
++      int config_issued = 0;
+       char *fw_config_file, fw_config_file_path[256];
++      char *config_name = NULL;
+       /*
+        * Reset device if necessary.
+@@ -4688,7 +4624,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
+        */
+       switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
+       case CHELSIO_T4:
+-              fw_config_file = FW_CFNAME;
++              fw_config_file = FW4_CFNAME;
+               break;
+       case CHELSIO_T5:
+               fw_config_file = FW5_CFNAME;
+@@ -4702,13 +4638,16 @@ static int adap_init0_config(struct adapter *adapter, int reset)
+       ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev);
+       if (ret < 0) {
+-              using_flash = 1;
++              config_name = "On FLASH";
+               mtype = FW_MEMTYPE_CF_FLASH;
+               maddr = t4_flash_cfg_addr(adapter);
+       } else {
+               u32 params[7], val[7];
+-              using_flash = 0;
++              sprintf(fw_config_file_path,
++                      "/lib/firmware/%s", fw_config_file);
++              config_name = fw_config_file_path;
++
+               if (cf->size >= FLASH_CFG_MAX_SIZE)
+                       ret = -ENOMEM;
+               else {
+@@ -4776,6 +4715,26 @@ static int adap_init0_config(struct adapter *adapter, int reset)
+                     FW_LEN16(caps_cmd));
+       ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
+                        &caps_cmd);
++
++      /* If the CAPS_CONFIG failed with an ENOENT (for a Firmware
++       * Configuration File in FLASH), our last gasp effort is to use the
++       * Firmware Configuration File which is embedded in the firmware.  A
++       * very few early versions of the firmware didn't have one embedded
++       * but we can ignore those.
++       */
++      if (ret == -ENOENT) {
++              memset(&caps_cmd, 0, sizeof(caps_cmd));
++              caps_cmd.op_to_write =
++                      htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
++                                      FW_CMD_REQUEST |
++                                      FW_CMD_READ);
++              caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
++              ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd,
++                              sizeof(caps_cmd), &caps_cmd);
++              config_name = "Firmware Default";
++      }
++
++      config_issued = 1;
+       if (ret < 0)
+               goto bye;
+@@ -4816,7 +4775,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
+       if (ret < 0)
+               goto bye;
+-      sprintf(fw_config_file_path, "/lib/firmware/%s", fw_config_file);
+       /*
+        * Return successfully and note that we're operating with parameters
+        * not supplied by the driver, rather than from hard-wired
+@@ -4824,11 +4782,8 @@ static int adap_init0_config(struct adapter *adapter, int reset)
+        */
+       adapter->flags |= USING_SOFT_PARAMS;
+       dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\
+-               "Configuration File %s, version %#x, computed checksum %#x\n",
+-               (using_flash
+-                ? "in device FLASH"
+-                : fw_config_file_path),
+-               finiver, cfcsum);
++               "Configuration File \"%s\", version %#x, computed checksum %#x\n",
++               config_name, finiver, cfcsum);
+       return 0;
+       /*
+@@ -4837,9 +4792,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
+        * want to issue a warning since this is fairly common.)
+        */
+ bye:
+-      if (ret != -ENOENT)
+-              dev_warn(adapter->pdev_dev, "Configuration file error %d\n",
+-                       -ret);
++      if (config_issued && ret != -ENOENT)
++              dev_warn(adapter->pdev_dev, "\"%s\" configuration file error %d\n",
++                       config_name, -ret);
+       return ret;
+ }
+@@ -5086,6 +5041,47 @@ bye:
+       return ret;
+ }
++static struct fw_info fw_info_array[] = {
++      {
++              .chip = CHELSIO_T4,
++              .fs_name = FW4_CFNAME,
++              .fw_mod_name = FW4_FNAME,
++              .fw_hdr = {
++                      .chip = FW_HDR_CHIP_T4,
++                      .fw_ver = __cpu_to_be32(FW_VERSION(T4)),
++                      .intfver_nic = FW_INTFVER(T4, NIC),
++                      .intfver_vnic = FW_INTFVER(T4, VNIC),
++                      .intfver_ri = FW_INTFVER(T4, RI),
++                      .intfver_iscsi = FW_INTFVER(T4, ISCSI),
++                      .intfver_fcoe = FW_INTFVER(T4, FCOE),
++              },
++      }, {
++              .chip = CHELSIO_T5,
++              .fs_name = FW5_CFNAME,
++              .fw_mod_name = FW5_FNAME,
++              .fw_hdr = {
++                      .chip = FW_HDR_CHIP_T5,
++                      .fw_ver = __cpu_to_be32(FW_VERSION(T5)),
++                      .intfver_nic = FW_INTFVER(T5, NIC),
++                      .intfver_vnic = FW_INTFVER(T5, VNIC),
++                      .intfver_ri = FW_INTFVER(T5, RI),
++                      .intfver_iscsi = FW_INTFVER(T5, ISCSI),
++                      .intfver_fcoe = FW_INTFVER(T5, FCOE),
++              },
++      }
++};
++
++static struct fw_info *find_fw_info(int chip)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(fw_info_array); i++) {
++              if (fw_info_array[i].chip == chip)
++                      return &fw_info_array[i];
++      }
++      return NULL;
++}
++
+ /*
+  * Phase 0 of initialization: contact FW, obtain config, perform basic init.
+  */
+@@ -5123,44 +5119,54 @@ static int adap_init0(struct adapter *adap)
+        * later reporting and B. to warn if the currently loaded firmware
+        * is excessively mismatched relative to the driver.)
+        */
+-      ret = t4_check_fw_version(adap);
+-
+-      /* The error code -EFAULT is returned by t4_check_fw_version() if
+-       * firmware on adapter < supported firmware. If firmware on adapter
+-       * is too old (not supported by driver) and we're the MASTER_PF set
+-       * adapter state to DEV_STATE_UNINIT to force firmware upgrade
+-       * and reinitialization.
+-       */
+-      if ((adap->flags & MASTER_PF) && ret == -EFAULT)
+-              state = DEV_STATE_UNINIT;
++      t4_get_fw_version(adap, &adap->params.fw_vers);
++      t4_get_tp_version(adap, &adap->params.tp_vers);
+       if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
+-              if (ret == -EINVAL || ret == -EFAULT || ret > 0) {
+-                      if (upgrade_fw(adap) >= 0) {
+-                              /*
+-                               * Note that the chip was reset as part of the
+-                               * firmware upgrade so we don't reset it again
+-                               * below and grab the new firmware version.
+-                               */
+-                              reset = 0;
+-                              ret = t4_check_fw_version(adap);
+-                      } else
+-                              if (ret == -EFAULT) {
+-                                      /*
+-                                       * Firmware is old but still might
+-                                       * work if we force reinitialization
+-                                       * of the adapter. Ignoring FW upgrade
+-                                       * failure.
+-                                       */
+-                                      dev_warn(adap->pdev_dev,
+-                                               "Ignoring firmware upgrade "
+-                                               "failure, and forcing driver "
+-                                               "to reinitialize the "
+-                                               "adapter.\n");
+-                                      ret = 0;
+-                              }
++              struct fw_info *fw_info;
++              struct fw_hdr *card_fw;
++              const struct firmware *fw;
++              const u8 *fw_data = NULL;
++              unsigned int fw_size = 0;
++
++              /* This is the firmware whose headers the driver was compiled
++               * against
++               */
++              fw_info = find_fw_info(CHELSIO_CHIP_VERSION(adap->params.chip));
++              if (fw_info == NULL) {
++                      dev_err(adap->pdev_dev,
++                              "unable to get firmware info for chip %d.\n",
++                              CHELSIO_CHIP_VERSION(adap->params.chip));
++                      return -EINVAL;
+               }
++
++              /* allocate memory to read the header of the firmware on the
++               * card
++               */
++              card_fw = t4_alloc_mem(sizeof(*card_fw));
++
++              /* Get FW from from /lib/firmware/ */
++              ret = request_firmware(&fw, fw_info->fw_mod_name,
++                                     adap->pdev_dev);
++              if (ret < 0) {
++                      dev_err(adap->pdev_dev,
++                              "unable to load firmware image %s, error %d\n",
++                              fw_info->fw_mod_name, ret);
++              } else {
++                      fw_data = fw->data;
++                      fw_size = fw->size;
++              }
++
++              /* upgrade FW logic */
++              ret = t4_prep_fw(adap, fw_info, fw_data, fw_size, card_fw,
++                               state, &reset);
++
++              /* Cleaning up */
++              if (fw != NULL)
++                      release_firmware(fw);
++              t4_free_mem(card_fw);
++
+               if (ret < 0)
+-                      return ret;
++                      goto bye;
+       }
+       /*
+@@ -5245,7 +5251,7 @@ static int adap_init0(struct adapter *adap)
+                               if (ret == -ENOENT) {
+                                       dev_info(adap->pdev_dev,
+                                           "No Configuration File present "
+-                                          "on adapter.  Using hard-wired "
++                                          "on adapter. Using hard-wired "
+                                           "configuration parameters.\n");
+                                       ret = adap_init0_no_config(adap, reset);
+                               }
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+index 83b5e42..74a6fce 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+@@ -863,104 +863,169 @@ unlock:
+ }
+ /**
+- *    get_fw_version - read the firmware version
++ *    t4_get_fw_version - read the firmware version
+  *    @adapter: the adapter
+  *    @vers: where to place the version
+  *
+  *    Reads the FW version from flash.
+  */
+-static int get_fw_version(struct adapter *adapter, u32 *vers)
++int t4_get_fw_version(struct adapter *adapter, u32 *vers)
+ {
+-      return t4_read_flash(adapter, adapter->params.sf_fw_start +
+-                           offsetof(struct fw_hdr, fw_ver), 1, vers, 0);
++      return t4_read_flash(adapter, FLASH_FW_START +
++                           offsetof(struct fw_hdr, fw_ver), 1,
++                           vers, 0);
+ }
+ /**
+- *    get_tp_version - read the TP microcode version
++ *    t4_get_tp_version - read the TP microcode version
+  *    @adapter: the adapter
+  *    @vers: where to place the version
+  *
+  *    Reads the TP microcode version from flash.
+  */
+-static int get_tp_version(struct adapter *adapter, u32 *vers)
++int t4_get_tp_version(struct adapter *adapter, u32 *vers)
+ {
+-      return t4_read_flash(adapter, adapter->params.sf_fw_start +
++      return t4_read_flash(adapter, FLASH_FW_START +
+                            offsetof(struct fw_hdr, tp_microcode_ver),
+                            1, vers, 0);
+ }
+-/**
+- *    t4_check_fw_version - check if the FW is compatible with this driver
+- *    @adapter: the adapter
+- *
+- *    Checks if an adapter's FW is compatible with the driver.  Returns 0
+- *    if there's exact match, a negative error if the version could not be
+- *    read or there's a major version mismatch, and a positive value if the
+- *    expected major version is found but there's a minor version mismatch.
++/* Is the given firmware API compatible with the one the driver was compiled
++ * with?
+  */
+-int t4_check_fw_version(struct adapter *adapter)
++static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2)
+ {
+-      u32 api_vers[2];
+-      int ret, major, minor, micro;
+-      int exp_major, exp_minor, exp_micro;
+-      ret = get_fw_version(adapter, &adapter->params.fw_vers);
+-      if (!ret)
+-              ret = get_tp_version(adapter, &adapter->params.tp_vers);
+-      if (!ret)
+-              ret = t4_read_flash(adapter, adapter->params.sf_fw_start +
+-                                  offsetof(struct fw_hdr, intfver_nic),
+-                                  2, api_vers, 1);
+-      if (ret)
+-              return ret;
++      /* short circuit if it's the exact same firmware version */
++      if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver)
++              return 1;
+-      major = FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers);
+-      minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers);
+-      micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers);
++#define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x)
++      if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) &&
++          SAME_INTF(ri) && SAME_INTF(iscsi) && SAME_INTF(fcoe))
++              return 1;
++#undef SAME_INTF
+-      switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
+-      case CHELSIO_T4:
+-              exp_major = FW_VERSION_MAJOR;
+-              exp_minor = FW_VERSION_MINOR;
+-              exp_micro = FW_VERSION_MICRO;
+-              break;
+-      case CHELSIO_T5:
+-              exp_major = FW_VERSION_MAJOR_T5;
+-              exp_minor = FW_VERSION_MINOR_T5;
+-              exp_micro = FW_VERSION_MICRO_T5;
+-              break;
+-      default:
+-              dev_err(adapter->pdev_dev, "Unsupported chip type, %x\n",
+-                      adapter->params.chip);
+-              return -EINVAL;
+-      }
++      return 0;
++}
+-      memcpy(adapter->params.api_vers, api_vers,
+-             sizeof(adapter->params.api_vers));
++/* The firmware in the filesystem is usable, but should it be installed?
++ * This routine explains itself in detail if it indicates the filesystem
++ * firmware should be installed.
++ */
++static int should_install_fs_fw(struct adapter *adap, int card_fw_usable,
++                              int k, int c)
++{
++      const char *reason;
+-      if (major < exp_major || (major == exp_major && minor < exp_minor) ||
+-          (major == exp_major && minor == exp_minor && micro < exp_micro)) {
+-              dev_err(adapter->pdev_dev,
+-                      "Card has firmware version %u.%u.%u, minimum "
+-                      "supported firmware is %u.%u.%u.\n", major, minor,
+-                      micro, exp_major, exp_minor, exp_micro);
+-              return -EFAULT;
++      if (!card_fw_usable) {
++              reason = "incompatible or unusable";
++              goto install;
+       }
+-      if (major != exp_major) {            /* major mismatch - fail */
+-              dev_err(adapter->pdev_dev,
+-                      "card FW has major version %u, driver wants %u\n",
+-                      major, exp_major);
+-              return -EINVAL;
++      if (k > c) {
++              reason = "older than the version supported with this driver";
++              goto install;
+       }
+-      if (minor == exp_minor && micro == exp_micro)
+-              return 0;                                   /* perfect match */
++      return 0;
++
++install:
++      dev_err(adap->pdev_dev, "firmware on card (%u.%u.%u.%u) is %s, "
++              "installing firmware %u.%u.%u.%u on card.\n",
++              FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
++              FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), reason,
++              FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
++              FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
+-      /* Minor/micro version mismatch.  Report it but often it's OK. */
+       return 1;
+ }
++int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
++             const u8 *fw_data, unsigned int fw_size,
++             struct fw_hdr *card_fw, enum dev_state state,
++             int *reset)
++{
++      int ret, card_fw_usable, fs_fw_usable;
++      const struct fw_hdr *fs_fw;
++      const struct fw_hdr *drv_fw;
++
++      drv_fw = &fw_info->fw_hdr;
++
++      /* Read the header of the firmware on the card */
++      ret = -t4_read_flash(adap, FLASH_FW_START,
++                          sizeof(*card_fw) / sizeof(uint32_t),
++                          (uint32_t *)card_fw, 1);
++      if (ret == 0) {
++              card_fw_usable = fw_compatible(drv_fw, (const void *)card_fw);
++      } else {
++              dev_err(adap->pdev_dev,
++                      "Unable to read card's firmware header: %d\n", ret);
++              card_fw_usable = 0;
++      }
++
++      if (fw_data != NULL) {
++              fs_fw = (const void *)fw_data;
++              fs_fw_usable = fw_compatible(drv_fw, fs_fw);
++      } else {
++              fs_fw = NULL;
++              fs_fw_usable = 0;
++      }
++
++      if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
++          (!fs_fw_usable || fs_fw->fw_ver == drv_fw->fw_ver)) {
++              /* Common case: the firmware on the card is an exact match and
++               * the filesystem one is an exact match too, or the filesystem
++               * one is absent/incompatible.
++               */
++      } else if (fs_fw_usable && state == DEV_STATE_UNINIT &&
++                 should_install_fs_fw(adap, card_fw_usable,
++                                      be32_to_cpu(fs_fw->fw_ver),
++                                      be32_to_cpu(card_fw->fw_ver))) {
++              ret = -t4_fw_upgrade(adap, adap->mbox, fw_data,
++                                   fw_size, 0);
++              if (ret != 0) {
++                      dev_err(adap->pdev_dev,
++                              "failed to install firmware: %d\n", ret);
++                      goto bye;
++              }
++
++              /* Installed successfully, update the cached header too. */
++              memcpy(card_fw, fs_fw, sizeof(*card_fw));
++              card_fw_usable = 1;
++              *reset = 0;     /* already reset as part of load_fw */
++      }
++
++      if (!card_fw_usable) {
++              uint32_t d, c, k;
++
++              d = be32_to_cpu(drv_fw->fw_ver);
++              c = be32_to_cpu(card_fw->fw_ver);
++              k = fs_fw ? be32_to_cpu(fs_fw->fw_ver) : 0;
++
++              dev_err(adap->pdev_dev, "Cannot find a usable firmware: "
++                      "chip state %d, "
++                      "driver compiled with %d.%d.%d.%d, "
++                      "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n",
++                      state,
++                      FW_HDR_FW_VER_MAJOR_GET(d), FW_HDR_FW_VER_MINOR_GET(d),
++                      FW_HDR_FW_VER_MICRO_GET(d), FW_HDR_FW_VER_BUILD_GET(d),
++                      FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
++                      FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c),
++                      FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
++                      FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
++              ret = EINVAL;
++              goto bye;
++      }
++
++      /* We're using whatever's on the card and it's known to be good. */
++      adap->params.fw_vers = be32_to_cpu(card_fw->fw_ver);
++      adap->params.tp_vers = be32_to_cpu(card_fw->tp_microcode_ver);
++
++bye:
++      return ret;
++}
++
+ /**
+  *    t4_flash_erase_sectors - erase a range of flash sectors
+  *    @adapter: the adapter
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+index 6f77ac4..74fea74 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+@@ -2157,7 +2157,7 @@ struct fw_debug_cmd {
+ struct fw_hdr {
+       u8 ver;
+-      u8 reserved1;
++      u8 chip;                        /* terminator chip type */
+       __be16  len512;                 /* bin length in units of 512-bytes */
+       __be32  fw_ver;                 /* firmware version */
+       __be32  tp_microcode_ver;
+@@ -2176,6 +2176,11 @@ struct fw_hdr {
+       __be32  reserved6[23];
+ };
++enum fw_hdr_chip {
++      FW_HDR_CHIP_T4,
++      FW_HDR_CHIP_T5
++};
++
+ #define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff)
+ #define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
+ #define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
+-- 
+1.7.1
+
diff --git a/linux-next-cherry-picks/0003-cxgb4-Reserve-stid-0-for-T4-T5-adapters.patch b/linux-next-cherry-picks/0003-cxgb4-Reserve-stid-0-for-T4-T5-adapters.patch
new file mode 100644 (file)
index 0000000..7899828
--- /dev/null
@@ -0,0 +1,49 @@
+From b6f8eaece6d5f0247931b6dac140e6cf876f48de Mon Sep 17 00:00:00 2001
+From: Kumar Sanghvi <kumaras@chelsio.com>
+Date: Wed, 18 Dec 2013 16:38:19 +0530
+Subject: [PATCH] cxgb4: Reserve stid 0 for T4/T5 adapters
+
+When creating offload server entries, an IPv6 passive connection request
+can trigger a reply with a null STID, whereas the driver would expect
+the reply 'STID to match the value used for the request.
+This happens due to h/w limitation on T4 and T5.
+
+This patch ensures that STID 0 is never used if the stid range starts
+from zero.
+
+Based on original work by Santosh Rastapur <santosh@chelsio.com>
+
+Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |    6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index d6b12e0..f36f8e1 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -3134,6 +3134,7 @@ static int tid_init(struct tid_info *t)
+       size_t size;
+       unsigned int stid_bmap_size;
+       unsigned int natids = t->natids;
++      struct adapter *adap = container_of(t, struct adapter, tids);
+       stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
+       size = t->ntids * sizeof(*t->tid_tab) +
+@@ -3167,6 +3168,11 @@ static int tid_init(struct tid_info *t)
+               t->afree = t->atid_tab;
+       }
+       bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
++      /* Reserve stid 0 for T4/T5 adapters */
++      if (!t->stid_base &&
++          (is_t4(adap->params.chip) || is_t5(adap->params.chip)))
++              __set_bit(0, t->stid_bmap);
++
+       return 0;
+ }
+-- 
+1.7.1
+
diff --git a/linux-next-cherry-picks/0004-cxgb4-Include-TCP-as-protocol-when-creating-server-f.patch b/linux-next-cherry-picks/0004-cxgb4-Include-TCP-as-protocol-when-creating-server-f.patch
new file mode 100644 (file)
index 0000000..157f06f
--- /dev/null
@@ -0,0 +1,55 @@
+From 7c89e5550ccb2a3118854639d9525847e896c686 Mon Sep 17 00:00:00 2001
+From: Kumar Sanghvi <kumaras@chelsio.com>
+Date: Wed, 18 Dec 2013 16:38:20 +0530
+Subject: [PATCH] cxgb4: Include TCP as protocol when creating server filters
+
+We were creating LE Workaround Server Filters without specifying
+IPPROTO_TCP (6) in the filters (when F_PROTOCOL is set in TP_VLAN_PRI_MAP).
+This meant that UDP packets with matching IP Addresses/Ports would get
+caught up in the filter and be delivered to ULDs like iw_cxgb4.
+So, include the protocol information in the server filter properly.
+
+Based on original work by Casey Leedom <leedom@chelsio.com>
+
+Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |    5 +++++
+ drivers/net/ethernet/chelsio/cxgb4/t4_regs.h    |    4 ++++
+ 2 files changed, 9 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index f36f8e1..df1d6b8 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -4217,6 +4217,11 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
+               }
+       }
++      if (adap->filter_mode & F_PROTOCOL) {
++              f->fs.val.proto = IPPROTO_TCP;
++              f->fs.mask.proto = ~0;
++      }
++
+       f->fs.dirsteer = 1;
+       f->fs.iq = queue;
+       /* Mark filter as locked */
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+index 0a8205d..d3dd218 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+@@ -1171,6 +1171,10 @@
+ #define A_TP_TX_SCHED_PCMD 0x25
++#define S_PROTOCOL    5
++#define V_PROTOCOL(x) ((x) << S_PROTOCOL)
++#define F_PROTOCOL    V_PROTOCOL(1U)
++
+ #define S_PORT    1
+ #define V_PORT(x) ((x) << S_PORT)
+ #define F_PORT    V_PORT(1U)
+-- 
+1.7.1
+
diff --git a/linux-next-cherry-picks/0005-cxgb4-Assign-filter-server-TIDS-Account-for-stid.patch b/linux-next-cherry-picks/0005-cxgb4-Assign-filter-server-TIDS-Account-for-stid.patch
new file mode 100644 (file)
index 0000000..0878418
--- /dev/null
@@ -0,0 +1,95 @@
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index 951787f..94a6e62 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -3073,7 +3073,14 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
+       if (stid >= 0) {
+               t->stid_tab[stid].data = data;
+               stid += t->stid_base;
+-              t->stids_in_use++;
++              /* IPv6 requires max of 520 bits or 16 cells in TCAM
++               * This is equivalent to 4 TIDs. With CLIP enabled it
++               * needs 2 TIDs.
++               */
++              if (family == PF_INET)
++                      t->stids_in_use++;
++              else
++                      t->stids_in_use += 4;
+       }
+       spin_unlock_bh(&t->stid_lock);
+       return stid;
+@@ -3099,7 +3106,8 @@ int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
+       }
+       if (stid >= 0) {
+               t->stid_tab[stid].data = data;
+-              stid += t->stid_base;
++              stid -= t->nstids;
++              stid += t->sftid_base;
+               t->stids_in_use++;
+       }
+       spin_unlock_bh(&t->stid_lock);
+@@ -3111,14 +3119,24 @@ EXPORT_SYMBOL(cxgb4_alloc_sftid);
+  */
+ void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
+ {
+-      stid -= t->stid_base;
++      /* Is it a server filter TID? */
++      if (t->nsftids && (stid >= t->sftid_base)) {
++              stid -= t->sftid_base;
++              stid += t->nstids;
++      } else {
++              stid -= t->stid_base;
++      }
++
+       spin_lock_bh(&t->stid_lock);
+       if (family == PF_INET)
+               __clear_bit(stid, t->stid_bmap);
+       else
+               bitmap_release_region(t->stid_bmap, stid, 2);
+       t->stid_tab[stid].data = NULL;
+-      t->stids_in_use--;
++      if (family == PF_INET)
++              t->stids_in_use--;
++      else
++              t->stids_in_use -= 4;
+       spin_unlock_bh(&t->stid_lock);
+ }
+ EXPORT_SYMBOL(cxgb4_free_stid);
+@@ -4262,7 +4280,7 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
+       adap = netdev2adap(dev);
+       /* Adjust stid to correct filter index */
+-      stid -= adap->tids.nstids;
++      stid -= adap->tids.sftid_base;
+       stid += adap->tids.nftids;
+       /* Check to make sure the filter requested is writable ...
+@@ -4325,7 +4343,7 @@ int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
+       adap = netdev2adap(dev);
+       /* Adjust stid to correct filter index */
+-      stid -= adap->tids.nstids;
++      stid -= adap->tids.sftid_base;
+       stid += adap->tids.nftids;
+       f = &adap->tids.ftid_tab[stid];
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+index 6f21f24..4dd0a82 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+@@ -131,7 +131,14 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
+ static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
+ {
+-      stid -= t->stid_base;
++      /* Is it a server filter TID? */
++      if (t->nsftids && (stid >= t->sftid_base)) {
++              stid -= t->sftid_base;
++              stid += t->nstids;
++      } else {
++              stid -= t->stid_base;
++      }
++
+       return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL;
+ }
diff --git a/linux-next-cherry-picks/0006-cxgb4-Add-API-to-correctly-calculate-tuple-fields.patch b/linux-next-cherry-picks/0006-cxgb4-Add-API-to-correctly-calculate-tuple-fields.patch
new file mode 100644 (file)
index 0000000..cb647d0
--- /dev/null
@@ -0,0 +1,405 @@
+From dcf7b6f5bdeaa13d5e465d8795d2e7d6d1e27b65 Mon Sep 17 00:00:00 2001
+From: Kumar Sanghvi <kumaras@chelsio.com>
+Date: Wed, 18 Dec 2013 16:38:23 +0530
+Subject: [PATCH] cxgb4: Add API to correctly calculate tuple fields
+
+Adds API cxgb4_select_ntuple so as to enable Upper Level Drivers to correctly
+calculate the tuple fields.
+
+Adds constant definitions for TP_VLAN_PRI_MAP for the Compressed
+Filter Tuple field widths and structures and uses them.
+
+Also, the CPL Parameters field for T5 is 40 bits so we need to prototype
+cxgb4_select_ntuple() to calculate and return u64 values.
+
+Based on original work by Casey Leedom <leedom@chelsio.com>
+
+Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4.h      |   21 +++++
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |   20 +----
+ drivers/net/ethernet/chelsio/cxgb4/l2t.c        |   35 ++++++++
+ drivers/net/ethernet/chelsio/cxgb4/l2t.h        |    3 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c      |  103 +++++++++++++++++++++++
+ drivers/net/ethernet/chelsio/cxgb4/t4_regs.h    |   69 +++++++++++++++
+ 6 files changed, 235 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+index 6c93088..56e0415 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+@@ -228,6 +228,25 @@ struct tp_params {
+       uint32_t dack_re;            /* DACK timer resolution */
+       unsigned short tx_modq[NCHAN];  /* channel to modulation queue map */
++
++      u32 vlan_pri_map;               /* cached TP_VLAN_PRI_MAP */
++      u32 ingress_config;             /* cached TP_INGRESS_CONFIG */
++
++      /* TP_VLAN_PRI_MAP Compressed Filter Tuple field offsets.  This is a
++       * subset of the set of fields which may be present in the Compressed
++       * Filter Tuple portion of filters and TCP TCB connections.  The
++       * fields which are present are controlled by the TP_VLAN_PRI_MAP.
++       * Since a variable number of fields may or may not be present, their
++       * shifted field positions within the Compressed Filter Tuple may
++       * vary, or not even be present if the field isn't selected in
++       * TP_VLAN_PRI_MAP.  Since some of these fields are needed in various
++       * places we store their offsets here, or a -1 if the field isn't
++       * present.
++       */
++      int vlan_shift;
++      int vnic_shift;
++      int port_shift;
++      int protocol_shift;
+ };
+ struct vpd_params {
+@@ -926,6 +945,8 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
+              const u8 *fw_data, unsigned int fw_size,
+              struct fw_hdr *card_fw, enum dev_state state, int *reset);
+ int t4_prep_adapter(struct adapter *adapter);
++int t4_init_tp_params(struct adapter *adap);
++int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
+ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
+ void t4_fatal_err(struct adapter *adapter);
+ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index f9ca36c..fff02ed 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -3755,7 +3755,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
+       lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
+                       t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
+                       (adap->fn * 4));
+-      lli.filt_mode = adap->filter_mode;
++      lli.filt_mode = adap->params.tp.vlan_pri_map;
+       /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
+       for (i = 0; i < NCHAN; i++)
+               lli.tx_modq[i] = i;
+@@ -4229,13 +4229,13 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
+                       f->fs.val.lip[i] = val[i];
+                       f->fs.mask.lip[i] = ~0;
+               }
+-              if (adap->filter_mode & F_PORT) {
++              if (adap->params.tp.vlan_pri_map & F_PORT) {
+                       f->fs.val.iport = port;
+                       f->fs.mask.iport = mask;
+               }
+       }
+-      if (adap->filter_mode & F_PROTOCOL) {
++      if (adap->params.tp.vlan_pri_map & F_PROTOCOL) {
+               f->fs.val.proto = IPPROTO_TCP;
+               f->fs.mask.proto = ~0;
+       }
+@@ -5121,7 +5121,7 @@ static int adap_init0(struct adapter *adap)
+       enum dev_state state;
+       u32 params[7], val[7];
+       struct fw_caps_config_cmd caps_cmd;
+-      int reset = 1, j;
++      int reset = 1;
+       /*
+        * Contact FW, advertising Master capability (and potentially forcing
+@@ -5463,21 +5463,11 @@ static int adap_init0(struct adapter *adap)
+       /*
+        * These are finalized by FW initialization, load their values now.
+        */
+-      v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
+-      adap->params.tp.tre = TIMERRESOLUTION_GET(v);
+-      adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
+       t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
+       t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
+                    adap->params.b_wnd);
+-      /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
+-      for (j = 0; j < NCHAN; j++)
+-              adap->params.tp.tx_modq[j] = j;
+-
+-      t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+-                       &adap->filter_mode, 1,
+-                       TP_VLAN_PRI_MAP);
+-
++      t4_init_tp_params(adap);
+       adap->flags |= FW_OK;
+       return 0;
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+index 2987809..cb05be9 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+@@ -45,6 +45,7 @@
+ #include "l2t.h"
+ #include "t4_msg.h"
+ #include "t4fw_api.h"
++#include "t4_regs.h"
+ #define VLAN_NONE 0xfff
+@@ -411,6 +412,40 @@ done:
+ }
+ EXPORT_SYMBOL(cxgb4_l2t_get);
++u64 cxgb4_select_ntuple(struct net_device *dev,
++                      const struct l2t_entry *l2t)
++{
++      struct adapter *adap = netdev2adap(dev);
++      struct tp_params *tp = &adap->params.tp;
++      u64 ntuple = 0;
++
++      /* Initialize each of the fields which we care about which are present
++       * in the Compressed Filter Tuple.
++       */
++      if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE)
++              ntuple |= (F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift;
++
++      if (tp->port_shift >= 0)
++              ntuple |= (u64)l2t->lport << tp->port_shift;
++
++      if (tp->protocol_shift >= 0)
++              ntuple |= (u64)IPPROTO_TCP << tp->protocol_shift;
++
++      if (tp->vnic_shift >= 0) {
++              u32 viid = cxgb4_port_viid(dev);
++              u32 vf = FW_VIID_VIN_GET(viid);
++              u32 pf = FW_VIID_PFN_GET(viid);
++              u32 vld = FW_VIID_VIVLD_GET(viid);
++
++              ntuple |= (u64)(V_FT_VNID_ID_VF(vf) |
++                              V_FT_VNID_ID_PF(pf) |
++                              V_FT_VNID_ID_VLD(vld)) << tp->vnic_shift;
++      }
++
++      return ntuple;
++}
++EXPORT_SYMBOL(cxgb4_select_ntuple);
++
+ /*
+  * Called when address resolution fails for an L2T entry to handle packets
+  * on the arpq head.  If a packet specifies a failure handler it is invoked,
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.h b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
+index 108c0f1..85eb5c7 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
+@@ -98,7 +98,8 @@ int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
+ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
+                               const struct net_device *physdev,
+                               unsigned int priority);
+-
++u64 cxgb4_select_ntuple(struct net_device *dev,
++                      const struct l2t_entry *l2t);
+ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
+ struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
+ int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+index 74a6fce..e1413ea 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+@@ -3808,6 +3808,109 @@ int t4_prep_adapter(struct adapter *adapter)
+       return 0;
+ }
++/**
++ *      t4_init_tp_params - initialize adap->params.tp
++ *      @adap: the adapter
++ *
++ *      Initialize various fields of the adapter's TP Parameters structure.
++ */
++int t4_init_tp_params(struct adapter *adap)
++{
++      int chan;
++      u32 v;
++
++      v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
++      adap->params.tp.tre = TIMERRESOLUTION_GET(v);
++      adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
++
++      /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
++      for (chan = 0; chan < NCHAN; chan++)
++              adap->params.tp.tx_modq[chan] = chan;
++
++      /* Cache the adapter's Compressed Filter Mode and global Incress
++       * Configuration.
++       */
++      t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
++                       &adap->params.tp.vlan_pri_map, 1,
++                       TP_VLAN_PRI_MAP);
++      t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
++                       &adap->params.tp.ingress_config, 1,
++                       TP_INGRESS_CONFIG);
++
++      /* Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
++       * shift positions of several elements of the Compressed Filter Tuple
++       * for this adapter which we need frequently ...
++       */
++      adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
++      adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
++      adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
++      adap->params.tp.protocol_shift = t4_filter_field_shift(adap,
++                                                             F_PROTOCOL);
++
++      /* If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
++       * represents the presense of an Outer VLAN instead of a VNIC ID.
++       */
++      if ((adap->params.tp.ingress_config & F_VNIC) == 0)
++              adap->params.tp.vnic_shift = -1;
++
++      return 0;
++}
++
++/**
++ *      t4_filter_field_shift - calculate filter field shift
++ *      @adap: the adapter
++ *      @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
++ *
++ *      Return the shift position of a filter field within the Compressed
++ *      Filter Tuple.  The filter field is specified via its selection bit
++ *      within TP_VLAN_PRI_MAL (filter mode).  E.g. F_VLAN.
++ */
++int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
++{
++      unsigned int filter_mode = adap->params.tp.vlan_pri_map;
++      unsigned int sel;
++      int field_shift;
++
++      if ((filter_mode & filter_sel) == 0)
++              return -1;
++
++      for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
++              switch (filter_mode & sel) {
++              case F_FCOE:
++                      field_shift += W_FT_FCOE;
++                      break;
++              case F_PORT:
++                      field_shift += W_FT_PORT;
++                      break;
++              case F_VNIC_ID:
++                      field_shift += W_FT_VNIC_ID;
++                      break;
++              case F_VLAN:
++                      field_shift += W_FT_VLAN;
++                      break;
++              case F_TOS:
++                      field_shift += W_FT_TOS;
++                      break;
++              case F_PROTOCOL:
++                      field_shift += W_FT_PROTOCOL;
++                      break;
++              case F_ETHERTYPE:
++                      field_shift += W_FT_ETHERTYPE;
++                      break;
++              case F_MACMATCH:
++                      field_shift += W_FT_MACMATCH;
++                      break;
++              case F_MPSHITTYPE:
++                      field_shift += W_FT_MPSHITTYPE;
++                      break;
++              case F_FRAGMENTATION:
++                      field_shift += W_FT_FRAGMENTATION;
++                      break;
++              }
++      }
++      return field_shift;
++}
++
+ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
+ {
+       u8 addr[6];
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+index d3dd218..4082522 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+@@ -1171,14 +1171,50 @@
+ #define A_TP_TX_SCHED_PCMD 0x25
++#define S_VNIC    11
++#define V_VNIC(x) ((x) << S_VNIC)
++#define F_VNIC    V_VNIC(1U)
++
++#define S_FRAGMENTATION    9
++#define V_FRAGMENTATION(x) ((x) << S_FRAGMENTATION)
++#define F_FRAGMENTATION    V_FRAGMENTATION(1U)
++
++#define S_MPSHITTYPE    8
++#define V_MPSHITTYPE(x) ((x) << S_MPSHITTYPE)
++#define F_MPSHITTYPE    V_MPSHITTYPE(1U)
++
++#define S_MACMATCH    7
++#define V_MACMATCH(x) ((x) << S_MACMATCH)
++#define F_MACMATCH    V_MACMATCH(1U)
++
++#define S_ETHERTYPE    6
++#define V_ETHERTYPE(x) ((x) << S_ETHERTYPE)
++#define F_ETHERTYPE    V_ETHERTYPE(1U)
++
+ #define S_PROTOCOL    5
+ #define V_PROTOCOL(x) ((x) << S_PROTOCOL)
+ #define F_PROTOCOL    V_PROTOCOL(1U)
++#define S_TOS    4
++#define V_TOS(x) ((x) << S_TOS)
++#define F_TOS    V_TOS(1U)
++
++#define S_VLAN    3
++#define V_VLAN(x) ((x) << S_VLAN)
++#define F_VLAN    V_VLAN(1U)
++
++#define S_VNIC_ID    2
++#define V_VNIC_ID(x) ((x) << S_VNIC_ID)
++#define F_VNIC_ID    V_VNIC_ID(1U)
++
+ #define S_PORT    1
+ #define V_PORT(x) ((x) << S_PORT)
+ #define F_PORT    V_PORT(1U)
++#define S_FCOE    0
++#define V_FCOE(x) ((x) << S_FCOE)
++#define F_FCOE    V_FCOE(1U)
++
+ #define NUM_MPS_CLS_SRAM_L_INSTANCES 336
+ #define NUM_MPS_T5_CLS_SRAM_L_INSTANCES 512
+@@ -1217,4 +1253,37 @@
+ #define V_CHIPID(x) ((x) << S_CHIPID)
+ #define G_CHIPID(x) (((x) >> S_CHIPID) & M_CHIPID)
++/* TP_VLAN_PRI_MAP controls which subset of fields will be present in the
++ * Compressed Filter Tuple for LE filters.  Each bit set in TP_VLAN_PRI_MAP
++ * selects for a particular field being present.  These fields, when present
++ * in the Compressed Filter Tuple, have the following widths in bits.
++ */
++#define W_FT_FCOE                       1
++#define W_FT_PORT                       3
++#define W_FT_VNIC_ID                    17
++#define W_FT_VLAN                       17
++#define W_FT_TOS                        8
++#define W_FT_PROTOCOL                   8
++#define W_FT_ETHERTYPE                  16
++#define W_FT_MACMATCH                   9
++#define W_FT_MPSHITTYPE                 3
++#define W_FT_FRAGMENTATION              1
++
++/* Some of the Compressed Filter Tuple fields have internal structure.  These
++ * bit shifts/masks describe those structures.  All shifts are relative to the
++ * base position of the fields within the Compressed Filter Tuple
++ */
++#define S_FT_VLAN_VLD                   16
++#define V_FT_VLAN_VLD(x)                ((x) << S_FT_VLAN_VLD)
++#define F_FT_VLAN_VLD                   V_FT_VLAN_VLD(1U)
++
++#define S_FT_VNID_ID_VF                 0
++#define V_FT_VNID_ID_VF(x)              ((x) << S_FT_VNID_ID_VF)
++
++#define S_FT_VNID_ID_PF                 7
++#define V_FT_VNID_ID_PF(x)              ((x) << S_FT_VNID_ID_PF)
++
++#define S_FT_VNID_ID_VLD                16
++#define V_FT_VNID_ID_VLD(x)             ((x) << S_FT_VNID_ID_VLD)
++
+ #endif /* __T4_REGS_H */
+-- 
+1.7.1
+
diff --git a/linux-next-cherry-picks/0007-RDMA-cxgb4-Calculate-the-filter-server-TID-properly.patch b/linux-next-cherry-picks/0007-RDMA-cxgb4-Calculate-the-filter-server-TID-properly.patch
new file mode 100644 (file)
index 0000000..a6ef058
--- /dev/null
@@ -0,0 +1,32 @@
+From a4ea025fc24532bae8a038d038f8e0f15b8a7d98 Mon Sep 17 00:00:00 2001
+From: Kumar Sanghvi <kumaras@chelsio.com>
+Date: Wed, 18 Dec 2013 16:38:24 +0530
+Subject: [PATCH] RDMA/cxgb4: Calculate the filter server TID properly
+
+Based on original work by Santosh Rastapur <santosh@chelsio.com>
+
+Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/infiniband/hw/cxgb4/cm.c |    4 +---
+ 1 files changed, 1 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
+index 12fef76..02c7515 100644
+--- a/drivers/infiniband/hw/cxgb4/cm.c
++++ b/drivers/infiniband/hw/cxgb4/cm.c
+@@ -3323,9 +3323,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
+       /*
+        * Calculate the server tid from filter hit index from cpl_rx_pkt.
+        */
+-      stid = (__force int) cpu_to_be32((__force u32) rss->hash_val)
+-                                        - dev->rdev.lldi.tids->sftid_base
+-                                        + dev->rdev.lldi.tids->nstids;
++      stid = (__force int) cpu_to_be32((__force u32) rss->hash_val);
+       lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
+       if (!lep) {
+-- 
+1.7.1
+
diff --git a/linux-next-cherry-picks/0008-RDMA-cxgb4-Server-filters-are-supported-only-for-IPv.patch b/linux-next-cherry-picks/0008-RDMA-cxgb4-Server-filters-are-supported-only-for-IPv.patch
new file mode 100644 (file)
index 0000000..2591671
--- /dev/null
@@ -0,0 +1,29 @@
+From 8c04469057c3307d92d2c7076edcf9eb8f752bca Mon Sep 17 00:00:00 2001
+From: Kumar Sanghvi <kumaras@chelsio.com>
+Date: Wed, 18 Dec 2013 16:38:25 +0530
+Subject: [PATCH] RDMA/cxgb4: Server filters are supported only for IPv4
+
+Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/infiniband/hw/cxgb4/cm.c |    3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
+index 02c7515..bfd4ed7 100644
+--- a/drivers/infiniband/hw/cxgb4/cm.c
++++ b/drivers/infiniband/hw/cxgb4/cm.c
+@@ -2938,7 +2938,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
+       /*
+        * Allocate a server TID.
+        */
+-      if (dev->rdev.lldi.enable_fw_ofld_conn)
++      if (dev->rdev.lldi.enable_fw_ofld_conn &&
++          ep->com.local_addr.ss_family == AF_INET)
+               ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids,
+                                            cm_id->local_addr.ss_family, ep);
+       else
+-- 
+1.7.1
+
diff --git a/linux-next-cherry-picks/0009-RDMA-cxgb4-Use-cxgb4_select_ntuple-to-correctly-calc.patch b/linux-next-cherry-picks/0009-RDMA-cxgb4-Use-cxgb4_select_ntuple-to-correctly-calc.patch
new file mode 100644 (file)
index 0000000..ba1a27b
--- /dev/null
@@ -0,0 +1,139 @@
+From 41b4f86c1368758a02129e0629a9cc7c2811fa32 Mon Sep 17 00:00:00 2001
+From: Kumar Sanghvi <kumaras@chelsio.com>
+Date: Wed, 18 Dec 2013 16:38:26 +0530
+Subject: [PATCH] RDMA/cxgb4: Use cxgb4_select_ntuple to correctly calculate ntuple fields
+
+Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/infiniband/hw/cxgb4/cm.c |   71 +++++++++-----------------------------
+ 1 files changed, 17 insertions(+), 54 deletions(-)
+
+diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
+index bfd4ed7..4512687 100644
+--- a/drivers/infiniband/hw/cxgb4/cm.c
++++ b/drivers/infiniband/hw/cxgb4/cm.c
+@@ -524,50 +524,6 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
+       return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+ }
+-#define VLAN_NONE 0xfff
+-#define FILTER_SEL_VLAN_NONE 0xffff
+-#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
+-#define FILTER_SEL_WIDTH_VIN_P_FC \
+-      (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
+-#define FILTER_SEL_WIDTH_TAG_P_FC \
+-      (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
+-#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
+-
+-static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
+-                                struct l2t_entry *l2t)
+-{
+-      unsigned int ntuple = 0;
+-      u32 viid;
+-
+-      switch (dev->rdev.lldi.filt_mode) {
+-
+-      /* default filter mode */
+-      case HW_TPL_FR_MT_PR_IV_P_FC:
+-              if (l2t->vlan == VLAN_NONE)
+-                      ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
+-              else {
+-                      ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
+-                      ntuple |= 1 << FILTER_SEL_WIDTH_TAG_P_FC;
+-              }
+-              ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
+-                        FILTER_SEL_WIDTH_VLD_TAG_P_FC;
+-              break;
+-      case HW_TPL_FR_MT_PR_OV_P_FC: {
+-              viid = cxgb4_port_viid(l2t->neigh->dev);
+-
+-              ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
+-              ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
+-              ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
+-              ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
+-                        FILTER_SEL_WIDTH_VLD_TAG_P_FC;
+-              break;
+-      }
+-      default:
+-              break;
+-      }
+-      return ntuple;
+-}
+-
+ static int send_connect(struct c4iw_ep *ep)
+ {
+       struct cpl_act_open_req *req;
+@@ -641,8 +597,9 @@ static int send_connect(struct c4iw_ep *ep)
+                       req->local_ip = la->sin_addr.s_addr;
+                       req->peer_ip = ra->sin_addr.s_addr;
+                       req->opt0 = cpu_to_be64(opt0);
+-                      req->params = cpu_to_be32(select_ntuple(ep->com.dev,
+-                                              ep->dst, ep->l2t));
++                      req->params = cpu_to_be32(cxgb4_select_ntuple(
++                                              ep->com.dev->rdev.lldi.ports[0],
++                                              ep->l2t));
+                       req->opt2 = cpu_to_be32(opt2);
+               } else {
+                       req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
+@@ -662,9 +619,9 @@ static int send_connect(struct c4iw_ep *ep)
+                       req6->peer_ip_lo = *((__be64 *)
+                                               (ra6->sin6_addr.s6_addr + 8));
+                       req6->opt0 = cpu_to_be64(opt0);
+-                      req6->params = cpu_to_be32(
+-                                      select_ntuple(ep->com.dev, ep->dst,
+-                                                    ep->l2t));
++                      req6->params = cpu_to_be32(cxgb4_select_ntuple(
++                                              ep->com.dev->rdev.lldi.ports[0],
++                                              ep->l2t));
+                       req6->opt2 = cpu_to_be32(opt2);
+               }
+       } else {
+@@ -681,8 +638,9 @@ static int send_connect(struct c4iw_ep *ep)
+                       t5_req->peer_ip = ra->sin_addr.s_addr;
+                       t5_req->opt0 = cpu_to_be64(opt0);
+                       t5_req->params = cpu_to_be64(V_FILTER_TUPLE(
+-                                              select_ntuple(ep->com.dev,
+-                                              ep->dst, ep->l2t)));
++                                                   cxgb4_select_ntuple(
++                                           ep->com.dev->rdev.lldi.ports[0],
++                                           ep->l2t)));
+                       t5_req->opt2 = cpu_to_be32(opt2);
+               } else {
+                       t5_req6 = (struct cpl_t5_act_open_req6 *)
+@@ -703,7 +661,9 @@ static int send_connect(struct c4iw_ep *ep)
+                                               (ra6->sin6_addr.s6_addr + 8));
+                       t5_req6->opt0 = cpu_to_be64(opt0);
+                       t5_req6->params = (__force __be64)cpu_to_be32(
+-                              select_ntuple(ep->com.dev, ep->dst, ep->l2t));
++                                                      cxgb4_select_ntuple(
++                                              ep->com.dev->rdev.lldi.ports[0],
++                                              ep->l2t));
+                       t5_req6->opt2 = cpu_to_be32(opt2);
+               }
+       }
+@@ -1630,7 +1590,8 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
+       memset(req, 0, sizeof(*req));
+       req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR));
+       req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
+-      req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst,
++      req->le.filter = cpu_to_be32(cxgb4_select_ntuple(
++                                   ep->com.dev->rdev.lldi.ports[0],
+                                    ep->l2t));
+       sin = (struct sockaddr_in *)&ep->com.local_addr;
+       req->le.lport = sin->sin_port;
+@@ -3396,7 +3357,9 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
+       window = (__force u16) htons((__force u16)tcph->window);
+       /* Calcuate filter portion for LE region. */
+-      filter = (__force unsigned int) cpu_to_be32(select_ntuple(dev, dst, e));
++      filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple(
++                                                  dev->rdev.lldi.ports[0],
++                                                  e));
+       /*
+        * Synthesize the cpl_pass_accept_req. We have everything except the
+-- 
+1.7.1
+