[dpdk-dev,3/7] cxgbe: add support to update RSS hash configuration and key

Message ID 713e92d0143827f8af409763815cde15b9d40305.1517685185.git.rahul.lakkireddy@chelsio.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Rahul Lakkireddy Feb. 4, 2018, 6:06 a.m. UTC
  From: Kumar Sanghvi <kumaras@chelsio.com>

Add firmware API for updating RSS hash configuration and key.  Move
RSS hash configuration from cxgb4_write_rss() to a separate function
cxgbe_write_rss_conf().

Also, rename cxgb4_write_rss() to cxgbe_write_rss() for consistency.

Original work by Surendra Mobiya <surendra@chelsio.com>

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
---
 doc/guides/nics/cxgbe.rst               |  2 +
 doc/guides/nics/features/cxgbe.ini      |  1 +
 doc/guides/rel_notes/release_18_02.rst  |  3 ++
 drivers/net/cxgbe/base/adapter.h        |  4 +-
 drivers/net/cxgbe/base/common.h         |  3 ++
 drivers/net/cxgbe/base/t4_hw.c          | 73 +++++++++++++++++++++++++++
 drivers/net/cxgbe/base/t4_regs.h        | 25 +++++++++
 drivers/net/cxgbe/base/t4fw_interface.h | 89 +++++++++++++++++++++++++++++++++
 drivers/net/cxgbe/cxgbe.h               |  2 +
 drivers/net/cxgbe/cxgbe_ethdev.c        | 32 ++++++++++++
 drivers/net/cxgbe/cxgbe_main.c          | 79 ++++++++++++++++++++++-------
 11 files changed, 295 insertions(+), 18 deletions(-)
  

Comments

Ferruh Yigit Feb. 5, 2018, 5:09 p.m. UTC | #1
On 2/4/2018 6:06 AM, Rahul Lakkireddy wrote:
> From: Kumar Sanghvi <kumaras@chelsio.com>
> 
> Add firmware API for updating RSS hash configuration and key.  Move
> RSS hash configuration from cxgb4_write_rss() to a separate function
> cxgbe_write_rss_conf().
> 
> Also, rename cxgb4_write_rss() to cxgbe_write_rss() for consistency.
> 
> Original work by Surendra Mobiya <surendra@chelsio.com>
> 
> Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
> Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
> ---
>  doc/guides/nics/cxgbe.rst               |  2 +
>  doc/guides/nics/features/cxgbe.ini      |  1 +
>  doc/guides/rel_notes/release_18_02.rst  |  3 ++
>  drivers/net/cxgbe/base/adapter.h        |  4 +-
>  drivers/net/cxgbe/base/common.h         |  3 ++
>  drivers/net/cxgbe/base/t4_hw.c          | 73 +++++++++++++++++++++++++++
>  drivers/net/cxgbe/base/t4_regs.h        | 25 +++++++++
>  drivers/net/cxgbe/base/t4fw_interface.h | 89 +++++++++++++++++++++++++++++++++
>  drivers/net/cxgbe/cxgbe.h               |  2 +
>  drivers/net/cxgbe/cxgbe_ethdev.c        | 32 ++++++++++++
>  drivers/net/cxgbe/cxgbe_main.c          | 79 ++++++++++++++++++++++-------
>  11 files changed, 295 insertions(+), 18 deletions(-)

I tend to get driver patches even after integration deadline, mainly because of
their limited scope.
But since these are new features, submitted just before rc3, adding with
questions in first patch, I am for postponing this patchset to next release and
do more review, what do you think?
  
Rahul Lakkireddy Feb. 6, 2018, 9:22 a.m. UTC | #2
On Monday, February 02/05/18, 2018 at 22:39:55 +0530, Ferruh Yigit wrote:
> On 2/4/2018 6:06 AM, Rahul Lakkireddy wrote:
> > From: Kumar Sanghvi <kumaras@chelsio.com>
> > 
> > Add firmware API for updating RSS hash configuration and key.  Move
> > RSS hash configuration from cxgb4_write_rss() to a separate function
> > cxgbe_write_rss_conf().
> > 
> > Also, rename cxgb4_write_rss() to cxgbe_write_rss() for consistency.
> > 
> > Original work by Surendra Mobiya <surendra@chelsio.com>
> > 
> > Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
> > Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
> > ---
> >  doc/guides/nics/cxgbe.rst               |  2 +
> >  doc/guides/nics/features/cxgbe.ini      |  1 +
> >  doc/guides/rel_notes/release_18_02.rst  |  3 ++
> >  drivers/net/cxgbe/base/adapter.h        |  4 +-
> >  drivers/net/cxgbe/base/common.h         |  3 ++
> >  drivers/net/cxgbe/base/t4_hw.c          | 73 +++++++++++++++++++++++++++
> >  drivers/net/cxgbe/base/t4_regs.h        | 25 +++++++++
> >  drivers/net/cxgbe/base/t4fw_interface.h | 89 +++++++++++++++++++++++++++++++++
> >  drivers/net/cxgbe/cxgbe.h               |  2 +
> >  drivers/net/cxgbe/cxgbe_ethdev.c        | 32 ++++++++++++
> >  drivers/net/cxgbe/cxgbe_main.c          | 79 ++++++++++++++++++++++-------
> >  11 files changed, 295 insertions(+), 18 deletions(-)
> 
> I tend to get driver patches even after integration deadline, mainly because of
> their limited scope.
> But since these are new features, submitted just before rc3, adding with
> questions in first patch, I am for postponing this patchset to next release and
> do more review, what do you think?

Does dpdk-next-net tree work similar to linux "next" trees?  I mean does
it represent the next release (DPDK 18.05-rc1) merge window?  Can we
explicitly mention in Patch title which tree it is targeted for viz.
dpdk or dpdk-next-net?

Thanks,
Rahul
  
Ferruh Yigit Feb. 6, 2018, 10:11 a.m. UTC | #3
On 2/6/2018 9:22 AM, Rahul Lakkireddy wrote:
> On Monday, February 02/05/18, 2018 at 22:39:55 +0530, Ferruh Yigit wrote:
>> On 2/4/2018 6:06 AM, Rahul Lakkireddy wrote:
>>> From: Kumar Sanghvi <kumaras@chelsio.com>
>>>
>>> Add firmware API for updating RSS hash configuration and key.  Move
>>> RSS hash configuration from cxgb4_write_rss() to a separate function
>>> cxgbe_write_rss_conf().
>>>
>>> Also, rename cxgb4_write_rss() to cxgbe_write_rss() for consistency.
>>>
>>> Original work by Surendra Mobiya <surendra@chelsio.com>
>>>
>>> Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
>>> Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
>>> ---
>>>  doc/guides/nics/cxgbe.rst               |  2 +
>>>  doc/guides/nics/features/cxgbe.ini      |  1 +
>>>  doc/guides/rel_notes/release_18_02.rst  |  3 ++
>>>  drivers/net/cxgbe/base/adapter.h        |  4 +-
>>>  drivers/net/cxgbe/base/common.h         |  3 ++
>>>  drivers/net/cxgbe/base/t4_hw.c          | 73 +++++++++++++++++++++++++++
>>>  drivers/net/cxgbe/base/t4_regs.h        | 25 +++++++++
>>>  drivers/net/cxgbe/base/t4fw_interface.h | 89 +++++++++++++++++++++++++++++++++
>>>  drivers/net/cxgbe/cxgbe.h               |  2 +
>>>  drivers/net/cxgbe/cxgbe_ethdev.c        | 32 ++++++++++++
>>>  drivers/net/cxgbe/cxgbe_main.c          | 79 ++++++++++++++++++++++-------
>>>  11 files changed, 295 insertions(+), 18 deletions(-)
>>
>> I tend to get driver patches even after integration deadline, mainly because of
>> their limited scope.
>> But since these are new features, submitted just before rc3, adding with
>> questions in first patch, I am for postponing this patchset to next release and
>> do more review, what do you think?
> 
> Does dpdk-next-net tree work similar to linux "next" trees?  I mean does
> it represent the next release (DPDK 18.05-rc1) merge window?  Can we
> explicitly mention in Patch title which tree it is targeted for viz.
> dpdk or dpdk-next-net?

Hi Rahul,

It is not like Linux next trees, this is more like Dave's net tree.
In dpdk responsibilities split into sub-trees, and all target current release,
patches merged into sub-trees and pulled by main tree in integration deadline.

All network drivers and ethdev abstraction layer patches goes into next-net
sub-tree.


Briefly overall process is [1]:
- A new feature needs to be sent before proposal deadline, this can be a full
version of the set or RFC. Proposal deadline for the release announced in
https://dpdk.org/dev/roadmap

- After that point code reviews done and new versions sent till integration
deadline. Accepted patches are integrated to release candidate 1 (rc1).
Of course patch can be reviewed and merged without waiting integration deadline.
If a patch not get an approval and merge into tree in integration deadline,
most probably it won't go into release.

- Fixes can be sent from beginning of release to rcX. Only latest rcX mostly for
the fixes on features introduced in that release.

- After rc1, code tested and fixes sent for found defects. No new feature
expected after rc1.

- We go mostly to rc3 or rc4 before release.


[1]
Thomas, please correct me if I missed something. And this needs to be documented
indeed.

> 
> Thanks,
> Rahul
>
  
Thomas Monjalon Feb. 6, 2018, 10:38 a.m. UTC | #4
06/02/2018 11:11, Ferruh Yigit:
> On 2/6/2018 9:22 AM, Rahul Lakkireddy wrote:
> > On Monday, February 02/05/18, 2018 at 22:39:55 +0530, Ferruh Yigit wrote:
> >> I tend to get driver patches even after integration deadline, mainly because of
> >> their limited scope.
> >> But since these are new features, submitted just before rc3, adding with
> >> questions in first patch, I am for postponing this patchset to next release and
> >> do more review, what do you think?
> > 
> > Does dpdk-next-net tree work similar to linux "next" trees?  I mean does
> > it represent the next release (DPDK 18.05-rc1) merge window?  Can we
> > explicitly mention in Patch title which tree it is targeted for viz.
> > dpdk or dpdk-next-net?
> 
> Hi Rahul,
> 
> It is not like Linux next trees, this is more like Dave's net tree.
> In dpdk responsibilities split into sub-trees, and all target current release,
> patches merged into sub-trees and pulled by main tree in integration deadline.
> 
> All network drivers and ethdev abstraction layer patches goes into next-net
> sub-tree.
> 
> 
> Briefly overall process is [1]:
> - A new feature needs to be sent before proposal deadline, this can be a full
> version of the set or RFC. Proposal deadline for the release announced in
> https://dpdk.org/dev/roadmap
> 
> - After that point code reviews done and new versions sent till integration
> deadline. Accepted patches are integrated to release candidate 1 (rc1).
> Of course patch can be reviewed and merged without waiting integration deadline.
> If a patch not get an approval and merge into tree in integration deadline,
> most probably it won't go into release.
> 
> - Fixes can be sent from beginning of release to rcX. Only latest rcX mostly for
> the fixes on features introduced in that release.
> 
> - After rc1, code tested and fixes sent for found defects. No new feature
> expected after rc1.
> 
> - We go mostly to rc3 or rc4 before release.
> 
> 
> [1]
> Thomas, please correct me if I missed something. And this needs to be documented
> indeed.

If the patchset targets 18.05, it should be notified.
I suggest --subject-prefix='PATCH 18.05'.
Then it will be marked as Deferred in patchwork until the start of
the 18.05 release cycle.
We can review it but we do not apply it before the start of the cycle,
because we don't see a real need for such "in advance" branch.
  
Rahul Lakkireddy Feb. 7, 2018, 7:01 a.m. UTC | #5
On Tuesday, February 02/06/18, 2018 at 16:08:35 +0530, Thomas Monjalon wrote:
> 06/02/2018 11:11, Ferruh Yigit:
> > On 2/6/2018 9:22 AM, Rahul Lakkireddy wrote:
> > > On Monday, February 02/05/18, 2018 at 22:39:55 +0530, Ferruh Yigit wrote:
> > >> I tend to get driver patches even after integration deadline, mainly because of
> > >> their limited scope.
> > >> But since these are new features, submitted just before rc3, adding with
> > >> questions in first patch, I am for postponing this patchset to next release and
> > >> do more review, what do you think?
> > > 
> > > Does dpdk-next-net tree work similar to linux "next" trees?  I mean does
> > > it represent the next release (DPDK 18.05-rc1) merge window?  Can we
> > > explicitly mention in Patch title which tree it is targeted for viz.
> > > dpdk or dpdk-next-net?
> > 
> > Hi Rahul,
> > 
> > It is not like Linux next trees, this is more like Dave's net tree.
> > In dpdk responsibilities split into sub-trees, and all target current release,
> > patches merged into sub-trees and pulled by main tree in integration deadline.
> > 
> > All network drivers and ethdev abstraction layer patches goes into next-net
> > sub-tree.
> > 
> > 
> > Briefly overall process is [1]:
> > - A new feature needs to be sent before proposal deadline, this can be a full
> > version of the set or RFC. Proposal deadline for the release announced in
> > https://dpdk.org/dev/roadmap
> > 
> > - After that point code reviews done and new versions sent till integration
> > deadline. Accepted patches are integrated to release candidate 1 (rc1).
> > Of course patch can be reviewed and merged without waiting integration deadline.
> > If a patch not get an approval and merge into tree in integration deadline,
> > most probably it won't go into release.
> > 
> > - Fixes can be sent from beginning of release to rcX. Only latest rcX mostly for
> > the fixes on features introduced in that release.
> > 
> > - After rc1, code tested and fixes sent for found defects. No new feature
> > expected after rc1.
> > 
> > - We go mostly to rc3 or rc4 before release.
> > 
> > 
> > [1]
> > Thomas, please correct me if I missed something. And this needs to be documented
> > indeed.
> 
> If the patchset targets 18.05, it should be notified.
> I suggest --subject-prefix='PATCH 18.05'.
> Then it will be marked as Deferred in patchwork until the start of
> the 18.05 release cycle.
> We can review it but we do not apply it before the start of the cycle,
> because we don't see a real need for such "in advance" branch.
> 

Thank you Ferruh and Thomas for explaining workings/role of
dpdk-next-net tree.

I will wait for few more days to get reviews on patch related to
multiprocess.  And then, will re-submit the series as v2 once
dpdk-18.02 gets released.

Thanks,
Rahul
  

Patch

diff --git a/doc/guides/nics/cxgbe.rst b/doc/guides/nics/cxgbe.rst
index 8651a7be6..6126167c5 100644
--- a/doc/guides/nics/cxgbe.rst
+++ b/doc/guides/nics/cxgbe.rst
@@ -45,6 +45,8 @@  CXGBE PMD has support for:
 
 - Multiple queues for TX and RX
 - Receiver Side Steering (RSS)
+  Receiver Side Steering (RSS) on IPv4, IPv6, IPv4-TCP/UDP, IPv6-TCP/UDP.
+  For 4-tuple, enabling 'RSS on TCP' and 'RSS on TCP + UDP' is supported.
 - VLAN filtering
 - Checksum offload
 - Promiscuous mode
diff --git a/doc/guides/nics/features/cxgbe.ini b/doc/guides/nics/features/cxgbe.ini
index 1b9d81ffb..6cf5c13f5 100644
--- a/doc/guides/nics/features/cxgbe.ini
+++ b/doc/guides/nics/features/cxgbe.ini
@@ -14,6 +14,7 @@  TSO                  = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 RSS hash             = Y
+RSS key update       = Y
 Flow control         = Y
 CRC offload          = Y
 VLAN offload         = Y
diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst
index 689080bed..51a50cf93 100644
--- a/doc/guides/rel_notes/release_18_02.rst
+++ b/doc/guides/rel_notes/release_18_02.rst
@@ -204,6 +204,9 @@  New Features
     is unaffected by these changes, and can continue to be used for this
     and subsequent releases until such time as it's deprecation is announced.
 
+* **Added RSS hash and key update to CXGBE PMD.**
+
+  Support to update RSS hash and key has been added to CXGBE PMD.
 
 API Changes
 -----------
diff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h
index 0c1a1be25..4db2951e7 100644
--- a/drivers/net/cxgbe/base/adapter.h
+++ b/drivers/net/cxgbe/base/adapter.h
@@ -77,6 +77,7 @@  struct port_info {
 	u16    *rss;                    /* rss table */
 	u8     rss_mode;                /* rss mode */
 	u16    rss_size;                /* size of VI's RSS table slice */
+	u64    rss_hf;			/* RSS Hash Function */
 };
 
 /* Enable or disable autonegotiation.  If this is set to enable,
@@ -736,6 +737,7 @@  int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us,
 			       unsigned int cnt);
 int cxgbe_poll(struct sge_rspq *q, struct rte_mbuf **rx_pkts,
 	       unsigned int budget, unsigned int *work_done);
-int cxgb4_write_rss(const struct port_info *pi, const u16 *queues);
+int cxgbe_write_rss(const struct port_info *pi, const u16 *queues);
+int cxgbe_write_rss_conf(const struct port_info *pi, uint64_t flags);
 
 #endif /* __T4_ADAPTER_H__ */
diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h
index 1eda57d09..5301f7474 100644
--- a/drivers/net/cxgbe/base/common.h
+++ b/drivers/net/cxgbe/base/common.h
@@ -410,6 +410,9 @@  int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
 			int start, int n, const u16 *rspq, unsigned int nrspq);
 int t4_config_vi_rss(struct adapter *adapter, int mbox, unsigned int viid,
 		     unsigned int flags, unsigned int defq);
+void t4_fw_tp_pio_rw(struct adapter *adap, u32 *vals, unsigned int nregs,
+		     unsigned int start_index, unsigned int rw);
+void t4_write_rss_key(struct adapter *adap, u32 *key, int idx);
 
 enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS };
 int t4_bar2_sge_qregs(struct adapter *adapter, unsigned int qid,
diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c
index 56f38c838..9eb83fd5e 100644
--- a/drivers/net/cxgbe/base/t4_hw.c
+++ b/drivers/net/cxgbe/base/t4_hw.c
@@ -2166,6 +2166,79 @@  int t4_seeprom_wp(struct adapter *adapter, int enable)
 	return t4_seeprom_write(adapter, EEPROM_STAT_ADDR, enable ? 0xc : 0);
 }
 
+/**
+ * t4_fw_tp_pio_rw - Access TP PIO through LDST
+ * @adap: the adapter
+ * @vals: where the indirect register values are stored/written
+ * @nregs: how many indirect registers to read/write
+ * @start_idx: index of first indirect register to read/write
+ * @rw: Read (1) or Write (0)
+ *
+ * Access TP PIO registers through LDST
+ */
+void t4_fw_tp_pio_rw(struct adapter *adap, u32 *vals, unsigned int nregs,
+		     unsigned int start_index, unsigned int rw)
+{
+	int cmd = FW_LDST_ADDRSPC_TP_PIO;
+	struct fw_ldst_cmd c;
+	unsigned int i;
+	int ret;
+
+	for (i = 0 ; i < nregs; i++) {
+		memset(&c, 0, sizeof(c));
+		c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+						F_FW_CMD_REQUEST |
+						(rw ? F_FW_CMD_READ :
+						      F_FW_CMD_WRITE) |
+						V_FW_LDST_CMD_ADDRSPACE(cmd));
+		c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
+
+		c.u.addrval.addr = cpu_to_be32(start_index + i);
+		c.u.addrval.val  = rw ? 0 : cpu_to_be32(vals[i]);
+		ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
+		if (ret == 0) {
+			if (rw)
+				vals[i] = be32_to_cpu(c.u.addrval.val);
+		}
+	}
+}
+
+/**
+ * t4_write_rss_key - program one of the RSS keys
+ * @adap: the adapter
+ * @key: 10-entry array holding the 320-bit RSS key
+ * @idx: which RSS key to write
+ *
+ * Writes one of the RSS keys with the given 320-bit value.  If @idx is
+ * 0..15 the corresponding entry in the RSS key table is written,
+ * otherwise the global RSS key is written.
+ */
+void t4_write_rss_key(struct adapter *adap, u32 *key, int idx)
+{
+	u32 vrt = t4_read_reg(adap, A_TP_RSS_CONFIG_VRT);
+	u8 rss_key_addr_cnt = 16;
+
+	/* T6 and later: for KeyMode 3 (per-vf and per-vf scramble),
+	 * allows access to key addresses 16-63 by using KeyWrAddrX
+	 * as index[5:4](upper 2) into key table
+	 */
+	if ((CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) &&
+	    (vrt & F_KEYEXTEND) && (G_KEYMODE(vrt) == 3))
+		rss_key_addr_cnt = 32;
+
+	t4_fw_tp_pio_rw(adap, key, 10, A_TP_RSS_SECRET_KEY0, 0);
+
+	if (idx >= 0 && idx < rss_key_addr_cnt) {
+		if (rss_key_addr_cnt > 16)
+			t4_write_reg(adap, A_TP_RSS_CONFIG_VRT,
+				     V_KEYWRADDRX(idx >> 4) |
+				     V_T6_VFWRADDR(idx) | F_KEYWREN);
+		else
+			t4_write_reg(adap, A_TP_RSS_CONFIG_VRT,
+				     V_KEYWRADDR(idx) | F_KEYWREN);
+	}
+}
+
 /**
  * t4_config_rss_range - configure a portion of the RSS mapping table
  * @adapter: the adapter
diff --git a/drivers/net/cxgbe/base/t4_regs.h b/drivers/net/cxgbe/base/t4_regs.h
index 1100e16fe..0f0bca910 100644
--- a/drivers/net/cxgbe/base/t4_regs.h
+++ b/drivers/net/cxgbe/base/t4_regs.h
@@ -503,9 +503,34 @@ 
 #define V_MTUVALUE(x) ((x) << S_MTUVALUE)
 #define G_MTUVALUE(x) (((x) >> S_MTUVALUE) & M_MTUVALUE)
 
+#define A_TP_RSS_CONFIG_VRT 0x7e00
+
+#define S_KEYMODE    6
+#define M_KEYMODE    0x3U
+#define G_KEYMODE(x) (((x) >> S_KEYMODE) & M_KEYMODE)
+
+#define S_KEYWRADDR    0
+#define V_KEYWRADDR(x) ((x) << S_KEYWRADDR)
+
+#define S_KEYWREN    4
+#define V_KEYWREN(x) ((x) << S_KEYWREN)
+#define F_KEYWREN    V_KEYWREN(1U)
+
+#define S_KEYWRADDRX    30
+#define V_KEYWRADDRX(x) ((x) << S_KEYWRADDRX)
+
+#define S_KEYEXTEND    26
+#define V_KEYEXTEND(x) ((x) << S_KEYEXTEND)
+#define F_KEYEXTEND    V_KEYEXTEND(1U)
+
+#define S_T6_VFWRADDR    8
+#define V_T6_VFWRADDR(x) ((x) << S_T6_VFWRADDR)
+
 #define A_TP_PIO_ADDR 0x7e40
 #define A_TP_PIO_DATA 0x7e44
 
+#define A_TP_RSS_SECRET_KEY0 0x40
+
 #define A_TP_VLAN_PRI_MAP 0x140
 
 #define S_FRAGMENTATION    9
diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h
index 6ca4f3188..883a1c7f5 100644
--- a/drivers/net/cxgbe/base/t4fw_interface.h
+++ b/drivers/net/cxgbe/base/t4fw_interface.h
@@ -171,6 +171,7 @@  struct fw_eth_tx_pkts_wr {
 #define FW_CMD_HELLO_RETRIES	3
 
 enum fw_cmd_opcodes {
+	FW_LDST_CMD		       = 0x01,
 	FW_RESET_CMD                   = 0x03,
 	FW_HELLO_CMD                   = 0x04,
 	FW_BYE_CMD                     = 0x05,
@@ -238,6 +239,94 @@  struct fw_cmd_hdr {
 
 #define FW_LEN16(fw_struct) V_FW_CMD_LEN16(sizeof(fw_struct) / 16)
 
+/* address spaces
+ */
+enum fw_ldst_addrspc {
+	FW_LDST_ADDRSPC_TP_PIO    = 0x0010,
+};
+
+struct fw_ldst_cmd {
+	__be32 op_to_addrspace;
+	__be32 cycles_to_len16;
+	union fw_ldst {
+		struct fw_ldst_addrval {
+			__be32 addr;
+			__be32 val;
+		} addrval;
+		struct fw_ldst_idctxt {
+			__be32 physid;
+			__be32 msg_ctxtflush;
+			__be32 ctxt_data7;
+			__be32 ctxt_data6;
+			__be32 ctxt_data5;
+			__be32 ctxt_data4;
+			__be32 ctxt_data3;
+			__be32 ctxt_data2;
+			__be32 ctxt_data1;
+			__be32 ctxt_data0;
+		} idctxt;
+		struct fw_ldst_mdio {
+			__be16 paddr_mmd;
+			__be16 raddr;
+			__be16 vctl;
+			__be16 rval;
+		} mdio;
+		struct fw_ldst_mps {
+			__be16 fid_ctl;
+			__be16 rplcpf_pkd;
+			__be32 rplc127_96;
+			__be32 rplc95_64;
+			__be32 rplc63_32;
+			__be32 rplc31_0;
+			__be32 atrb;
+			__be16 vlan[16];
+		} mps;
+		struct fw_ldst_func {
+			__u8   access_ctl;
+			__u8   mod_index;
+			__be16 ctl_id;
+			__be32 offset;
+			__be64 data0;
+			__be64 data1;
+		} func;
+		struct fw_ldst_pcie {
+			__u8   ctrl_to_fn;
+			__u8   bnum;
+			__u8   r;
+			__u8   ext_r;
+			__u8   select_naccess;
+			__u8   pcie_fn;
+			__be16 nset_pkd;
+			__be32 data[12];
+		} pcie;
+		struct fw_ldst_i2c_deprecated {
+			__u8   pid_pkd;
+			__u8   base;
+			__u8   boffset;
+			__u8   data;
+			__be32 r9;
+		} i2c_deprecated;
+		struct fw_ldst_i2c {
+			__u8   pid;
+			__u8   did;
+			__u8   boffset;
+			__u8   blen;
+			__be32 r9;
+			__u8   data[48];
+		} i2c;
+		struct fw_ldst_le {
+			__be32 index;
+			__be32 r9;
+			__u8   val[33];
+			__u8   r11[7];
+		} le;
+	} u;
+};
+
+#define S_FW_LDST_CMD_ADDRSPACE         0
+#define M_FW_LDST_CMD_ADDRSPACE         0xff
+#define V_FW_LDST_CMD_ADDRSPACE(x)      ((x) << S_FW_LDST_CMD_ADDRSPACE)
+
 struct fw_reset_cmd {
 	__be32 op_to_write;
 	__be32 retval_len16;
diff --git a/drivers/net/cxgbe/cxgbe.h b/drivers/net/cxgbe/cxgbe.h
index f98915455..489e09dda 100644
--- a/drivers/net/cxgbe/cxgbe.h
+++ b/drivers/net/cxgbe/cxgbe.h
@@ -46,6 +46,8 @@ 
 #define CXGBE_MIN_RX_BUFSIZE ETHER_MIN_MTU /* min buf size */
 #define CXGBE_MAX_RX_PKTLEN (9000 + ETHER_HDR_LEN + ETHER_CRC_LEN) /* max pkt */
 
+#define CXGBE_DEFAULT_RSS_KEY_LEN     40 /* 320-bits */
+
 int cxgbe_probe(struct adapter *adapter);
 void cxgbe_get_speed_caps(struct port_info *pi, u32 *speed_caps);
 int cxgbe_up(struct adapter *adap);
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index 5a25125fe..7b902763b 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -171,6 +171,7 @@  static void cxgbe_dev_info_get(struct rte_eth_dev *eth_dev,
 				       DEV_TX_OFFLOAD_TCP_TSO;
 
 	device_info->reta_size = pi->rss_size;
+	device_info->hash_key_size = CXGBE_DEFAULT_RSS_KEY_LEN;
 
 	device_info->rx_desc_lim = cxgbe_desc_lim;
 	device_info->tx_desc_lim = cxgbe_desc_lim;
@@ -788,6 +789,36 @@  cxgbe_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev)
 	return NULL;
 }
 
+/* Update RSS hash configuration
+ */
+static int cxgbe_dev_rss_hash_update(struct rte_eth_dev *dev,
+				     struct rte_eth_rss_conf *rss_conf)
+{
+	struct port_info *pi = (struct port_info *)(dev->data->dev_private);
+	struct adapter *adapter = pi->adapter;
+	int err;
+
+	err = cxgbe_write_rss_conf(pi, rss_conf->rss_hf);
+	if (err)
+		return err;
+
+	pi->rss_hf = rss_conf->rss_hf;
+
+	if (rss_conf->rss_key) {
+		u32 key[10], mod_key[10];
+		int i, j;
+
+		memcpy(key, rss_conf->rss_key, CXGBE_DEFAULT_RSS_KEY_LEN);
+
+		for (i = 9, j = 0; i >= 0; i--, j++)
+			mod_key[j] = cpu_to_be32(key[i]);
+
+		t4_write_rss_key(adapter, mod_key, -1);
+	}
+
+	return 0;
+}
+
 static int cxgbe_get_eeprom_length(struct rte_eth_dev *dev)
 {
 	RTE_SET_USED(dev);
@@ -986,6 +1017,7 @@  static const struct eth_dev_ops cxgbe_eth_dev_ops = {
 	.get_eeprom		= cxgbe_get_eeprom,
 	.set_eeprom		= cxgbe_set_eeprom,
 	.get_reg		= cxgbe_get_regs,
+	.rss_hash_update	= cxgbe_dev_rss_hash_update,
 };
 
 /*
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index c502fadf7..930c3dfdf 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -360,6 +360,8 @@  static int init_rss(struct adapter *adap)
 		pi->rss = rte_zmalloc(NULL, pi->rss_size * sizeof(u16), 0);
 		if (!pi->rss)
 			return -ENOMEM;
+
+		pi->rss_hf = ETH_RSS_TCP | ETH_RSS_UDP;
 	}
 	return 0;
 }
@@ -930,14 +932,67 @@  int link_start(struct port_info *pi)
 }
 
 /**
- * cxgb4_write_rss - write the RSS table for a given port
+ * cxgbe_write_rss_conf - flash the RSS configuration for a given port
+ * @pi: the port
+ * @rss_hf: Hash configuration to apply
+ */
+int cxgbe_write_rss_conf(const struct port_info *pi, uint64_t rss_hf)
+{
+	struct adapter *adapter = pi->adapter;
+	const struct sge_eth_rxq *rxq;
+	u64 flags = 0;
+	u16 rss;
+	int err;
+
+	/*  Should never be called before setting up sge eth rx queues */
+	if (!(adapter->flags & FULL_INIT_DONE)) {
+		dev_err(adap, "%s No RXQs available on port %d\n",
+			__func__, pi->port_id);
+		return -EINVAL;
+	}
+
+	if (rss_hf & ETH_RSS_IPV4)
+		flags |= F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN;
+
+	if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
+		flags |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN;
+
+	if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP)
+		flags |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN |
+			 F_FW_RSS_VI_CONFIG_CMD_UDPEN;
+
+	if (rss_hf & ETH_RSS_IPV6)
+		flags |= F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN;
+
+	if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
+		flags |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN;
+
+	if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP)
+		flags |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN |
+			 F_FW_RSS_VI_CONFIG_CMD_UDPEN;
+
+	rxq = &adapter->sge.ethrxq[pi->first_qset];
+	rss = rxq[0].rspq.abs_id;
+
+	/* If Tunnel All Lookup isn't specified in the global RSS
+	 * Configuration, then we need to specify a default Ingress
+	 * Queue for any ingress packets which aren't hashed.  We'll
+	 * use our first ingress queue ...
+	 */
+	err = t4_config_vi_rss(adapter, adapter->mbox, pi->viid,
+			       flags, rss);
+	return err;
+}
+
+/**
+ * cxgbe_write_rss - write the RSS table for a given port
  * @pi: the port
  * @queues: array of queue indices for RSS
  *
  * Sets up the portion of the HW RSS table for the port's VI to distribute
  * packets to the Rx queues in @queues.
  */
-int cxgb4_write_rss(const struct port_info *pi, const u16 *queues)
+int cxgbe_write_rss(const struct port_info *pi, const u16 *queues)
 {
 	u16 *rss;
 	int i, err;
@@ -958,20 +1013,6 @@  int cxgb4_write_rss(const struct port_info *pi, const u16 *queues)
 
 	err = t4_config_rss_range(adapter, adapter->pf, pi->viid, 0,
 				  pi->rss_size, rss, pi->rss_size);
-	/*
-	 * If Tunnel All Lookup isn't specified in the global RSS
-	 * Configuration, then we need to specify a default Ingress
-	 * Queue for any ingress packets which aren't hashed.  We'll
-	 * use our first ingress queue ...
-	 */
-	if (!err)
-		err = t4_config_vi_rss(adapter, adapter->mbox, pi->viid,
-				       F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN |
-				       F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN |
-				       F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN |
-				       F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN |
-				       F_FW_RSS_VI_CONFIG_CMD_UDPEN,
-				       rss[0]);
 	rte_free(rss);
 	return err;
 }
@@ -1001,7 +1042,11 @@  int setup_rss(struct port_info *pi)
 			for (j = 0; j < pi->rss_size; j++)
 				pi->rss[j] = j % pi->n_rx_qsets;
 
-			err = cxgb4_write_rss(pi, pi->rss);
+			err = cxgbe_write_rss(pi, pi->rss);
+			if (err)
+				return err;
+
+			err = cxgbe_write_rss_conf(pi, pi->rss_hf);
 			if (err)
 				return err;
 			pi->flags |= PORT_RSS_DONE;