* [PATCH v2 net-next 7/9] lan743x: Add EEE support
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran
In-Reply-To: <1531422306-6547-1-git-send-email-Bryan.Whitehead@microchip.com>
Implement EEE support
Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
drivers/net/ethernet/microchip/lan743x_ethtool.c | 89 ++++++++++++++++++++++++
drivers/net/ethernet/microchip/lan743x_main.h | 3 +
2 files changed, 92 insertions(+)
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index f9d875d..3d95290 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -415,6 +415,93 @@ static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
}
}
+static int lan743x_ethtool_get_eee(struct net_device *netdev,
+ struct ethtool_eee *eee)
+{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+ struct phy_device *phydev = netdev->phydev;
+ u32 buf;
+ int ret;
+
+ if (!phydev)
+ return -EIO;
+ if (!phydev->drv) {
+ netif_err(adapter, drv, adapter->netdev,
+ "Missing PHY Driver\n");
+ return -EIO;
+ }
+
+ ret = phy_ethtool_get_eee(phydev, eee);
+ if (ret < 0)
+ return ret;
+
+ buf = lan743x_csr_read(adapter, MAC_CR);
+ if (buf & MAC_CR_EEE_EN_) {
+ eee->eee_enabled = true;
+ eee->eee_active = !!(eee->advertised & eee->lp_advertised);
+ eee->tx_lpi_enabled = true;
+ /* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */
+ buf = lan743x_csr_read(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT);
+ eee->tx_lpi_timer = buf;
+ } else {
+ eee->eee_enabled = false;
+ eee->eee_active = false;
+ eee->tx_lpi_enabled = false;
+ eee->tx_lpi_timer = 0;
+ }
+
+ return 0;
+}
+
+static int lan743x_ethtool_set_eee(struct net_device *netdev,
+ struct ethtool_eee *eee)
+{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+ struct phy_device *phydev = NULL;
+ u32 buf = 0;
+ int ret = 0;
+
+ if (!netdev)
+ return -EINVAL;
+ adapter = netdev_priv(netdev);
+ if (!adapter)
+ return -EINVAL;
+ phydev = netdev->phydev;
+ if (!phydev)
+ return -EIO;
+ if (!phydev->drv) {
+ netif_err(adapter, drv, adapter->netdev,
+ "Missing PHY Driver\n");
+ return -EIO;
+ }
+
+ if (eee->eee_enabled) {
+ ret = phy_init_eee(phydev, 0);
+ if (ret) {
+ netif_err(adapter, drv, adapter->netdev,
+ "EEE initialization failed\n");
+ return ret;
+ }
+
+ buf = lan743x_csr_read(adapter, MAC_CR);
+ buf |= MAC_CR_EEE_EN_;
+ lan743x_csr_write(adapter, MAC_CR, buf);
+
+ phy_ethtool_set_eee(phydev, eee);
+
+ buf = (u32)eee->tx_lpi_timer;
+ lan743x_csr_write(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT, buf);
+ netif_info(adapter, drv, adapter->netdev, "Enabled EEE\n");
+ } else {
+ buf = lan743x_csr_read(adapter, MAC_CR);
+ buf &= ~MAC_CR_EEE_EN_;
+ lan743x_csr_write(adapter, MAC_CR, buf);
+ netif_info(adapter, drv, adapter->netdev, "Disabled EEE\n");
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_PM
static void lan743x_ethtool_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
@@ -471,6 +558,8 @@ const struct ethtool_ops lan743x_ethtool_ops = {
.get_strings = lan743x_ethtool_get_strings,
.get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
.get_sset_count = lan743x_ethtool_get_sset_count,
+ .get_eee = lan743x_ethtool_get_eee,
+ .set_eee = lan743x_ethtool_set_eee,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
#ifdef CONFIG_PM
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 72b9beb..93cb60a 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -82,6 +82,7 @@
((value << 0) & FCT_FLOW_CTL_ON_THRESHOLD_)
#define MAC_CR (0x100)
+#define MAC_CR_EEE_EN_ BIT(17)
#define MAC_CR_ADD_ BIT(12)
#define MAC_CR_ASD_ BIT(11)
#define MAC_CR_CNTR_RST_ BIT(5)
@@ -117,6 +118,8 @@
#define MAC_MII_DATA (0x124)
+#define MAC_EEE_TX_LPI_REQ_DLY_CNT (0x130)
+
#define MAC_WUCSR (0x140)
#define MAC_WUCSR_RFE_WAKE_EN_ BIT(14)
#define MAC_WUCSR_PFDA_EN_ BIT(3)
--
2.7.4
^ permalink raw reply related
* [PATCH v2 net-next 8/9] lan743x: Add RSS support
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran
In-Reply-To: <1531422306-6547-1-git-send-email-Bryan.Whitehead@microchip.com>
Implement RSS support
Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
drivers/net/ethernet/microchip/lan743x_ethtool.c | 132 +++++++++++++++++++++++
drivers/net/ethernet/microchip/lan743x_main.c | 20 ++++
drivers/net/ethernet/microchip/lan743x_main.h | 19 ++++
3 files changed, 171 insertions(+)
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 3d95290..33d6c2d 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -415,6 +415,133 @@ static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
}
}
+static int lan743x_ethtool_get_rxnfc(struct net_device *netdev,
+ struct ethtool_rxnfc *rxnfc,
+ u32 *rule_locs)
+{
+ switch (rxnfc->cmd) {
+ case ETHTOOL_GRXFH:
+ rxnfc->data = 0;
+ switch (rxnfc->flow_type) {
+ case TCP_V4_FLOW:case UDP_V4_FLOW:
+ case TCP_V6_FLOW:case UDP_V6_FLOW:
+ rxnfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case IPV4_FLOW: case IPV6_FLOW:
+ rxnfc->data |= RXH_IP_SRC | RXH_IP_DST;
+ return 0;
+ }
+ break;
+ case ETHTOOL_GRXRINGS:
+ rxnfc->data = LAN743X_USED_RX_CHANNELS;
+ return 0;
+ }
+ return -EOPNOTSUPP;
+}
+
+static u32 lan743x_ethtool_get_rxfh_key_size(struct net_device *netdev)
+{
+ return 40;
+}
+
+static u32 lan743x_ethtool_get_rxfh_indir_size(struct net_device *netdev)
+{
+ return 128;
+}
+
+static int lan743x_ethtool_get_rxfh(struct net_device *netdev,
+ u32 *indir, u8 *key, u8 *hfunc)
+{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+ if (indir) {
+ int dw_index;
+ int byte_index = 0;
+
+ for (dw_index = 0; dw_index < 32; dw_index++) {
+ u32 four_entries =
+ lan743x_csr_read(adapter, RFE_INDX(dw_index));
+
+ byte_index = dw_index << 2;
+ indir[byte_index + 0] =
+ ((four_entries >> 0) & 0x000000FF);
+ indir[byte_index + 1] =
+ ((four_entries >> 8) & 0x000000FF);
+ indir[byte_index + 2] =
+ ((four_entries >> 16) & 0x000000FF);
+ indir[byte_index + 3] =
+ ((four_entries >> 24) & 0x000000FF);
+ }
+ }
+ if (key) {
+ int dword_index;
+ int byte_index = 0;
+
+ for (dword_index = 0; dword_index < 10; dword_index++) {
+ u32 four_entries =
+ lan743x_csr_read(adapter,
+ RFE_HASH_KEY(dword_index));
+
+ byte_index = dword_index << 2;
+ key[byte_index + 0] =
+ ((four_entries >> 0) & 0x000000FF);
+ key[byte_index + 1] =
+ ((four_entries >> 8) & 0x000000FF);
+ key[byte_index + 2] =
+ ((four_entries >> 16) & 0x000000FF);
+ key[byte_index + 3] =
+ ((four_entries >> 24) & 0x000000FF);
+ }
+ }
+ if (hfunc)
+ (*hfunc) = ETH_RSS_HASH_TOP;
+ return 0;
+}
+
+static int lan743x_ethtool_set_rxfh(struct net_device *netdev,
+ const u32 *indir, const u8 *key,
+ const u8 hfunc)
+{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+ if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
+ return -EOPNOTSUPP;
+
+ if (indir) {
+ u32 indir_value = 0;
+ int dword_index = 0;
+ int byte_index = 0;
+
+ for (dword_index = 0; dword_index < 32; dword_index++) {
+ byte_index = dword_index << 2;
+ indir_value =
+ (((indir[byte_index + 0] & 0x000000FF) << 0) |
+ ((indir[byte_index + 1] & 0x000000FF) << 8) |
+ ((indir[byte_index + 2] & 0x000000FF) << 16) |
+ ((indir[byte_index + 3] & 0x000000FF) << 24));
+ lan743x_csr_write(adapter, RFE_INDX(dword_index),
+ indir_value);
+ }
+ }
+ if (key) {
+ int dword_index = 0;
+ int byte_index = 0;
+ u32 key_value = 0;
+
+ for (dword_index = 0; dword_index < 10; dword_index++) {
+ byte_index = dword_index << 2;
+ key_value =
+ ((((u32)(key[byte_index + 0])) << 0) |
+ (((u32)(key[byte_index + 1])) << 8) |
+ (((u32)(key[byte_index + 2])) << 16) |
+ (((u32)(key[byte_index + 3])) << 24));
+ lan743x_csr_write(adapter, RFE_HASH_KEY(dword_index),
+ key_value);
+ }
+ }
+ return 0;
+}
+
static int lan743x_ethtool_get_eee(struct net_device *netdev,
struct ethtool_eee *eee)
{
@@ -558,6 +685,11 @@ const struct ethtool_ops lan743x_ethtool_ops = {
.get_strings = lan743x_ethtool_get_strings,
.get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
.get_sset_count = lan743x_ethtool_get_sset_count,
+ .get_rxnfc = lan743x_ethtool_get_rxnfc,
+ .get_rxfh_key_size = lan743x_ethtool_get_rxfh_key_size,
+ .get_rxfh_indir_size = lan743x_ethtool_get_rxfh_indir_size,
+ .get_rxfh = lan743x_ethtool_get_rxfh,
+ .set_rxfh = lan743x_ethtool_set_rxfh,
.get_eee = lan743x_ethtool_get_eee,
.set_eee = lan743x_ethtool_set_eee,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 8e9eff8..953b581 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -1025,6 +1025,24 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
return ret;
}
+static void lan743x_rfe_open(struct lan743x_adapter *adapter)
+{
+ lan743x_csr_write(adapter, RFE_RSS_CFG,
+ RFE_RSS_CFG_UDP_IPV6_EX_ |
+ RFE_RSS_CFG_TCP_IPV6_EX_ |
+ RFE_RSS_CFG_IPV6_EX_ |
+ RFE_RSS_CFG_UDP_IPV6_ |
+ RFE_RSS_CFG_TCP_IPV6_ |
+ RFE_RSS_CFG_IPV6_ |
+ RFE_RSS_CFG_UDP_IPV4_ |
+ RFE_RSS_CFG_TCP_IPV4_ |
+ RFE_RSS_CFG_IPV4_ |
+ RFE_RSS_CFG_VALID_HASH_BITS_ |
+ RFE_RSS_CFG_RSS_QUEUE_ENABLE_ |
+ RFE_RSS_CFG_RSS_HASH_STORE_ |
+ RFE_RSS_CFG_RSS_ENABLE_);
+}
+
static void lan743x_rfe_update_mac_address(struct lan743x_adapter *adapter)
{
u8 *mac_addr;
@@ -2419,6 +2437,8 @@ static int lan743x_netdev_open(struct net_device *netdev)
if (ret)
goto close_mac;
+ lan743x_rfe_open(adapter);
+
for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++) {
ret = lan743x_rx_open(&adapter->rx[index]);
if (ret)
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 93cb60a..4fa7a5e 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -166,6 +166,25 @@
#define RFE_CTL_MCAST_HASH_ BIT(3)
#define RFE_CTL_DA_PERFECT_ BIT(1)
+#define RFE_RSS_CFG (0x554)
+#define RFE_RSS_CFG_UDP_IPV6_EX_ BIT(16)
+#define RFE_RSS_CFG_TCP_IPV6_EX_ BIT(15)
+#define RFE_RSS_CFG_IPV6_EX_ BIT(14)
+#define RFE_RSS_CFG_UDP_IPV6_ BIT(13)
+#define RFE_RSS_CFG_TCP_IPV6_ BIT(12)
+#define RFE_RSS_CFG_IPV6_ BIT(11)
+#define RFE_RSS_CFG_UDP_IPV4_ BIT(10)
+#define RFE_RSS_CFG_TCP_IPV4_ BIT(9)
+#define RFE_RSS_CFG_IPV4_ BIT(8)
+#define RFE_RSS_CFG_VALID_HASH_BITS_ (0x000000E0)
+#define RFE_RSS_CFG_RSS_QUEUE_ENABLE_ BIT(2)
+#define RFE_RSS_CFG_RSS_HASH_STORE_ BIT(1)
+#define RFE_RSS_CFG_RSS_ENABLE_ BIT(0)
+
+#define RFE_HASH_KEY(index) (0x558 + (index << 2))
+
+#define RFE_INDX(index) (0x580 + (index << 2))
+
#define MAC_WUCSR2 (0x600)
#define INT_STS (0x780)
--
2.7.4
^ permalink raw reply related
* [PATCH v2 net-next 9/9] lan743x: Add PTP support
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran
In-Reply-To: <1531422306-6547-1-git-send-email-Bryan.Whitehead@microchip.com>
PTP support includes:
Ingress, and egress timestamping.
PTP clock support
Pulse per second output on GPIO
Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
drivers/net/ethernet/microchip/Makefile | 2 +-
drivers/net/ethernet/microchip/lan743x_ethtool.c | 28 +
drivers/net/ethernet/microchip/lan743x_main.c | 81 +-
drivers/net/ethernet/microchip/lan743x_main.h | 96 +-
drivers/net/ethernet/microchip/lan743x_ptp.c | 1194 ++++++++++++++++++++++
drivers/net/ethernet/microchip/lan743x_ptp.h | 78 ++
6 files changed, 1474 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/ethernet/microchip/lan743x_ptp.c
create mode 100644 drivers/net/ethernet/microchip/lan743x_ptp.h
diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
index 43f47cb..538926d 100644
--- a/drivers/net/ethernet/microchip/Makefile
+++ b/drivers/net/ethernet/microchip/Makefile
@@ -6,4 +6,4 @@ obj-$(CONFIG_ENC28J60) += enc28j60.o
obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o
obj-$(CONFIG_LAN743X) += lan743x.o
-lan743x-objs := lan743x_main.o lan743x_ethtool.o
+lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 33d6c2d..8800716 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -4,6 +4,7 @@
#include <linux/netdevice.h>
#include "lan743x_main.h"
#include "lan743x_ethtool.h"
+#include <linux/net_tstamp.h>
#include <linux/pci.h>
#include <linux/phy.h>
@@ -542,6 +543,32 @@ static int lan743x_ethtool_set_rxfh(struct net_device *netdev,
return 0;
}
+static int lan743x_ethtool_get_ts_info(struct net_device *netdev,
+ struct ethtool_ts_info *ts_info)
+{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+ ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+#ifdef CONFIG_PTP_1588_CLOCK
+ if (adapter->ptp.ptp_clock)
+ ts_info->phc_index = ptp_clock_index(adapter->ptp.ptp_clock);
+ else
+ ts_info->phc_index = -1;
+#else
+ ts_info->phc_index = -1;
+#endif
+ ts_info->tx_types = BIT(HWTSTAMP_TX_OFF) |
+ BIT(HWTSTAMP_TX_ON);
+ ts_info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+ BIT(HWTSTAMP_FILTER_ALL);
+ return 0;
+}
+
static int lan743x_ethtool_get_eee(struct net_device *netdev,
struct ethtool_eee *eee)
{
@@ -690,6 +717,7 @@ const struct ethtool_ops lan743x_ethtool_ops = {
.get_rxfh_indir_size = lan743x_ethtool_get_rxfh_indir_size,
.get_rxfh = lan743x_ethtool_get_rxfh,
.set_rxfh = lan743x_ethtool_set_rxfh,
+ .get_ts_info = lan743x_ethtool_get_ts_info,
.get_eee = lan743x_ethtool_get_eee,
.set_eee = lan743x_ethtool_set_eee,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 953b581..ca9ae49 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -267,6 +267,10 @@ static void lan743x_intr_shared_isr(void *context, u32 int_sts, u32 flags)
lan743x_intr_software_isr(adapter);
int_sts &= ~INT_BIT_SW_GP_;
}
+ if (int_sts & INT_BIT_1588_) {
+ lan743x_ptp_isr(adapter);
+ int_sts &= ~INT_BIT_1588_;
+ }
}
if (int_sts)
lan743x_csr_write(adapter, INT_EN_CLR, int_sts);
@@ -976,6 +980,7 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
ksettings.base.duplex,
local_advertisement,
remote_advertisement);
+ lan743x_ptp_update_latency(adapter, ksettings.base.speed);
}
}
@@ -1256,11 +1261,29 @@ static void lan743x_tx_release_desc(struct lan743x_tx *tx,
buffer_info->dma_ptr = 0;
buffer_info->buffer_length = 0;
}
- if (buffer_info->skb) {
+ if (!buffer_info->skb)
+ goto clear_active;
+
+ if (!(buffer_info->flags &
+ TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED)) {
dev_kfree_skb(buffer_info->skb);
- buffer_info->skb = NULL;
+ goto clear_skb;
}
+ if (cleanup) {
+ lan743x_ptp_unrequest_tx_timestamp(tx->adapter);
+ dev_kfree_skb(buffer_info->skb);
+ } else {
+ lan743x_ptp_tx_timestamp_skb(tx->adapter,
+ buffer_info->skb,
+ (buffer_info->flags &
+ TX_BUFFER_INFO_FLAG_IGNORE_SYNC)
+ != 0);
+ }
+
+clear_skb:
+ buffer_info->skb = NULL;
+
clear_active:
buffer_info->flags &= ~TX_BUFFER_INFO_FLAG_ACTIVE;
@@ -1321,10 +1344,25 @@ static int lan743x_tx_get_avail_desc(struct lan743x_tx *tx)
return last_head - last_tail - 1;
}
+void lan743x_tx_set_timestamping_mode(struct lan743x_tx *tx,
+ bool enable_timestamping,
+ bool enable_onestep_sync)
+{
+ if (enable_timestamping)
+ tx->ts_flags |= TX_TS_FLAG_TIMESTAMPING_ENABLED;
+ else
+ tx->ts_flags &= ~TX_TS_FLAG_TIMESTAMPING_ENABLED;
+ if (enable_onestep_sync)
+ tx->ts_flags |= TX_TS_FLAG_ONE_STEP_SYNC;
+ else
+ tx->ts_flags &= ~TX_TS_FLAG_ONE_STEP_SYNC;
+}
+
static int lan743x_tx_frame_start(struct lan743x_tx *tx,
unsigned char *first_buffer,
unsigned int first_buffer_length,
unsigned int frame_length,
+ bool time_stamp,
bool check_sum)
{
/* called only from within lan743x_tx_xmit_frame.
@@ -1362,6 +1400,8 @@ static int lan743x_tx_frame_start(struct lan743x_tx *tx,
TX_DESC_DATA0_DTYPE_DATA_ |
TX_DESC_DATA0_FS_ |
TX_DESC_DATA0_FCS_;
+ if (time_stamp)
+ tx->frame_data0 |= TX_DESC_DATA0_TSE_;
if (check_sum)
tx->frame_data0 |= TX_DESC_DATA0_ICE_ |
@@ -1475,6 +1515,7 @@ static int lan743x_tx_frame_add_fragment(struct lan743x_tx *tx,
static void lan743x_tx_frame_end(struct lan743x_tx *tx,
struct sk_buff *skb,
+ bool time_stamp,
bool ignore_sync)
{
/* called only from within lan743x_tx_xmit_frame
@@ -1492,6 +1533,8 @@ static void lan743x_tx_frame_end(struct lan743x_tx *tx,
tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail];
buffer_info = &tx->buffer_info[tx->frame_tail];
buffer_info->skb = skb;
+ if (time_stamp)
+ buffer_info->flags |= TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED;
if (ignore_sync)
buffer_info->flags |= TX_BUFFER_INFO_FLAG_IGNORE_SYNC;
@@ -1520,6 +1563,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
unsigned int frame_length = 0;
unsigned int head_length = 0;
unsigned long irq_flags = 0;
+ bool do_timestamp = false;
bool ignore_sync = false;
int nr_frags = 0;
bool gso = false;
@@ -1541,6 +1585,16 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
}
/* space available, transmit skb */
+ if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+ if (tx->ts_flags & TX_TS_FLAG_TIMESTAMPING_ENABLED) {
+ if (lan743x_ptp_request_tx_timestamp(tx->adapter)) {
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ do_timestamp = true;
+ if (tx->ts_flags & TX_TS_FLAG_ONE_STEP_SYNC)
+ ignore_sync = true;
+ }
+ }
+ }
head_length = skb_headlen(skb);
frame_length = skb_pagelen(skb);
nr_frags = skb_shinfo(skb)->nr_frags;
@@ -1554,6 +1608,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
if (lan743x_tx_frame_start(tx,
skb->data, head_length,
start_frame_length,
+ do_timestamp,
skb->ip_summed == CHECKSUM_PARTIAL)) {
dev_kfree_skb(skb);
goto unlock;
@@ -1581,7 +1636,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
}
finish:
- lan743x_tx_frame_end(tx, skb, ignore_sync);
+ lan743x_tx_frame_end(tx, skb, do_timestamp, ignore_sync);
unlock:
spin_unlock_irqrestore(&tx->ring_lock, irq_flags);
@@ -2410,6 +2465,8 @@ static int lan743x_netdev_close(struct net_device *netdev)
for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++)
lan743x_rx_close(&adapter->rx[index]);
+ lan743x_ptp_close(adapter);
+
lan743x_phy_close(adapter);
lan743x_mac_close(adapter);
@@ -2437,6 +2494,10 @@ static int lan743x_netdev_open(struct net_device *netdev)
if (ret)
goto close_mac;
+ ret = lan743x_ptp_open(adapter);
+ if (ret)
+ goto close_phy;
+
lan743x_rfe_open(adapter);
for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++) {
@@ -2456,6 +2517,9 @@ static int lan743x_netdev_open(struct net_device *netdev)
if (adapter->rx[index].ring_cpu_ptr)
lan743x_rx_close(&adapter->rx[index]);
}
+ lan743x_ptp_close(adapter);
+
+close_phy:
lan743x_phy_close(adapter);
close_mac:
@@ -2483,6 +2547,8 @@ static int lan743x_netdev_ioctl(struct net_device *netdev,
{
if (!netif_running(netdev))
return -EINVAL;
+ if (cmd == SIOCSHWTSTAMP)
+ return lan743x_ptp_ioctl(netdev, ifr, cmd);
return phy_mii_ioctl(netdev->phydev, ifr, cmd);
}
@@ -2607,6 +2673,11 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
adapter->intr.irq = adapter->pdev->irq;
lan743x_csr_write(adapter, INT_EN_CLR, 0xFFFFFFFF);
mutex_init(&adapter->dp_lock);
+
+ ret = lan743x_gpio_init(adapter);
+ if (ret)
+ return ret;
+
ret = lan743x_mac_init(adapter);
if (ret)
return ret;
@@ -2615,6 +2686,10 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
if (ret)
return ret;
+ ret = lan743x_ptp_init(adapter);
+ if (ret)
+ return ret;
+
lan743x_rfe_update_mac_address(adapter);
ret = lan743x_dmac_init(adapter);
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 4fa7a5e..578a618 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -4,12 +4,17 @@
#ifndef _LAN743X_H
#define _LAN743X_H
+#include "lan743x_ptp.h"
+
#define DRIVER_AUTHOR "Bryan Whitehead <Bryan.Whitehead@microchip.com>"
#define DRIVER_DESC "LAN743x PCIe Gigabit Ethernet Driver"
#define DRIVER_NAME "lan743x"
/* Register Definitions */
#define ID_REV (0x00)
+#define ID_REV_ID_MASK_ (0xFFFF0000)
+#define ID_REV_ID_LAN7430_ (0x74300000)
+#define ID_REV_ID_LAN7431_ (0x74310000)
#define ID_REV_IS_VALID_CHIP_ID_(id_rev) \
(((id_rev) & 0xFFF00000) == 0x74300000)
#define ID_REV_CHIP_REV_MASK_ (0x0000FFFF)
@@ -62,6 +67,21 @@
#define E2P_DATA (0x044)
+#define GPIO_CFG0 (0x050)
+#define GPIO_CFG0_GPIO_DIR_BIT_(bit) BIT(16 + (bit))
+#define GPIO_CFG0_GPIO_DATA_BIT_(bit) BIT(0 + (bit))
+
+#define GPIO_CFG1 (0x054)
+#define GPIO_CFG1_GPIOEN_BIT_(bit) BIT(16 + (bit))
+#define GPIO_CFG1_GPIOBUF_BIT_(bit) BIT(0 + (bit))
+
+#define GPIO_CFG2 (0x058)
+#define GPIO_CFG2_1588_POL_BIT_(bit) BIT(0 + (bit))
+
+#define GPIO_CFG3 (0x05C)
+#define GPIO_CFG3_1588_CH_SEL_BIT_(bit) BIT(16 + (bit))
+#define GPIO_CFG3_1588_OE_BIT_(bit) BIT(0 + (bit))
+
#define FCT_RX_CTL (0xAC)
#define FCT_RX_CTL_EN_(channel) BIT(28 + (channel))
#define FCT_RX_CTL_DIS_(channel) BIT(24 + (channel))
@@ -193,7 +213,8 @@
#define INT_BIT_DMA_TX_(channel) BIT(16 + (channel))
#define INT_BIT_ALL_TX_ (0x000F0000)
#define INT_BIT_SW_GP_ BIT(9)
-#define INT_BIT_ALL_OTHER_ (0x00000280)
+#define INT_BIT_1588_ BIT(7)
+#define INT_BIT_ALL_OTHER_ (INT_BIT_SW_GP_ | INT_BIT_1588_)
#define INT_BIT_MAS_ BIT(0)
#define INT_SET (0x784)
@@ -234,6 +255,66 @@
#define INT_MOD_CFG6 (0x7D8)
#define INT_MOD_CFG7 (0x7DC)
+#define PTP_CMD_CTL (0x0A00)
+#define PTP_CMD_CTL_PTP_CLK_STP_NSEC_ BIT(6)
+#define PTP_CMD_CTL_PTP_CLOCK_STEP_SEC_ BIT(5)
+#define PTP_CMD_CTL_PTP_CLOCK_LOAD_ BIT(4)
+#define PTP_CMD_CTL_PTP_CLOCK_READ_ BIT(3)
+#define PTP_CMD_CTL_PTP_ENABLE_ BIT(2)
+#define PTP_CMD_CTL_PTP_DISABLE_ BIT(1)
+#define PTP_CMD_CTL_PTP_RESET_ BIT(0)
+#define PTP_GENERAL_CONFIG (0x0A04)
+#define PTP_GENERAL_CONFIG_CLOCK_EVENT_X_MASK_(channel) \
+ (0x7 << (1 + ((channel) << 2)))
+#define PTP_GENERAL_CONFIG_CLOCK_EVENT_100US_ (2)
+#define PTP_GENERAL_CONFIG_CLOCK_EVENT_X_SET_(channel, value) \
+ (((value) & 0x7) << (1 + ((channel) << 2)))
+#define PTP_GENERAL_CONFIG_RELOAD_ADD_X_(channel) (BIT((channel) << 2))
+
+#define PTP_INT_STS (0x0A08)
+#define PTP_INT_EN_SET (0x0A0C)
+#define PTP_INT_EN_CLR (0x0A10)
+#define PTP_INT_BIT_TX_SWTS_ERR_ BIT(13)
+#define PTP_INT_BIT_TX_TS_ BIT(12)
+#define PTP_INT_BIT_TIMER_B_ BIT(1)
+#define PTP_INT_BIT_TIMER_A_ BIT(0)
+
+#define PTP_CLOCK_SEC (0x0A14)
+#define PTP_CLOCK_NS (0x0A18)
+#define PTP_CLOCK_SUBNS (0x0A1C)
+#define PTP_CLOCK_RATE_ADJ (0x0A20)
+#define PTP_CLOCK_RATE_ADJ_DIR_ BIT(31)
+#define PTP_CLOCK_STEP_ADJ (0x0A2C)
+#define PTP_CLOCK_STEP_ADJ_DIR_ BIT(31)
+#define PTP_CLOCK_STEP_ADJ_VALUE_MASK_ (0x3FFFFFFF)
+#define PTP_CLOCK_TARGET_SEC_X(channel) (0x0A30 + ((channel) << 4))
+#define PTP_CLOCK_TARGET_NS_X(channel) (0x0A34 + ((channel) << 4))
+#define PTP_CLOCK_TARGET_RELOAD_SEC_X(channel) (0x0A38 + ((channel) << 4))
+#define PTP_CLOCK_TARGET_RELOAD_NS_X(channel) (0x0A3C + ((channel) << 4))
+#define PTP_LATENCY (0x0A5C)
+#define PTP_LATENCY_TX_SET_(tx_latency) (((u32)(tx_latency)) << 16)
+#define PTP_LATENCY_RX_SET_(rx_latency) \
+ (((u32)(rx_latency)) & 0x0000FFFF)
+#define PTP_CAP_INFO (0x0A60)
+#define PTP_CAP_INFO_TX_TS_CNT_GET_(reg_val) ((reg_val & 0x00000070) >> 4)
+
+#define PTP_TX_MOD (0x0AA4)
+#define PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_ (0x10000000)
+
+#define PTP_TX_MOD2 (0x0AA8)
+#define PTP_TX_MOD2_TX_PTP_CLR_UDPV4_CHKSUM_ (0x00000001)
+
+#define PTP_TX_EGRESS_SEC (0x0AAC)
+#define PTP_TX_EGRESS_NS (0x0AB0)
+#define PTP_TX_EGRESS_NS_CAPTURE_CAUSE_MASK_ (0xC0000000)
+#define PTP_TX_EGRESS_NS_CAPTURE_CAUSE_AUTO_ (0x00000000)
+#define PTP_TX_EGRESS_NS_CAPTURE_CAUSE_SW_ (0x40000000)
+#define PTP_TX_EGRESS_NS_TS_NS_MASK_ (0x3FFFFFFF)
+
+#define PTP_TX_MSG_HEADER (0x0AB4)
+#define PTP_TX_MSG_HEADER_MSG_TYPE_ (0x000F0000)
+#define PTP_TX_MSG_HEADER_MSG_TYPE_SYNC_ (0x00000000)
+
#define DMAC_CFG (0xC00)
#define DMAC_CFG_COAL_EN_ BIT(16)
#define DMAC_CFG_CH_ARB_SEL_RX_HIGH_ (0x00000000)
@@ -542,8 +623,12 @@ struct lan743x_tx_buffer_info;
#define TX_FRAME_FLAG_IN_PROGRESS BIT(0)
+#define TX_TS_FLAG_TIMESTAMPING_ENABLED BIT(0)
+#define TX_TS_FLAG_ONE_STEP_SYNC BIT(1)
+
struct lan743x_tx {
struct lan743x_adapter *adapter;
+ u32 ts_flags;
u32 vector_flags;
int channel_number;
@@ -570,6 +655,10 @@ struct lan743x_tx {
struct sk_buff *overflow_skb;
};
+void lan743x_tx_set_timestamping_mode(struct lan743x_tx *tx,
+ bool enable_timestamping,
+ bool enable_onestep_sync);
+
/* RX */
struct lan743x_rx_descriptor;
struct lan743x_rx_buffer_info;
@@ -610,6 +699,9 @@ struct lan743x_adapter {
/* lock, used to prevent concurrent access to data port */
struct mutex dp_lock;
+ struct lan743x_gpio gpio;
+ struct lan743x_ptp ptp;
+
u8 mac_address[ETH_ALEN];
struct lan743x_phy phy;
@@ -660,6 +752,7 @@ struct lan743x_adapter {
#define TX_DESC_DATA0_IPE_ (0x00200000)
#define TX_DESC_DATA0_TPE_ (0x00100000)
#define TX_DESC_DATA0_FCS_ (0x00020000)
+#define TX_DESC_DATA0_TSE_ (0x00010000)
#define TX_DESC_DATA0_BUF_LENGTH_MASK_ (0x0000FFFF)
#define TX_DESC_DATA0_EXT_LSO_ (0x00200000)
#define TX_DESC_DATA0_EXT_PAY_LENGTH_MASK_ (0x000FFFFF)
@@ -673,6 +766,7 @@ struct lan743x_tx_descriptor {
} __aligned(DEFAULT_DMA_DESCRIPTOR_SPACING);
#define TX_BUFFER_INFO_FLAG_ACTIVE BIT(0)
+#define TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED BIT(1)
#define TX_BUFFER_INFO_FLAG_IGNORE_SYNC BIT(2)
#define TX_BUFFER_INFO_FLAG_SKB_FRAGMENT BIT(3)
struct lan743x_tx_buffer_info {
diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c
new file mode 100644
index 0000000..f14565b
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan743x_ptp.c
@@ -0,0 +1,1194 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2018 Microchip Technology Inc. */
+
+#include <linux/netdevice.h>
+#include "lan743x_main.h"
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/net_tstamp.h>
+
+#include "lan743x_ptp.h"
+
+/* GPIO */
+#define LAN743X_NUMBER_OF_GPIO (12)
+
+int lan743x_gpio_init(struct lan743x_adapter *adapter)
+{
+ struct lan743x_gpio *gpio = &adapter->gpio;
+
+ spin_lock_init(&gpio->gpio_lock);
+
+ gpio->gpio_cfg0 = 0; /* set all direction to input, data = 0 */
+ gpio->gpio_cfg1 = 0x0FFF0000;/* disable all gpio, set to open drain */
+ gpio->gpio_cfg2 = 0;/* set all to 1588 low polarity level */
+ gpio->gpio_cfg3 = 0;/* disable all 1588 output */
+ lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
+ lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
+ lan743x_csr_write(adapter, GPIO_CFG2, gpio->gpio_cfg2);
+ lan743x_csr_write(adapter, GPIO_CFG3, gpio->gpio_cfg3);
+
+ return 0;
+}
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_gpio_reserve_ptp_output(struct lan743x_adapter *adapter,
+ int bit, int ptp_channel)
+{
+ struct lan743x_gpio *gpio = &adapter->gpio;
+ unsigned long irq_flags = 0;
+ int bit_mask = BIT(bit);
+ int ret = -EBUSY;
+
+ spin_lock_irqsave(&gpio->gpio_lock, irq_flags);
+
+ if (!(gpio->used_bits & bit_mask)) {
+ gpio->used_bits |= bit_mask;
+ gpio->output_bits |= bit_mask;
+ gpio->ptp_bits |= bit_mask;
+
+ /* set as output, and zero initial value */
+ gpio->gpio_cfg0 |= GPIO_CFG0_GPIO_DIR_BIT_(bit);
+ gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DATA_BIT_(bit);
+ lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
+
+ /* enable gpio , and set buffer type to push pull */
+ gpio->gpio_cfg1 &= ~GPIO_CFG1_GPIOEN_BIT_(bit);
+ gpio->gpio_cfg1 |= GPIO_CFG1_GPIOBUF_BIT_(bit);
+ lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
+
+ /* set 1588 polarity to high */
+ gpio->gpio_cfg2 |= GPIO_CFG2_1588_POL_BIT_(bit);
+ lan743x_csr_write(adapter, GPIO_CFG2, gpio->gpio_cfg2);
+
+ if (!ptp_channel) {
+ /* use channel A */
+ gpio->gpio_cfg3 &= ~GPIO_CFG3_1588_CH_SEL_BIT_(bit);
+ } else {
+ /* use channel B */
+ gpio->gpio_cfg3 |= GPIO_CFG3_1588_CH_SEL_BIT_(bit);
+ }
+ gpio->gpio_cfg3 |= GPIO_CFG3_1588_OE_BIT_(bit);
+ lan743x_csr_write(adapter, GPIO_CFG3, gpio->gpio_cfg3);
+
+ ret = bit;
+ }
+ spin_unlock_irqrestore(&gpio->gpio_lock, irq_flags);
+ return ret;
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_gpio_release(struct lan743x_adapter *adapter, int bit)
+{
+ struct lan743x_gpio *gpio = &adapter->gpio;
+ unsigned long irq_flags = 0;
+ int bit_mask = BIT(bit);
+
+ spin_lock_irqsave(&gpio->gpio_lock, irq_flags);
+ if (gpio->used_bits & bit_mask) {
+ gpio->used_bits &= ~bit_mask;
+ if (gpio->output_bits & bit_mask) {
+ gpio->output_bits &= ~bit_mask;
+
+ if (gpio->ptp_bits & bit_mask) {
+ gpio->ptp_bits &= ~bit_mask;
+ /* disable ptp output */
+ gpio->gpio_cfg3 &= ~GPIO_CFG3_1588_OE_BIT_(bit);
+ lan743x_csr_write(adapter, GPIO_CFG3,
+ gpio->gpio_cfg3);
+ }
+ /* release gpio output */
+
+ /* disable gpio */
+ gpio->gpio_cfg1 |= GPIO_CFG1_GPIOEN_BIT_(bit);
+ gpio->gpio_cfg1 &= ~GPIO_CFG1_GPIOBUF_BIT_(bit);
+ lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
+
+ /* reset back to input */
+ gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DIR_BIT_(bit);
+ gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DATA_BIT_(bit);
+ lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
+ }
+ }
+ spin_unlock_irqrestore(&gpio->gpio_lock, irq_flags);
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+/* PTP */
+#define LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB (31249999)
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptp_reserve_event_ch(struct lan743x_adapter *adapter);
+static void lan743x_ptp_release_event_ch(struct lan743x_adapter *adapter,
+ int event_channel);
+#endif
+
+static bool lan743x_ptp_is_enabled(struct lan743x_adapter *adapter);
+static void lan743x_ptp_enable(struct lan743x_adapter *adapter);
+static void lan743x_ptp_disable(struct lan743x_adapter *adapter);
+static void lan743x_ptp_reset(struct lan743x_adapter *adapter);
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_clock_get(struct lan743x_adapter *adapter,
+ u32 *seconds, u32 *nano_seconds,
+ u32 *sub_nano_seconds);
+static int lan743x_ptp_enable_pps(struct lan743x_adapter *adapter);
+static void lan743x_ptp_disable_pps(struct lan743x_adapter *adapter);
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
+ s64 time_step_ns);
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+static void lan743x_ptp_clock_set(struct lan743x_adapter *adapter,
+ u32 seconds, u32 nano_seconds,
+ u32 sub_nano_seconds);
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_adjfreq(struct ptp_clock_info *ptpci, s32 delta_ppb)
+{
+ struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+ ptp_clock_info);
+ struct lan743x_adapter *adapter = container_of(ptp,
+ struct lan743x_adapter,
+ ptp);
+ u32 lan743x_rate_adj = 0;
+ bool positive = true;
+ u32 u32_delta = 0;
+ u64 u64_delta = 0;
+
+ if ((delta_ppb < (-LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB)) ||
+ delta_ppb > LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB) {
+ return -EINVAL;
+ }
+ if (delta_ppb > 0) {
+ u32_delta = (u32)delta_ppb;
+ positive = true;
+ } else {
+ u32_delta = (u32)(-delta_ppb);
+ positive = false;
+ }
+ u64_delta = (((u64)u32_delta) * 0x800000000ULL);
+ lan743x_rate_adj = (u32)(u64_delta / 1000000000);
+
+ if (positive)
+ lan743x_rate_adj |= PTP_CLOCK_RATE_ADJ_DIR_;
+
+ lan743x_csr_write(adapter, PTP_CLOCK_RATE_ADJ,
+ lan743x_rate_adj);
+
+ netif_info(adapter, drv, adapter->netdev,
+ "adjfreq, delta_ppb = %d, lan743x_rate_adj = 0x%08X\n",
+ delta_ppb, lan743x_rate_adj);
+ return 0;
+}
+#endif /*CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_adjtime(struct ptp_clock_info *ptpci, s64 delta)
+{
+ struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+ ptp_clock_info);
+ struct lan743x_adapter *adapter = container_of(ptp,
+ struct lan743x_adapter,
+ ptp);
+ bool enable_pps = false;
+
+ if (ptp->pps_event_ch >= 0) {
+ lan743x_ptp_disable_pps(adapter);
+ enable_pps = true;
+ }
+
+ lan743x_ptp_clock_step(adapter, delta);
+ netif_info(adapter, drv, adapter->netdev,
+ "adjtime, delta = %lld\n", delta);
+
+ if (enable_pps)
+ lan743x_ptp_enable_pps(adapter);
+
+ return 0;
+}
+#endif /*CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_gettime64(struct ptp_clock_info *ptpci,
+ struct timespec64 *ts)
+{
+ struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+ ptp_clock_info);
+ struct lan743x_adapter *adapter = container_of(ptp,
+ struct lan743x_adapter,
+ ptp);
+
+ if (ts) {
+ u32 seconds = 0;
+ u32 nano_seconds = 0;
+
+ lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
+ ts->tv_sec = seconds;
+ ts->tv_nsec = nano_seconds;
+ netif_info(adapter, drv, adapter->netdev,
+ "gettime = %u.%09u\n", seconds, nano_seconds);
+ } else {
+ netif_warn(adapter, drv, adapter->netdev, "ts == NULL\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+#endif /*CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_settime64(struct ptp_clock_info *ptpci,
+ const struct timespec64 *ts)
+{
+ struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+ ptp_clock_info);
+ struct lan743x_adapter *adapter = container_of(ptp,
+ struct lan743x_adapter,
+ ptp);
+ bool enable_pps = false;
+
+ if (ptp->pps_event_ch >= 0) {
+ lan743x_ptp_disable_pps(adapter);
+ enable_pps = true;
+ }
+
+ if (ts) {
+ u32 seconds = 0;
+ u32 nano_seconds = 0;
+
+ if (ts->tv_sec > 0xFFFFFFFFLL ||
+ ts->tv_sec < 0) {
+ netif_warn(adapter, drv, adapter->netdev,
+ "ts->tv_sec out of range, %lld\n",
+ ts->tv_sec);
+ return -EINVAL;
+ }
+ if (ts->tv_nsec >= 1000000000L ||
+ ts->tv_nsec < 0) {
+ netif_warn(adapter, drv, adapter->netdev,
+ "ts->tv_nsec out of range, %ld\n",
+ ts->tv_nsec);
+ return -EINVAL;
+ }
+ seconds = ts->tv_sec;
+ nano_seconds = ts->tv_nsec;
+ netif_info(adapter, drv, adapter->netdev,
+ "settime = %u.%09u\n", seconds, nano_seconds);
+ lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
+ } else {
+ netif_warn(adapter, drv, adapter->netdev, "ts == NULL\n");
+ return -EINVAL;
+ }
+
+ if (enable_pps)
+ lan743x_ptp_enable_pps(adapter);
+
+ return 0;
+}
+#endif /*CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptp_enable_pps(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+ u32 current_seconds = 0;
+ u32 target_seconds = 0;
+ u32 general_config = 0;
+ int result = -ENODEV;
+ int pps_bit = 0;
+
+ if (ptp->pps_event_ch >= 0) {
+ result = 0;
+ goto done;
+ }
+
+ ptp->pps_event_ch = lan743x_ptp_reserve_event_ch(adapter);
+ if (ptp->pps_event_ch < 0) {
+ netif_warn(adapter, drv, adapter->netdev,
+ "Failed to reserve event channel for PPS\n");
+ goto done;
+ }
+
+ switch(adapter->csr.id_rev & ID_REV_ID_MASK_) {
+ case ID_REV_ID_LAN7430_:
+ pps_bit = 2;/* GPIO 2 is preferred on EVB LAN7430 */
+ break;
+ case ID_REV_ID_LAN7431_:
+ pps_bit = 4;/* GPIO 4 is preferred on EVB LAN7431 */
+ break;
+ }
+
+ ptp->pps_gpio_bit = lan743x_gpio_reserve_ptp_output(adapter, pps_bit,
+ ptp->pps_event_ch);
+
+ if (ptp->pps_gpio_bit < 0) {
+ netif_warn(adapter, drv, adapter->netdev,
+ "Failed to reserve gpio 0 for PPS\n");
+ goto done;
+ }
+
+ lan743x_ptp_clock_get(adapter, ¤t_seconds, NULL, NULL);
+
+ /* set the first target ahead by 2 seconds
+ * to make sure its not missed
+ */
+ target_seconds = current_seconds + 2;
+
+ /* set the new target */
+ lan743x_csr_write(adapter,
+ PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
+ 0xFFFF0000);
+ lan743x_csr_write(adapter,
+ PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch), 0);
+
+ general_config = lan743x_csr_read(adapter, PTP_GENERAL_CONFIG);
+
+ general_config &= ~(PTP_GENERAL_CONFIG_CLOCK_EVENT_X_MASK_
+ (ptp->pps_event_ch));
+ general_config |= PTP_GENERAL_CONFIG_CLOCK_EVENT_X_SET_
+ (ptp->pps_event_ch,
+ PTP_GENERAL_CONFIG_CLOCK_EVENT_100US_);
+ general_config &= ~PTP_GENERAL_CONFIG_RELOAD_ADD_X_
+ (ptp->pps_event_ch);
+ lan743x_csr_write(adapter, PTP_GENERAL_CONFIG, general_config);
+
+ /* set the reload to one second steps */
+ lan743x_csr_write(adapter,
+ PTP_CLOCK_TARGET_RELOAD_SEC_X(ptp->pps_event_ch),
+ 1);
+ lan743x_csr_write(adapter,
+ PTP_CLOCK_TARGET_RELOAD_NS_X(ptp->pps_event_ch),
+ 0);
+
+ /* set the new target */
+ lan743x_csr_write(adapter,
+ PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
+ target_seconds);
+ lan743x_csr_write(adapter,
+ PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch),
+ 0);
+ return 0;
+
+done:
+ if (ptp->pps_gpio_bit >= 0) {
+ lan743x_gpio_release(adapter, ptp->pps_gpio_bit);
+ ptp->pps_gpio_bit = -1;
+ }
+ if (ptp->pps_event_ch >= 0) {
+ lan743x_ptp_release_event_ch(adapter,
+ ptp->pps_event_ch);
+ ptp->pps_event_ch = -1;
+ }
+ return result;
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_disable_pps(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ if (ptp->pps_gpio_bit >= 0) {
+ lan743x_gpio_release(adapter, ptp->pps_gpio_bit);
+ ptp->pps_gpio_bit = -1;
+ }
+
+ if (ptp->pps_event_ch >= 0) {
+ u32 general_config = 0;
+
+ /* set target to far in the future, effectively disabling it */
+ lan743x_csr_write(adapter,
+ PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
+ 0xFFFF0000);
+ lan743x_csr_write(adapter,
+ PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch), 0);
+
+ general_config = lan743x_csr_read(adapter, PTP_GENERAL_CONFIG);
+ general_config |= PTP_GENERAL_CONFIG_RELOAD_ADD_X_
+ (ptp->pps_event_ch);
+ lan743x_csr_write(adapter, PTP_GENERAL_CONFIG, general_config);
+ lan743x_ptp_release_event_ch(adapter, ptp->pps_event_ch);
+ ptp->pps_event_ch = -1;
+ }
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_enable(struct ptp_clock_info *ptpci,
+ struct ptp_clock_request *request, int on)
+{
+ struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+ ptp_clock_info);
+ struct lan743x_adapter *adapter = container_of(ptp,
+ struct lan743x_adapter,
+ ptp);
+
+ if (request) {
+ switch (request->type) {
+ case PTP_CLK_REQ_EXTTS:
+ return -EINVAL;
+ case PTP_CLK_REQ_PEROUT:
+ return -EINVAL;
+ case PTP_CLK_REQ_PPS:
+ if (on) {
+ if (lan743x_ptp_enable_pps(adapter) >= 0)
+ netif_info(adapter, drv,
+ adapter->netdev,
+ "PPS is ON\n");
+ else
+ netif_warn(adapter, drv,
+ adapter->netdev,
+ "Error starting PPS\n");
+ } else {
+ lan743x_ptp_disable_pps(adapter);
+ netif_info(adapter, drv, adapter->netdev,
+ "PPS is OFF\n");
+ }
+ break;
+ default:
+ netif_err(adapter, drv, adapter->netdev,
+ "request->type == %d, Unknown\n",
+ request->type);
+ break;
+ }
+ } else {
+ netif_err(adapter, drv, adapter->netdev, "request == NULL\n");
+ }
+ return 0;
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+void lan743x_ptp_isr(void *context)
+{
+ struct lan743x_adapter *adapter = (struct lan743x_adapter *)context;
+ struct lan743x_ptp *ptp = NULL;
+ int enable_flag = 1;
+ u32 ptp_int_sts = 0;
+
+ ptp = &adapter->ptp;
+
+ lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_1588_);
+
+ ptp_int_sts = lan743x_csr_read(adapter, PTP_INT_STS);
+ ptp_int_sts &= lan743x_csr_read(adapter, PTP_INT_EN_SET);
+
+ if (ptp_int_sts & PTP_INT_BIT_TX_TS_) {
+ tasklet_schedule(&ptp->ptp_isr_bottom_half);
+ enable_flag = 0;/* tasklet will re-enable later */
+ }
+ if (ptp_int_sts & PTP_INT_BIT_TX_SWTS_ERR_) {
+ netif_err(adapter, drv, adapter->netdev,
+ "PTP TX Software Timestamp Error\n");
+ /* clear int status bit */
+ lan743x_csr_write(adapter, PTP_INT_STS,
+ PTP_INT_BIT_TX_SWTS_ERR_);
+ }
+ if (ptp_int_sts & PTP_INT_BIT_TIMER_B_) {
+ netif_info(adapter, drv, adapter->netdev,
+ "PTP TIMER B Interrupt\n");
+ /* clear int status bit */
+ lan743x_csr_write(adapter, PTP_INT_STS,
+ PTP_INT_BIT_TIMER_B_);
+ }
+ if (ptp_int_sts & PTP_INT_BIT_TIMER_A_) {
+ netif_info(adapter, drv, adapter->netdev,
+ "PTP TIMER A Interrupt\n");
+ /* clear int status bit */
+ lan743x_csr_write(adapter, PTP_INT_STS,
+ PTP_INT_BIT_TIMER_A_);
+ }
+
+ if (enable_flag) {
+ /* re-enable isr */
+ lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
+ }
+}
+
+static void lan743x_ptp_tx_ts_complete(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+ int i;
+ int c;
+
+ spin_lock_bh(&ptp->tx_ts_lock);
+ c = ptp->tx_ts_skb_queue_size;
+
+ if (c > ptp->tx_ts_queue_size)
+ c = ptp->tx_ts_queue_size;
+ if (c <= 0)
+ goto done;
+
+ for (i = 0; i < c; i++) {
+ bool ignore_sync = ((ptp->tx_ts_ignore_sync_queue &
+ BIT(i)) != 0);
+ struct sk_buff *skb = ptp->tx_ts_skb_queue[i];
+ u32 nseconds = ptp->tx_ts_nseconds_queue[i];
+ u32 seconds = ptp->tx_ts_seconds_queue[i];
+ u32 header = ptp->tx_ts_header_queue[i];
+ struct skb_shared_hwtstamps tstamps;
+
+ memset(&tstamps, 0, sizeof(tstamps));
+ tstamps.hwtstamp = ktime_set(seconds, nseconds);
+ if (!ignore_sync ||
+ ((header & PTP_TX_MSG_HEADER_MSG_TYPE_) !=
+ PTP_TX_MSG_HEADER_MSG_TYPE_SYNC_))
+ skb_tstamp_tx(skb, &tstamps);
+
+ dev_kfree_skb(skb);
+
+ ptp->tx_ts_skb_queue[i] = NULL;
+ ptp->tx_ts_seconds_queue[i] = 0;
+ ptp->tx_ts_nseconds_queue[i] = 0;
+ ptp->tx_ts_header_queue[i] = 0;
+ }
+
+ /* shift queue */
+ ptp->tx_ts_ignore_sync_queue >>= c;
+ for (i = c; i < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS; i++) {
+ ptp->tx_ts_skb_queue[i - c] = ptp->tx_ts_skb_queue[i];
+ ptp->tx_ts_seconds_queue[i - c] = ptp->tx_ts_seconds_queue[i];
+ ptp->tx_ts_nseconds_queue[i - c] = ptp->tx_ts_nseconds_queue[i];
+ ptp->tx_ts_header_queue[i - c] = ptp->tx_ts_header_queue[i];
+
+ ptp->tx_ts_skb_queue[i] = NULL;
+ ptp->tx_ts_seconds_queue[i] = 0;
+ ptp->tx_ts_nseconds_queue[i] = 0;
+ ptp->tx_ts_header_queue[i] = 0;
+ }
+ ptp->tx_ts_skb_queue_size -= c;
+ ptp->tx_ts_queue_size -= c;
+done:
+ ptp->pending_tx_timestamps -= c;
+ spin_unlock_bh(&ptp->tx_ts_lock);
+}
+
+static void lan743x_ptp_tx_ts_enqueue_skb(struct lan743x_adapter *adapter,
+ struct sk_buff *skb, bool ignore_sync)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ spin_lock_bh(&ptp->tx_ts_lock);
+ if (ptp->tx_ts_skb_queue_size < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
+ ptp->tx_ts_skb_queue[ptp->tx_ts_skb_queue_size] = skb;
+ if (ignore_sync)
+ ptp->tx_ts_ignore_sync_queue |=
+ BIT(ptp->tx_ts_skb_queue_size);
+ ptp->tx_ts_skb_queue_size++;
+ } else {
+ /* this should never happen, so long as the tx channel
+ * calls and honors the result from
+ * lan743x_ptp_request_tx_timestamp
+ */
+ netif_err(adapter, drv, adapter->netdev,
+ "tx ts skb queue overflow\n");
+ dev_kfree_skb(skb);
+ }
+ spin_unlock_bh(&ptp->tx_ts_lock);
+}
+
+static void lan743x_ptp_tx_ts_enqueue_ts(struct lan743x_adapter *adapter,
+ u32 seconds, u32 nano_seconds,
+ u32 header)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ spin_lock_bh(&ptp->tx_ts_lock);
+ if (ptp->tx_ts_queue_size < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
+ ptp->tx_ts_seconds_queue[ptp->tx_ts_queue_size] = seconds;
+ ptp->tx_ts_nseconds_queue[ptp->tx_ts_queue_size] = nano_seconds;
+ ptp->tx_ts_header_queue[ptp->tx_ts_queue_size] = header;
+ ptp->tx_ts_queue_size++;
+ } else {
+ netif_err(adapter, drv, adapter->netdev,
+ "tx ts queue overflow\n");
+ }
+ spin_unlock_bh(&ptp->tx_ts_lock);
+}
+
+static void lan743x_ptp_isr_bottom_half(unsigned long param)
+{
+ struct lan743x_adapter *adapter = (struct lan743x_adapter *)param;
+ bool new_timestamp_available = false;
+
+ while (lan743x_csr_read(adapter, PTP_INT_STS) & PTP_INT_BIT_TX_TS_) {
+ u32 cap_info = lan743x_csr_read(adapter, PTP_CAP_INFO);
+
+ if (PTP_CAP_INFO_TX_TS_CNT_GET_(cap_info) > 0) {
+ u32 seconds = lan743x_csr_read(adapter,
+ PTP_TX_EGRESS_SEC);
+ u32 nsec = lan743x_csr_read(adapter, PTP_TX_EGRESS_NS);
+ u32 cause = (nsec &
+ PTP_TX_EGRESS_NS_CAPTURE_CAUSE_MASK_);
+ u32 header = lan743x_csr_read(adapter,
+ PTP_TX_MSG_HEADER);
+
+ if (cause == PTP_TX_EGRESS_NS_CAPTURE_CAUSE_SW_) {
+ nsec &= PTP_TX_EGRESS_NS_TS_NS_MASK_;
+ lan743x_ptp_tx_ts_enqueue_ts(adapter,
+ seconds, nsec,
+ header);
+ new_timestamp_available = true;
+ } else if (cause ==
+ PTP_TX_EGRESS_NS_CAPTURE_CAUSE_AUTO_) {
+ netif_err(adapter, drv, adapter->netdev,
+ "Auto capture cause not supported\n");
+ } else {
+ netif_warn(adapter, drv, adapter->netdev,
+ "unknown tx timestamp capture cause\n");
+ }
+ } else {
+ netif_warn(adapter, drv, adapter->netdev,
+ "TX TS INT but no TX TS CNT\n");
+ }
+ lan743x_csr_write(adapter, PTP_INT_STS, PTP_INT_BIT_TX_TS_);
+ }
+
+ if (new_timestamp_available)
+ lan743x_ptp_tx_ts_complete(adapter);
+
+ lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
+}
+
+static void lan743x_ptp_sync_to_system_clock(struct lan743x_adapter *adapter)
+{
+ struct timeval tv;
+
+ memset(&tv, 0, sizeof(tv));
+ do_gettimeofday(&tv);
+ lan743x_ptp_clock_set(adapter, tv.tv_sec, tv.tv_usec * 1000, 0);
+}
+
+void lan743x_ptp_update_latency(struct lan743x_adapter *adapter,
+ u32 link_speed)
+{
+ switch (link_speed) {
+ case 10:
+ lan743x_csr_write(adapter, PTP_LATENCY,
+ PTP_LATENCY_TX_SET_(0) |
+ PTP_LATENCY_RX_SET_(0));
+ break;
+ case 100:
+ lan743x_csr_write(adapter, PTP_LATENCY,
+ PTP_LATENCY_TX_SET_(181) |
+ PTP_LATENCY_RX_SET_(594));
+ break;
+ case 1000:
+ lan743x_csr_write(adapter, PTP_LATENCY,
+ PTP_LATENCY_TX_SET_(30) |
+ PTP_LATENCY_RX_SET_(525));
+ break;
+ }
+}
+
+int lan743x_ptp_init(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ mutex_init(&ptp->command_lock);
+ spin_lock_init(&ptp->tx_ts_lock);
+ tasklet_init(&ptp->ptp_isr_bottom_half,
+ lan743x_ptp_isr_bottom_half, (unsigned long)adapter);
+ tasklet_disable(&ptp->ptp_isr_bottom_half);
+ ptp->used_event_ch = 0;
+ ptp->pps_event_ch = -1;
+ ptp->pps_gpio_bit = -1;
+ return 0;
+}
+
+int lan743x_ptp_open(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+ int ret = -ENODEV;
+ u32 temp;
+
+ lan743x_ptp_reset(adapter);
+ lan743x_ptp_sync_to_system_clock(adapter);
+ temp = lan743x_csr_read(adapter, PTP_TX_MOD2);
+ temp |= PTP_TX_MOD2_TX_PTP_CLR_UDPV4_CHKSUM_;
+ lan743x_csr_write(adapter, PTP_TX_MOD2, temp);
+ lan743x_ptp_enable(adapter);
+ tasklet_enable(&ptp->ptp_isr_bottom_half);
+ lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
+ lan743x_csr_write(adapter, PTP_INT_EN_SET,
+ PTP_INT_BIT_TX_SWTS_ERR_ | PTP_INT_BIT_TX_TS_);
+ ptp->flags |= PTP_FLAG_ISR_ENABLED;
+
+#ifdef CONFIG_PTP_1588_CLOCK
+ snprintf(ptp->pin_config[0].name, 32, "lan743x_ptp_pin_0");
+ ptp->pin_config[0].index = 0;
+ ptp->pin_config[0].func = PTP_PF_PEROUT;
+ ptp->pin_config[0].chan = 0;
+
+ ptp->ptp_clock_info.owner = THIS_MODULE;
+ snprintf(ptp->ptp_clock_info.name, 16, "%pm",
+ adapter->netdev->dev_addr);
+ ptp->ptp_clock_info.max_adj = LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB;
+ ptp->ptp_clock_info.n_alarm = 0;
+ ptp->ptp_clock_info.n_ext_ts = 0;
+ ptp->ptp_clock_info.n_per_out = 0;
+ ptp->ptp_clock_info.n_pins = 0;
+ ptp->ptp_clock_info.pps = 1;
+ ptp->ptp_clock_info.pin_config = NULL;
+ ptp->ptp_clock_info.adjfreq = lan743x_ptpci_adjfreq;
+ ptp->ptp_clock_info.adjtime = lan743x_ptpci_adjtime;
+ ptp->ptp_clock_info.gettime64 = lan743x_ptpci_gettime64;
+ ptp->ptp_clock_info.getcrosststamp = NULL;
+ ptp->ptp_clock_info.settime64 = lan743x_ptpci_settime64;
+ ptp->ptp_clock_info.enable = lan743x_ptpci_enable;
+ ptp->ptp_clock_info.verify = NULL;
+
+ ptp->ptp_clock = ptp_clock_register(&ptp->ptp_clock_info,
+ &adapter->pdev->dev);
+
+ if (IS_ERR(ptp->ptp_clock)) {
+ netif_err(adapter, ifup, adapter->netdev,
+ "ptp_clock_register failed\n");
+ goto done;
+ }
+ ptp->flags |= PTP_FLAG_PTP_CLOCK_REGISTERED;
+ netif_info(adapter, ifup, adapter->netdev,
+ "successfully registered ptp clock\n");
+#endif
+
+ return 0;
+
+#ifdef CONFIG_PTP_1588_CLOCK
+done:
+ lan743x_ptp_close(adapter);
+ return ret;
+#endif
+}
+
+void lan743x_ptp_close(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+ int index;
+
+#ifdef CONFIG_PTP_1588_CLOCK
+ if (ptp->flags & PTP_FLAG_PTP_CLOCK_REGISTERED) {
+ ptp_clock_unregister(ptp->ptp_clock);
+ ptp->ptp_clock = NULL;
+ ptp->flags &= ~PTP_FLAG_PTP_CLOCK_REGISTERED;
+ netif_info(adapter, drv, adapter->netdev,
+ "ptp clock unregister\n");
+ }
+#endif
+
+ if (ptp->flags & PTP_FLAG_ISR_ENABLED) {
+ lan743x_csr_write(adapter, PTP_INT_EN_CLR,
+ PTP_INT_BIT_TX_SWTS_ERR_ |
+ PTP_INT_BIT_TX_TS_);
+ lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_1588_);
+ tasklet_disable(&ptp->ptp_isr_bottom_half);
+ ptp->flags &= ~PTP_FLAG_ISR_ENABLED;
+ }
+
+ /* clean up pending timestamp requests */
+ lan743x_ptp_tx_ts_complete(adapter);
+ spin_lock_bh(&ptp->tx_ts_lock);
+ for (index = 0;
+ index < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS;
+ index++) {
+ struct sk_buff *skb = ptp->tx_ts_skb_queue[index];
+
+ if (skb)
+ dev_kfree_skb(skb);
+ ptp->tx_ts_skb_queue[index] = NULL;
+ ptp->tx_ts_seconds_queue[index] = 0;
+ ptp->tx_ts_nseconds_queue[index] = 0;
+ }
+ ptp->tx_ts_skb_queue_size = 0;
+ ptp->tx_ts_queue_size = 0;
+ ptp->pending_tx_timestamps = 0;
+ spin_unlock_bh(&ptp->tx_ts_lock);
+
+ lan743x_ptp_disable(adapter);
+}
+
+void lan743x_ptp_set_sync_ts_insert(struct lan743x_adapter *adapter,
+ bool ts_insert_enable)
+{
+ u32 ptp_tx_mod = lan743x_csr_read(adapter, PTP_TX_MOD);
+
+ if (ts_insert_enable)
+ ptp_tx_mod |= PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_;
+ else
+ ptp_tx_mod &= ~PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_;
+
+ lan743x_csr_write(adapter, PTP_TX_MOD, ptp_tx_mod);
+}
+
+static bool lan743x_ptp_is_enabled(struct lan743x_adapter *adapter)
+{
+ if (lan743x_csr_read(adapter, PTP_CMD_CTL) & PTP_CMD_CTL_PTP_ENABLE_)
+ return true;
+ return false;
+}
+
+static void lan743x_ptp_wait_till_cmd_done(struct lan743x_adapter *adapter,
+ u32 bit_mask)
+{
+ int timeout = 1000;
+ u32 data = 0;
+
+ while (timeout &&
+ (data = (lan743x_csr_read(adapter, PTP_CMD_CTL) &
+ bit_mask))) {
+ usleep_range(1000, 20000);
+ timeout--;
+ }
+ if (data) {
+ netif_err(adapter, drv, adapter->netdev,
+ "timeout waiting for cmd to be done, cmd = 0x%08X\n",
+ bit_mask);
+ }
+}
+
+static void lan743x_ptp_enable(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ mutex_lock(&ptp->command_lock);
+
+ if (lan743x_ptp_is_enabled(adapter)) {
+ netif_warn(adapter, drv, adapter->netdev,
+ "PTP already enabled\n");
+ goto done;
+ }
+ lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_);
+done:
+ mutex_unlock(&ptp->command_lock);
+}
+
+static void lan743x_ptp_disable(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ mutex_lock(&ptp->command_lock);
+ if (!lan743x_ptp_is_enabled(adapter)) {
+ netif_warn(adapter, drv, adapter->netdev,
+ "PTP already disabled\n");
+ goto done;
+ }
+ lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_DISABLE_);
+ lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_ENABLE_);
+done:
+ mutex_unlock(&ptp->command_lock);
+}
+
+static void lan743x_ptp_reset(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ mutex_lock(&ptp->command_lock);
+
+ if (lan743x_ptp_is_enabled(adapter)) {
+ netif_err(adapter, drv, adapter->netdev,
+ "Attempting reset while enabled\n");
+ goto done;
+ }
+
+ lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_RESET_);
+ lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_RESET_);
+done:
+ mutex_unlock(&ptp->command_lock);
+}
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptp_reserve_event_ch(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+ int result = -ENODEV;
+ int index = 0;
+
+ mutex_lock(&ptp->command_lock);
+ for (index = 0; index < LAN743X_PTP_NUMBER_OF_EVENT_CHANNELS; index++) {
+ if (!(test_bit(index, &ptp->used_event_ch))) {
+ ptp->used_event_ch |= BIT(index);
+ result = index;
+ break;
+ }
+ }
+ mutex_unlock(&ptp->command_lock);
+ return result;
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_release_event_ch(struct lan743x_adapter *adapter,
+ int event_channel)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ mutex_lock(&ptp->command_lock);
+ if (test_bit(event_channel, &ptp->used_event_ch)) {
+ ptp->used_event_ch &= ~BIT(event_channel);
+ } else {
+ netif_warn(adapter, drv, adapter->netdev,
+ "attempted release on a not used event_channel = %d\n",
+ event_channel);
+ }
+ mutex_unlock(&ptp->command_lock);
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_clock_get(struct lan743x_adapter *adapter,
+ u32 *seconds, u32 *nano_seconds,
+ u32 *sub_nano_seconds)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ mutex_lock(&ptp->command_lock);
+
+ lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_READ_);
+ lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_CLOCK_READ_);
+
+ if (seconds)
+ (*seconds) = lan743x_csr_read(adapter, PTP_CLOCK_SEC);
+
+ if (nano_seconds)
+ (*nano_seconds) = lan743x_csr_read(adapter, PTP_CLOCK_NS);
+
+ if (sub_nano_seconds)
+ (*sub_nano_seconds) =
+ lan743x_csr_read(adapter, PTP_CLOCK_SUBNS);
+
+ mutex_unlock(&ptp->command_lock);
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+static void lan743x_ptp_clock_set(struct lan743x_adapter *adapter,
+ u32 seconds, u32 nano_seconds,
+ u32 sub_nano_seconds)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ mutex_lock(&ptp->command_lock);
+
+ lan743x_csr_write(adapter, PTP_CLOCK_SEC, seconds);
+ lan743x_csr_write(adapter, PTP_CLOCK_NS, nano_seconds);
+ lan743x_csr_write(adapter, PTP_CLOCK_SUBNS, sub_nano_seconds);
+
+ lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_LOAD_);
+ lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_CLOCK_LOAD_);
+ mutex_unlock(&ptp->command_lock);
+}
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
+ s64 time_step_ns)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+ u64 abs_time_step_ns = 0;
+ u32 nano_seconds = 0;
+ s32 seconds = 0;
+
+ if (time_step_ns > 15000000000LL) {
+ /* convert to clock set */
+ u32 nano_seconds = 0;
+ u32 seconds = 0;
+
+ lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
+ seconds += (time_step_ns / 1000000000LL);
+ nano_seconds += (time_step_ns % 1000000000LL);
+ if (nano_seconds >= 1000000000) {
+ seconds++;
+ nano_seconds -= 1000000000;
+ }
+ lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
+ return;
+ } else if (time_step_ns < -15000000000LL) {
+ /* convert to clock set */
+ u32 nano_seconds_step = 0;
+ u32 nano_seconds = 0;
+ u32 seconds = 0;
+
+ time_step_ns = -time_step_ns;
+
+ lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
+ seconds -= (time_step_ns / 1000000000LL);
+ nano_seconds_step = (time_step_ns % 1000000000LL);
+ if (nano_seconds < nano_seconds_step) {
+ seconds--;
+ nano_seconds += 1000000000;
+ }
+ nano_seconds -= nano_seconds_step;
+ lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
+ return;
+ }
+
+ /* do clock step */
+
+ if (time_step_ns >= 0) {
+ abs_time_step_ns = (u64)(time_step_ns);
+ seconds = (s32)(abs_time_step_ns / 1000000000);
+ nano_seconds = (u32)(abs_time_step_ns % 1000000000);
+ } else {
+ abs_time_step_ns = (u64)(-time_step_ns);
+ seconds = -((s32)(abs_time_step_ns / 1000000000));
+ nano_seconds = (u32)(abs_time_step_ns % 1000000000);
+ if (nano_seconds > 0) {
+ /* subtracting nano seconds is not allowed
+ * convert to subtracting from seconds,
+ * and adding to nanoseconds
+ */
+ seconds--;
+ nano_seconds = (1000000000 - nano_seconds);
+ }
+ }
+
+ if (nano_seconds > 0) {
+ /* add 8 ns to cover the likely normal increment */
+ nano_seconds += 8;
+ }
+
+ if (nano_seconds >= 1000000000) {
+ /* carry into seconds */
+ seconds++;
+ nano_seconds -= 1000000000;
+ }
+
+ while (seconds) {
+ mutex_lock(&ptp->command_lock);
+ if (seconds > 0) {
+ u32 adjustment_value = (u32)seconds;
+
+ if (adjustment_value > 0xF)
+ adjustment_value = 0xF;
+ lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
+ PTP_CLOCK_STEP_ADJ_DIR_ |
+ adjustment_value);
+ seconds -= ((s32)adjustment_value);
+ } else {
+ u32 adjustment_value = (u32)(-seconds);
+
+ if (adjustment_value > 0xF)
+ adjustment_value = 0xF;
+ lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
+ adjustment_value);
+ seconds += ((s32)adjustment_value);
+ }
+ lan743x_csr_write(adapter, PTP_CMD_CTL,
+ PTP_CMD_CTL_PTP_CLOCK_STEP_SEC_);
+ lan743x_ptp_wait_till_cmd_done(adapter,
+ PTP_CMD_CTL_PTP_CLOCK_STEP_SEC_);
+ mutex_unlock(&ptp->command_lock);
+ }
+ if (nano_seconds) {
+ mutex_lock(&ptp->command_lock);
+ lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
+ PTP_CLOCK_STEP_ADJ_DIR_ |
+ (nano_seconds &
+ PTP_CLOCK_STEP_ADJ_VALUE_MASK_));
+ lan743x_csr_write(adapter, PTP_CMD_CTL,
+ PTP_CMD_CTL_PTP_CLK_STP_NSEC_);
+ lan743x_ptp_wait_till_cmd_done(adapter,
+ PTP_CMD_CTL_PTP_CLK_STP_NSEC_);
+ mutex_unlock(&ptp->command_lock);
+ }
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+bool lan743x_ptp_request_tx_timestamp(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+ bool result = false;
+
+ spin_lock_bh(&ptp->tx_ts_lock);
+ if (ptp->pending_tx_timestamps < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
+ ptp->pending_tx_timestamps++;
+ result = true;/* request granted */
+ }
+ spin_unlock_bh(&ptp->tx_ts_lock);
+ return result;
+}
+
+void lan743x_ptp_unrequest_tx_timestamp(struct lan743x_adapter *adapter)
+{
+ struct lan743x_ptp *ptp = &adapter->ptp;
+
+ spin_lock_bh(&ptp->tx_ts_lock);
+ if (ptp->pending_tx_timestamps > 0)
+ ptp->pending_tx_timestamps--;
+ else
+ netif_err(adapter, drv, adapter->netdev,
+ "unrequest failed, pending_tx_timestamps==0\n");
+ spin_unlock_bh(&ptp->tx_ts_lock);
+}
+
+void lan743x_ptp_tx_timestamp_skb(struct lan743x_adapter *adapter,
+ struct sk_buff *skb, bool ignore_sync)
+{
+ lan743x_ptp_tx_ts_enqueue_skb(adapter, skb, ignore_sync);
+
+ lan743x_ptp_tx_ts_complete(adapter);
+}
+
+int lan743x_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+ struct hwtstamp_config config;
+ int ret = 0;
+ int index;
+
+ if (!ifr) {
+ netif_err(adapter, drv, adapter->netdev,
+ "SIOCSHWTSTAMP, ifr == NULL\n");
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ if (config.flags) {
+ netif_warn(adapter, drv, adapter->netdev,
+ "ignoring hwtstamp_config.flags == 0x%08X, expected 0\n",
+ config.flags);
+ }
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
+ index++)
+ lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+ false, false);
+ lan743x_ptp_set_sync_ts_insert(adapter, false);
+ netif_info(adapter, drv, adapter->netdev,
+ " tx_type = HWTSTAMP_TX_OFF\n");
+ break;
+ case HWTSTAMP_TX_ON:
+ for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
+ index++)
+ lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+ true, false);
+ lan743x_ptp_set_sync_ts_insert(adapter, false);
+ netif_info(adapter, drv, adapter->netdev,
+ " tx_type = HWTSTAMP_TX_ON\n");
+ break;
+ case HWTSTAMP_TX_ONESTEP_SYNC:
+ for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
+ index++)
+ lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+ true, true);
+
+ lan743x_ptp_set_sync_ts_insert(adapter, true);
+ netif_info(adapter, drv, adapter->netdev,
+ " tx_type = HWTSTAMP_TX_ONESTEP_SYNC\n");
+ break;
+ default:
+ netif_info(adapter, drv, adapter->netdev,
+ " tx_type = %d, UNKNOWN\n", config.tx_type);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!ret)
+ return copy_to_user(ifr->ifr_data, &config,
+ sizeof(config)) ? -EFAULT : 0;
+ return ret;
+}
diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.h b/drivers/net/ethernet/microchip/lan743x_ptp.h
new file mode 100644
index 0000000..979ffce
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan743x_ptp.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2018 Microchip Technology Inc. */
+
+#ifndef _LAN743X_PTP_H
+#define _LAN743X_PTP_H
+
+#include "linux/ptp_clock_kernel.h"
+#include "linux/netdevice.h"
+
+struct lan743x_adapter;
+
+/* GPIO */
+struct lan743x_gpio {
+ /* gpio_lock: used to prevent concurrent access to gpio settings */
+ spinlock_t gpio_lock;
+
+ int used_bits;
+ int output_bits;
+ int ptp_bits;
+ u32 gpio_cfg0;
+ u32 gpio_cfg1;
+ u32 gpio_cfg2;
+ u32 gpio_cfg3;
+};
+
+int lan743x_gpio_init(struct lan743x_adapter *adapter);
+
+void lan743x_ptp_isr(void *context);
+bool lan743x_ptp_request_tx_timestamp(struct lan743x_adapter *adapter);
+void lan743x_ptp_unrequest_tx_timestamp(struct lan743x_adapter *adapter);
+void lan743x_ptp_tx_timestamp_skb(struct lan743x_adapter *adapter,
+ struct sk_buff *skb, bool ignore_sync);
+int lan743x_ptp_init(struct lan743x_adapter *adapter);
+int lan743x_ptp_open(struct lan743x_adapter *adapter);
+void lan743x_ptp_close(struct lan743x_adapter *adapter);
+void lan743x_ptp_update_latency(struct lan743x_adapter *adapter,
+ u32 link_speed);
+
+int lan743x_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+
+#define LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS (4)
+
+#define PTP_FLAG_PTP_CLOCK_REGISTERED BIT(1)
+#define PTP_FLAG_ISR_ENABLED BIT(2)
+
+struct lan743x_ptp {
+ int flags;
+
+ /* command_lock: used to prevent concurrent ptp commands */
+ struct mutex command_lock;
+
+#ifdef CONFIG_PTP_1588_CLOCK
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info ptp_clock_info;
+ struct ptp_pin_desc pin_config[1];
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+ struct tasklet_struct ptp_isr_bottom_half;
+
+#define LAN743X_PTP_NUMBER_OF_EVENT_CHANNELS (2)
+ unsigned long used_event_ch;
+
+ int pps_event_ch;
+ int pps_gpio_bit;
+
+ /* tx_ts_lock: used to prevent concurrent access to timestamp arrays */
+ spinlock_t tx_ts_lock;
+ int pending_tx_timestamps;
+ struct sk_buff *tx_ts_skb_queue[LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS];
+ unsigned int tx_ts_ignore_sync_queue;
+ int tx_ts_skb_queue_size;
+ u32 tx_ts_seconds_queue[LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS];
+ u32 tx_ts_nseconds_queue[LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS];
+ u32 tx_ts_header_queue[LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS];
+ int tx_ts_queue_size;
+};
+
+#endif /* _LAN743X_PTP_H */
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net-next 2/2] net: phy: add phy_speed_down and phy_speed_up
From: Andrew Lunn @ 2018-07-12 19:09 UTC (permalink / raw)
To: Heiner Kallweit; +Cc: Florian Fainelli, David Miller, netdev@vger.kernel.org
In-Reply-To: <0354bc0f-4bac-9715-e183-1a74b9cc6f1b@gmail.com>
> Like r8169 also tg3 driver doesn't wait for the speed-down-renegotiation
> to finish. Therefore, even though I share Andrew's concerns, there seem
> to be chips where it's safe to not wait for the renegotiation to finish
> (e.g. because device is in PCI D3 already and can't generate an interrupt).
> Having said that I'd keep the sync parameter for phy_speed_down so that
> the driver can decide.
Hi Heiner
Please put a big fat comment about the dangers of sync=false in the
function header. We want people to known it is dangerous by default,
and should only be used in special conditions, when it is known to be
safe.
Andrew
^ permalink raw reply
* Re: [PATCH net-next 2/2] net: phy: add phy_speed_down and phy_speed_up
From: Heiner Kallweit @ 2018-07-12 19:10 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Florian Fainelli, David Miller, netdev@vger.kernel.org
In-Reply-To: <20180712190945.GC10740@lunn.ch>
On 12.07.2018 21:09, Andrew Lunn wrote:
>> Like r8169 also tg3 driver doesn't wait for the speed-down-renegotiation
>> to finish. Therefore, even though I share Andrew's concerns, there seem
>> to be chips where it's safe to not wait for the renegotiation to finish
>> (e.g. because device is in PCI D3 already and can't generate an interrupt).
>> Having said that I'd keep the sync parameter for phy_speed_down so that
>> the driver can decide.
>
> Hi Heiner
>
> Please put a big fat comment about the dangers of sync=false in the
> function header. We want people to known it is dangerous by default,
> and should only be used in special conditions, when it is known to be
> safe.
> Andrew
>
OK ..
Heiner
^ permalink raw reply
* Re: [PATCH] net: usb: hso: use swap macro in hso_kick_transmit
From: Gustavo A. R. Silva @ 2018-07-12 19:27 UTC (permalink / raw)
To: David Miller; +Cc: linux-usb, netdev, linux-kernel
In-Reply-To: <20180711.225821.1348569242901912298.davem@davemloft.net>
Hi David,
On 07/12/2018 12:58 AM, David Miller wrote:
> From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
> Date: Mon, 9 Jul 2018 10:40:48 -0500
>
>> @@ -1748,14 +1747,11 @@ static void hso_kick_transmit(struct hso_serial *serial)
>> goto out;
>>
>> /* Switch pointers around to avoid memcpy */
>> - temp = serial->tx_buffer;
>> - serial->tx_buffer = serial->tx_data;
>> - serial->tx_data = temp;
>> + swap(serial->tx_buffer, serial->tx_data);
>> serial->tx_data_count = serial->tx_buffer_count;
>> serial->tx_buffer_count = 0;
>>
>> - /* If temp is set, it means we switched buffers */
>> - if (temp && serial->write_data) {
>> + if (serial->write_data) {
>
> I think temp can be NULL here, you have to retain this check.
>
I see. Well, in that case I will check serial->tx_data instead.
Thanks for the feedback.
--
Gustavo
^ permalink raw reply
* Re: [PATCH v3 net-next 00/19] TLS offload rx, netdev & mlx5
From: Boris Pismenny @ 2018-07-12 19:20 UTC (permalink / raw)
To: Dave Watson; +Cc: davem, netdev, aviadye, saeedm
In-Reply-To: <20180712165438.GB32492@macbook-pro-6.local.dhcp.thefacebook.com>
Hi Dave,
On 7/12/2018 12:54 PM, Dave Watson wrote:
> On 07/11/18 10:54 PM, Boris Pismenny wrote:
>> Hi,
>>
>> The following series provides TLS RX inline crypto offload.
>
> All the tls patches look good to me except #10
>
> "tls: Fix zerocopy_from_iter iov handling"
>
> which seems to break the non-device zerocopy flow.
Thanks for reviewing!
Sorry, it seems to break the zerocopy send flow, and I've tested only
with the receive flow offload disabled.
I'll fix it in v4. I think that adding a flag to indicate whether a
revert is needed should do the trick. In the receive flow the revert is
needed to handle potential errors, while in the transmit flow it needs
to be removed.
>
> The integration is very clean, thanks!
>
>>
>> v2->v3:
>> - Fix typo
>> - Adjust cover letter
>> - Fix bug in zero copy flows
>> - Use network byte order for the record number in resync
>> - Adjust the sequence provided in resync
>>
>> v1->v2:
>> - Fix bisectability problems due to variable name changes
>> - Fix potential uninitialized return value
>>
^ permalink raw reply
* Re: [PATCH net-next 2/2] net: phy: add phy_speed_down and phy_speed_up
From: Florian Fainelli @ 2018-07-12 19:25 UTC (permalink / raw)
To: Heiner Kallweit, Andrew Lunn; +Cc: David Miller, netdev@vger.kernel.org
In-Reply-To: <8857b2f4-9aab-fb90-ecad-7b27a6fa991c@gmail.com>
On 07/12/2018 12:10 PM, Heiner Kallweit wrote:
> On 12.07.2018 21:09, Andrew Lunn wrote:
>>> Like r8169 also tg3 driver doesn't wait for the speed-down-renegotiation
>>> to finish. Therefore, even though I share Andrew's concerns, there seem
>>> to be chips where it's safe to not wait for the renegotiation to finish
>>> (e.g. because device is in PCI D3 already and can't generate an interrupt).
>>> Having said that I'd keep the sync parameter for phy_speed_down so that
>>> the driver can decide.
>>
>> Hi Heiner
>>
>> Please put a big fat comment about the dangers of sync=false in the
>> function header. We want people to known it is dangerous by default,
>> and should only be used in special conditions, when it is known to be
>> safe.
>> Andrew
>>
> OK ..
What part do you find dangerous? Magic Packets are UDP packets and they
are not routed (unless specifically taken care of) so there is already
some "lossy" behavior involved with waking-up an Ethernet MAC, I don't
think that is too bad to retry several times until the link comes up.
--
Florian
^ permalink raw reply
* [PATCH v4 net-next 08/19] tls: Fill software context without allocation
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
This patch allows tls_set_sw_offload to fill the context in case it was
already allocated previously.
We will use it in TLS_DEVICE to fill the RX software context.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
net/tls/tls_sw.c | 34 ++++++++++++++++++++++------------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 86e22bc..5073676 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1090,28 +1090,38 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
}
if (tx) {
- sw_ctx_tx = kzalloc(sizeof(*sw_ctx_tx), GFP_KERNEL);
- if (!sw_ctx_tx) {
- rc = -ENOMEM;
- goto out;
+ if (!ctx->priv_ctx_tx) {
+ sw_ctx_tx = kzalloc(sizeof(*sw_ctx_tx), GFP_KERNEL);
+ if (!sw_ctx_tx) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ ctx->priv_ctx_tx = sw_ctx_tx;
+ } else {
+ sw_ctx_tx =
+ (struct tls_sw_context_tx *)ctx->priv_ctx_tx;
}
- crypto_init_wait(&sw_ctx_tx->async_wait);
- ctx->priv_ctx_tx = sw_ctx_tx;
} else {
- sw_ctx_rx = kzalloc(sizeof(*sw_ctx_rx), GFP_KERNEL);
- if (!sw_ctx_rx) {
- rc = -ENOMEM;
- goto out;
+ if (!ctx->priv_ctx_rx) {
+ sw_ctx_rx = kzalloc(sizeof(*sw_ctx_rx), GFP_KERNEL);
+ if (!sw_ctx_rx) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ ctx->priv_ctx_rx = sw_ctx_rx;
+ } else {
+ sw_ctx_rx =
+ (struct tls_sw_context_rx *)ctx->priv_ctx_rx;
}
- crypto_init_wait(&sw_ctx_rx->async_wait);
- ctx->priv_ctx_rx = sw_ctx_rx;
}
if (tx) {
+ crypto_init_wait(&sw_ctx_tx->async_wait);
crypto_info = &ctx->crypto_send;
cctx = &ctx->tx;
aead = &sw_ctx_tx->aead_send;
} else {
+ crypto_init_wait(&sw_ctx_rx->async_wait);
crypto_info = &ctx->crypto_recv;
cctx = &ctx->rx;
aead = &sw_ctx_rx->aead_recv;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 17/19] net/mlx5: Accel, add common metadata functions
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
This patch adds common functions to handle mellanox metadata headers.
These functions are used by IPsec and TLS to process FPGA metadata.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/accel/accel.h | 37 ++++++++++++++++++++++
.../mellanox/mlx5/core/en_accel/ipsec_rxtx.c | 19 +++--------
.../mellanox/mlx5/core/en_accel/tls_rxtx.c | 18 +++--------
3 files changed, 45 insertions(+), 29 deletions(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/accel.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/accel/accel.h b/drivers/net/ethernet/mellanox/mlx5/core/accel/accel.h
new file mode 100644
index 0000000..c132604
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/accel/accel.h
@@ -0,0 +1,37 @@
+#ifndef __MLX5E_ACCEL_H__
+#define __MLX5E_ACCEL_H__
+
+#ifdef CONFIG_MLX5_ACCEL
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include "en.h"
+
+static inline bool is_metadata_hdr_valid(struct sk_buff *skb)
+{
+ __be16 *ethtype;
+
+ if (unlikely(skb->len < ETH_HLEN + MLX5E_METADATA_ETHER_LEN))
+ return false;
+ ethtype = (__be16 *)(skb->data + ETH_ALEN * 2);
+ if (*ethtype != cpu_to_be16(MLX5E_METADATA_ETHER_TYPE))
+ return false;
+ return true;
+}
+
+static inline void remove_metadata_hdr(struct sk_buff *skb)
+{
+ struct ethhdr *old_eth;
+ struct ethhdr *new_eth;
+
+ /* Remove the metadata from the buffer */
+ old_eth = (struct ethhdr *)skb->data;
+ new_eth = (struct ethhdr *)(skb->data + MLX5E_METADATA_ETHER_LEN);
+ memmove(new_eth, old_eth, 2 * ETH_ALEN);
+ /* Ethertype is already in its new place */
+ skb_pull_inline(skb, MLX5E_METADATA_ETHER_LEN);
+}
+
+#endif /* CONFIG_MLX5_ACCEL */
+
+#endif /* __MLX5E_EN_ACCEL_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
index c245d8e..fda7929 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
@@ -37,6 +37,7 @@
#include "en_accel/ipsec_rxtx.h"
#include "en_accel/ipsec.h"
+#include "accel/accel.h"
#include "en.h"
enum {
@@ -346,19 +347,12 @@ struct sk_buff *mlx5e_ipsec_handle_tx_skb(struct net_device *netdev,
}
struct sk_buff *mlx5e_ipsec_handle_rx_skb(struct net_device *netdev,
- struct sk_buff *skb)
+ struct sk_buff *skb, u32 *cqe_bcnt)
{
struct mlx5e_ipsec_metadata *mdata;
- struct ethhdr *old_eth;
- struct ethhdr *new_eth;
struct xfrm_state *xs;
- __be16 *ethtype;
- /* Detect inline metadata */
- if (skb->len < ETH_HLEN + MLX5E_METADATA_ETHER_LEN)
- return skb;
- ethtype = (__be16 *)(skb->data + ETH_ALEN * 2);
- if (*ethtype != cpu_to_be16(MLX5E_METADATA_ETHER_TYPE))
+ if (!is_metadata_hdr_valid(skb))
return skb;
/* Use the metadata */
@@ -369,12 +363,7 @@ struct sk_buff *mlx5e_ipsec_handle_rx_skb(struct net_device *netdev,
return NULL;
}
- /* Remove the metadata from the buffer */
- old_eth = (struct ethhdr *)skb->data;
- new_eth = (struct ethhdr *)(skb->data + MLX5E_METADATA_ETHER_LEN);
- memmove(new_eth, old_eth, 2 * ETH_ALEN);
- /* Ethertype is already in its new place */
- skb_pull_inline(skb, MLX5E_METADATA_ETHER_LEN);
+ remove_metadata_hdr(skb);
return skb;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
index ecfc764..92d3745 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
@@ -33,6 +33,8 @@
#include "en_accel/tls.h"
#include "en_accel/tls_rxtx.h"
+#include "accel/accel.h"
+
#include <net/inet6_hashtables.h>
#include <linux/ipv6.h>
@@ -350,16 +352,9 @@ void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
u32 *cqe_bcnt)
{
struct mlx5e_tls_metadata *mdata;
- struct ethhdr *old_eth;
- struct ethhdr *new_eth;
- __be16 *ethtype;
struct mlx5e_priv *priv;
- /* Detect inline metadata */
- if (skb->len < ETH_HLEN + MLX5E_METADATA_ETHER_LEN)
- return;
- ethtype = (__be16 *)(skb->data + ETH_ALEN * 2);
- if (*ethtype != cpu_to_be16(MLX5E_METADATA_ETHER_TYPE))
+ if (!is_metadata_hdr_valid(skb))
return;
/* Use the metadata */
@@ -383,11 +378,6 @@ void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
return;
}
- /* Remove the metadata from the buffer */
- old_eth = (struct ethhdr *)skb->data;
- new_eth = (struct ethhdr *)(skb->data + MLX5E_METADATA_ETHER_LEN);
- memmove(new_eth, old_eth, 2 * ETH_ALEN);
- /* Ethertype is already in its new place */
- skb_pull_inline(skb, MLX5E_METADATA_ETHER_LEN);
+ remove_metadata_hdr(skb);
*cqe_bcnt -= MLX5E_METADATA_ETHER_LEN;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 03/19] net: Add TLS rx resync NDO
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
Add new netdev tls op for resynchronizing HW tls context
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
include/linux/netdevice.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b683971..0434df3 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -903,6 +903,8 @@ struct tlsdev_ops {
void (*tls_dev_del)(struct net_device *netdev,
struct tls_context *ctx,
enum tls_offload_ctx_dir direction);
+ void (*tls_dev_resync_rx)(struct net_device *netdev,
+ struct sock *sk, u32 seq, u64 rcd_sn);
};
#endif
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 18/19] net/mlx5e: IPsec, fix byte count in CQE
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
This patch fixes the byte count indication in CQE for processed IPsec
packets that contain a metadata header.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
index fda7929..128a82b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
@@ -364,6 +364,7 @@ struct sk_buff *mlx5e_ipsec_handle_rx_skb(struct net_device *netdev,
}
remove_metadata_hdr(skb);
+ *cqe_bcnt -= MLX5E_METADATA_ETHER_LEN;
return skb;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
index 2bfbbef..ca47c05 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
@@ -41,7 +41,7 @@
#include "en.h"
struct sk_buff *mlx5e_ipsec_handle_rx_skb(struct net_device *netdev,
- struct sk_buff *skb);
+ struct sk_buff *skb, u32 *cqe_bcnt);
void mlx5e_ipsec_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
void mlx5e_ipsec_inverse_table_init(void);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 847e195..4a85b26 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -1470,7 +1470,7 @@ void mlx5e_ipsec_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
mlx5e_free_rx_wqe(rq, wi);
goto wq_ll_pop;
}
- skb = mlx5e_ipsec_handle_rx_skb(rq->netdev, skb);
+ skb = mlx5e_ipsec_handle_rx_skb(rq->netdev, skb, &cqe_bcnt);
if (unlikely(!skb)) {
mlx5e_free_rx_wqe(rq, wi);
goto wq_ll_pop;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 02/19] net: Add TLS RX offload feature
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm, Ilya Lesokhin
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
From: Ilya Lesokhin <ilyal@mellanox.com>
This patch adds a netdev feature to configure TLS RX inline crypto offload.
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
include/linux/netdev_features.h | 2 ++
net/core/ethtool.c | 1 +
2 files changed, 3 insertions(+)
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 623bb8c..2b2a6dc 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -79,6 +79,7 @@ enum {
NETIF_F_HW_ESP_TX_CSUM_BIT, /* ESP with TX checksum offload */
NETIF_F_RX_UDP_TUNNEL_PORT_BIT, /* Offload of RX port for UDP tunnels */
NETIF_F_HW_TLS_TX_BIT, /* Hardware TLS TX offload */
+ NETIF_F_HW_TLS_RX_BIT, /* Hardware TLS RX offload */
NETIF_F_GRO_HW_BIT, /* Hardware Generic receive offload */
NETIF_F_HW_TLS_RECORD_BIT, /* Offload TLS record */
@@ -151,6 +152,7 @@ enum {
#define NETIF_F_HW_TLS_RECORD __NETIF_F(HW_TLS_RECORD)
#define NETIF_F_GSO_UDP_L4 __NETIF_F(GSO_UDP_L4)
#define NETIF_F_HW_TLS_TX __NETIF_F(HW_TLS_TX)
+#define NETIF_F_HW_TLS_RX __NETIF_F(HW_TLS_RX)
#define for_each_netdev_feature(mask_addr, bit) \
for_each_set_bit(bit, (unsigned long *)mask_addr, NETDEV_FEATURE_COUNT)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index e677a20..c9993c6 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -111,6 +111,7 @@ int ethtool_op_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
[NETIF_F_RX_UDP_TUNNEL_PORT_BIT] = "rx-udp_tunnel-port-offload",
[NETIF_F_HW_TLS_RECORD_BIT] = "tls-hw-record",
[NETIF_F_HW_TLS_TX_BIT] = "tls-hw-tx-offload",
+ [NETIF_F_HW_TLS_RX_BIT] = "tls-hw-rx-offload",
};
static const char
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 06/19] tls: Split decrypt_skb to two functions
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
Previously, decrypt_skb also updated the TLS context.
Now, decrypt_skb only decrypts the payload using the current context,
while decrypt_skb_update also updates the state.
Later, in the tls_device Rx flow, we will use decrypt_skb directly.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
include/net/tls.h | 2 ++
net/tls/tls_sw.c | 44 ++++++++++++++++++++++++++------------------
2 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/include/net/tls.h b/include/net/tls.h
index 5dcd808..49b8922 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -390,6 +390,8 @@ int tls_proccess_cmsg(struct sock *sk, struct msghdr *msg,
unsigned char *record_type);
void tls_register_device(struct tls_device *device);
void tls_unregister_device(struct tls_device *device);
+int decrypt_skb(struct sock *sk, struct sk_buff *skb,
+ struct scatterlist *sgout);
struct sk_buff *tls_validate_xmit_skb(struct sock *sk,
struct net_device *dev,
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 3bd7c14..99d0347 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -53,7 +53,6 @@ static int tls_do_decryption(struct sock *sk,
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
- struct strp_msg *rxm = strp_msg(skb);
struct aead_request *aead_req;
int ret;
@@ -74,18 +73,6 @@ static int tls_do_decryption(struct sock *sk,
ret = crypto_wait_req(crypto_aead_decrypt(aead_req), &ctx->async_wait);
- if (ret < 0)
- goto out;
-
- rxm->offset += tls_ctx->rx.prepend_size;
- rxm->full_len -= tls_ctx->rx.overhead_size;
- tls_advance_record_sn(sk, &tls_ctx->rx);
-
- ctx->decrypted = true;
-
- ctx->saved_data_ready(sk);
-
-out:
kfree(aead_req);
return ret;
}
@@ -670,8 +657,29 @@ static struct sk_buff *tls_wait_data(struct sock *sk, int flags,
return skb;
}
-static int decrypt_skb(struct sock *sk, struct sk_buff *skb,
- struct scatterlist *sgout)
+static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
+ struct scatterlist *sgout)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+ struct strp_msg *rxm = strp_msg(skb);
+ int err = 0;
+
+ err = decrypt_skb(sk, skb, sgout);
+ if (err < 0)
+ return err;
+
+ rxm->offset += tls_ctx->rx.prepend_size;
+ rxm->full_len -= tls_ctx->rx.overhead_size;
+ tls_advance_record_sn(sk, &tls_ctx->rx);
+ ctx->decrypted = true;
+ ctx->saved_data_ready(sk);
+
+ return err;
+}
+
+int decrypt_skb(struct sock *sk, struct sk_buff *skb,
+ struct scatterlist *sgout)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
@@ -821,7 +829,7 @@ int tls_sw_recvmsg(struct sock *sk,
if (err < 0)
goto fallback_to_reg_recv;
- err = decrypt_skb(sk, skb, sgin);
+ err = decrypt_skb_update(sk, skb, sgin);
for (; pages > 0; pages--)
put_page(sg_page(&sgin[pages]));
if (err < 0) {
@@ -830,7 +838,7 @@ int tls_sw_recvmsg(struct sock *sk,
}
} else {
fallback_to_reg_recv:
- err = decrypt_skb(sk, skb, NULL);
+ err = decrypt_skb_update(sk, skb, NULL);
if (err < 0) {
tls_err_abort(sk, EBADMSG);
goto recv_end;
@@ -901,7 +909,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
}
if (!ctx->decrypted) {
- err = decrypt_skb(sk, skb, NULL);
+ err = decrypt_skb_update(sk, skb, NULL);
if (err < 0) {
tls_err_abort(sk, EBADMSG);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 05/19] tls: Refactor tls_offload variable names
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
For symmetry, we rename tls_offload_context to
tls_offload_context_tx before we add tls_offload_context_rx.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/en_accel/tls.h | 6 +++---
include/net/tls.h | 16 +++++++-------
net/tls/tls_device.c | 25 +++++++++++-----------
net/tls/tls_device_fallback.c | 8 +++----
4 files changed, 27 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
index b616217..b82f4de 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
@@ -50,7 +50,7 @@ struct mlx5e_tls {
};
struct mlx5e_tls_offload_context {
- struct tls_offload_context base;
+ struct tls_offload_context_tx base;
u32 expected_seq;
__be32 swid;
};
@@ -59,8 +59,8 @@ struct mlx5e_tls_offload_context {
mlx5e_get_tls_tx_context(struct tls_context *tls_ctx)
{
BUILD_BUG_ON(sizeof(struct mlx5e_tls_offload_context) >
- TLS_OFFLOAD_CONTEXT_SIZE);
- return container_of(tls_offload_ctx(tls_ctx),
+ TLS_OFFLOAD_CONTEXT_SIZE_TX);
+ return container_of(tls_offload_ctx_tx(tls_ctx),
struct mlx5e_tls_offload_context,
base);
}
diff --git a/include/net/tls.h b/include/net/tls.h
index 70c2737..5dcd808 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -128,7 +128,7 @@ struct tls_record_info {
skb_frag_t frags[MAX_SKB_FRAGS];
};
-struct tls_offload_context {
+struct tls_offload_context_tx {
struct crypto_aead *aead_send;
spinlock_t lock; /* protects records list */
struct list_head records_list;
@@ -147,8 +147,8 @@ struct tls_offload_context {
#define TLS_DRIVER_STATE_SIZE (max_t(size_t, 8, sizeof(void *)))
};
-#define TLS_OFFLOAD_CONTEXT_SIZE \
- (ALIGN(sizeof(struct tls_offload_context), sizeof(void *)) + \
+#define TLS_OFFLOAD_CONTEXT_SIZE_TX \
+ (ALIGN(sizeof(struct tls_offload_context_tx), sizeof(void *)) + \
TLS_DRIVER_STATE_SIZE)
enum {
@@ -239,7 +239,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
void tls_device_init(void);
void tls_device_cleanup(void);
-struct tls_record_info *tls_get_record(struct tls_offload_context *context,
+struct tls_record_info *tls_get_record(struct tls_offload_context_tx *context,
u32 seq, u64 *p_record_sn);
static inline bool tls_record_is_start_marker(struct tls_record_info *rec)
@@ -380,10 +380,10 @@ static inline struct tls_sw_context_tx *tls_sw_ctx_tx(
return (struct tls_sw_context_tx *)tls_ctx->priv_ctx_tx;
}
-static inline struct tls_offload_context *tls_offload_ctx(
- const struct tls_context *tls_ctx)
+static inline struct tls_offload_context_tx *
+tls_offload_ctx_tx(const struct tls_context *tls_ctx)
{
- return (struct tls_offload_context *)tls_ctx->priv_ctx_tx;
+ return (struct tls_offload_context_tx *)tls_ctx->priv_ctx_tx;
}
int tls_proccess_cmsg(struct sock *sk, struct msghdr *msg,
@@ -396,7 +396,7 @@ struct sk_buff *tls_validate_xmit_skb(struct sock *sk,
struct sk_buff *skb);
int tls_sw_fallback_init(struct sock *sk,
- struct tls_offload_context *offload_ctx,
+ struct tls_offload_context_tx *offload_ctx,
struct tls_crypto_info *crypto_info);
#endif /* _TLS_OFFLOAD_H */
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index a7a8f8e..332a5d1 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -52,9 +52,8 @@
static void tls_device_free_ctx(struct tls_context *ctx)
{
- struct tls_offload_context *offload_ctx = tls_offload_ctx(ctx);
+ kfree(tls_offload_ctx_tx(ctx));
- kfree(offload_ctx);
kfree(ctx);
}
@@ -125,7 +124,7 @@ static void destroy_record(struct tls_record_info *record)
kfree(record);
}
-static void delete_all_records(struct tls_offload_context *offload_ctx)
+static void delete_all_records(struct tls_offload_context_tx *offload_ctx)
{
struct tls_record_info *info, *temp;
@@ -141,14 +140,14 @@ static void tls_icsk_clean_acked(struct sock *sk, u32 acked_seq)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_record_info *info, *temp;
- struct tls_offload_context *ctx;
+ struct tls_offload_context_tx *ctx;
u64 deleted_records = 0;
unsigned long flags;
if (!tls_ctx)
return;
- ctx = tls_offload_ctx(tls_ctx);
+ ctx = tls_offload_ctx_tx(tls_ctx);
spin_lock_irqsave(&ctx->lock, flags);
info = ctx->retransmit_hint;
@@ -179,7 +178,7 @@ static void tls_icsk_clean_acked(struct sock *sk, u32 acked_seq)
void tls_device_sk_destruct(struct sock *sk)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
- struct tls_offload_context *ctx = tls_offload_ctx(tls_ctx);
+ struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
if (ctx->open_record)
destroy_record(ctx->open_record);
@@ -219,7 +218,7 @@ static void tls_append_frag(struct tls_record_info *record,
static int tls_push_record(struct sock *sk,
struct tls_context *ctx,
- struct tls_offload_context *offload_ctx,
+ struct tls_offload_context_tx *offload_ctx,
struct tls_record_info *record,
struct page_frag *pfrag,
int flags,
@@ -264,7 +263,7 @@ static int tls_push_record(struct sock *sk,
return tls_push_sg(sk, ctx, offload_ctx->sg_tx_data, 0, flags);
}
-static int tls_create_new_record(struct tls_offload_context *offload_ctx,
+static int tls_create_new_record(struct tls_offload_context_tx *offload_ctx,
struct page_frag *pfrag,
size_t prepend_size)
{
@@ -290,7 +289,7 @@ static int tls_create_new_record(struct tls_offload_context *offload_ctx,
}
static int tls_do_allocation(struct sock *sk,
- struct tls_offload_context *offload_ctx,
+ struct tls_offload_context_tx *offload_ctx,
struct page_frag *pfrag,
size_t prepend_size)
{
@@ -324,7 +323,7 @@ static int tls_push_data(struct sock *sk,
unsigned char record_type)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
- struct tls_offload_context *ctx = tls_offload_ctx(tls_ctx);
+ struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE);
struct tls_record_info *record = ctx->open_record;
@@ -477,7 +476,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
return rc;
}
-struct tls_record_info *tls_get_record(struct tls_offload_context *context,
+struct tls_record_info *tls_get_record(struct tls_offload_context_tx *context,
u32 seq, u64 *p_record_sn)
{
u64 record_sn = context->hint_record_sn;
@@ -524,7 +523,7 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
{
u16 nonce_size, tag_size, iv_size, rec_seq_size;
struct tls_record_info *start_marker_record;
- struct tls_offload_context *offload_ctx;
+ struct tls_offload_context_tx *offload_ctx;
struct tls_crypto_info *crypto_info;
struct net_device *netdev;
char *iv, *rec_seq;
@@ -546,7 +545,7 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
goto out;
}
- offload_ctx = kzalloc(TLS_OFFLOAD_CONTEXT_SIZE, GFP_KERNEL);
+ offload_ctx = kzalloc(TLS_OFFLOAD_CONTEXT_SIZE_TX, GFP_KERNEL);
if (!offload_ctx) {
rc = -ENOMEM;
goto free_marker_record;
diff --git a/net/tls/tls_device_fallback.c b/net/tls/tls_device_fallback.c
index 748914a..d1d7dce 100644
--- a/net/tls/tls_device_fallback.c
+++ b/net/tls/tls_device_fallback.c
@@ -214,7 +214,7 @@ static void complete_skb(struct sk_buff *nskb, struct sk_buff *skb, int headln)
static int fill_sg_in(struct scatterlist *sg_in,
struct sk_buff *skb,
- struct tls_offload_context *ctx,
+ struct tls_offload_context_tx *ctx,
u64 *rcd_sn,
s32 *sync_size,
int *resync_sgs)
@@ -299,7 +299,7 @@ static struct sk_buff *tls_enc_skb(struct tls_context *tls_ctx,
s32 sync_size, u64 rcd_sn)
{
int tcp_payload_offset = skb_transport_offset(skb) + tcp_hdrlen(skb);
- struct tls_offload_context *ctx = tls_offload_ctx(tls_ctx);
+ struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
int payload_len = skb->len - tcp_payload_offset;
void *buf, *iv, *aad, *dummy_buf;
struct aead_request *aead_req;
@@ -361,7 +361,7 @@ static struct sk_buff *tls_sw_fallback(struct sock *sk, struct sk_buff *skb)
{
int tcp_payload_offset = skb_transport_offset(skb) + tcp_hdrlen(skb);
struct tls_context *tls_ctx = tls_get_ctx(sk);
- struct tls_offload_context *ctx = tls_offload_ctx(tls_ctx);
+ struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
int payload_len = skb->len - tcp_payload_offset;
struct scatterlist *sg_in, sg_out[3];
struct sk_buff *nskb = NULL;
@@ -415,7 +415,7 @@ struct sk_buff *tls_validate_xmit_skb(struct sock *sk,
}
int tls_sw_fallback_init(struct sock *sk,
- struct tls_offload_context *offload_ctx,
+ struct tls_offload_context_tx *offload_ctx,
struct tls_crypto_info *crypto_info)
{
const u8 *key;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 10/19] tls: Fix zerocopy_from_iter iov handling
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
zerocopy_from_iter iterates over the message, but it doesn't revert the
updates made by the iov iteration. This patch fixes it. Now, the iov can
be used after calling zerocopy_from_iter.
Fixes: 3c4d75591 ("tls: kernel TLS support")
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
net/tls/tls_sw.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 2a6ba0f..ea78678 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -267,7 +267,7 @@ static int zerocopy_from_iter(struct sock *sk, struct iov_iter *from,
int length, int *pages_used,
unsigned int *size_used,
struct scatterlist *to, int to_max_pages,
- bool charge)
+ bool charge, bool revert)
{
struct page *pages[MAX_SKB_FRAGS];
@@ -318,6 +318,8 @@ static int zerocopy_from_iter(struct sock *sk, struct iov_iter *from,
out:
*size_used = size;
*pages_used = num_elem;
+ if (revert)
+ iov_iter_revert(from, size);
return rc;
}
@@ -419,7 +421,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
&ctx->sg_plaintext_size,
ctx->sg_plaintext_data,
ARRAY_SIZE(ctx->sg_plaintext_data),
- true);
+ true, false);
if (ret)
goto fallback_to_reg_send;
@@ -834,7 +836,7 @@ int tls_sw_recvmsg(struct sock *sk,
err = zerocopy_from_iter(sk, &msg->msg_iter,
to_copy, &pages,
&chunk, &sgin[1],
- MAX_SKB_FRAGS, false);
+ MAX_SKB_FRAGS, false, true);
if (err < 0)
goto fallback_to_reg_recv;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 15/19] net/mlx5e: TLS, add software statistics
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
This patch adds software statistics for TLS to count important
events.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c | 3 +++
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h | 4 ++++
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c | 11 ++++++++++-
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
index 68368c9..541e6f4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
@@ -169,7 +169,10 @@ static void mlx5e_tls_resync_rx(struct net_device *netdev, struct sock *sk,
rx_ctx = mlx5e_get_tls_rx_context(tls_ctx);
+ netdev_info(netdev, "resyncing seq %d rcd %lld\n", seq,
+ be64_to_cpu(rcd_sn));
mlx5_accel_tls_resync_rx(priv->mdev, rx_ctx->handle, seq, rcd_sn);
+ atomic64_inc(&priv->tls->sw_stats.rx_tls_resync_reply);
}
static const struct tlsdev_ops mlx5e_tls_ops = {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
index 2d40ede..3f5d721 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
@@ -43,6 +43,10 @@ struct mlx5e_tls_sw_stats {
atomic64_t tx_tls_drop_resync_alloc;
atomic64_t tx_tls_drop_no_sync_data;
atomic64_t tx_tls_drop_bypass_required;
+ atomic64_t rx_tls_drop_resync_request;
+ atomic64_t rx_tls_resync_request;
+ atomic64_t rx_tls_resync_reply;
+ atomic64_t rx_tls_auth_fail;
};
struct mlx5e_tls {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
index d460fda..ecfc764 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
@@ -330,8 +330,12 @@ static int tls_update_resync_sn(struct net_device *netdev,
netdev->ifindex, 0);
#endif
}
- if (!sk || sk->sk_state == TCP_TIME_WAIT)
+ if (!sk || sk->sk_state == TCP_TIME_WAIT) {
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+
+ atomic64_inc(&priv->tls->sw_stats.rx_tls_drop_resync_request);
goto out;
+ }
skb->sk = sk;
skb->destructor = sock_edemux;
@@ -349,6 +353,7 @@ void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
struct ethhdr *old_eth;
struct ethhdr *new_eth;
__be16 *ethtype;
+ struct mlx5e_priv *priv;
/* Detect inline metadata */
if (skb->len < ETH_HLEN + MLX5E_METADATA_ETHER_LEN)
@@ -365,9 +370,13 @@ void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
break;
case SYNDROM_RESYNC_REQUEST:
tls_update_resync_sn(netdev, skb, mdata);
+ priv = netdev_priv(netdev);
+ atomic64_inc(&priv->tls->sw_stats.rx_tls_resync_request);
break;
case SYNDROM_AUTH_FAILED:
/* Authentication failure will be observed and verified by kTLS */
+ priv = netdev_priv(netdev);
+ atomic64_inc(&priv->tls->sw_stats.rx_tls_auth_fail);
break;
default:
/* Bypass the metadata header to others */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 11/19] net/mlx5e: TLS, refactor variable names
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
For symmetry, we rename mlx5e_tls_offload_context to
mlx5e_tls_offload_context_tx before we add mlx5e_tls_offload_context_rx.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Reviewed-by: Aviad Yehezkel <aviadye@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h | 8 ++++----
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c | 6 +++---
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
index d167845..7fb9c75 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
@@ -123,7 +123,7 @@ static int mlx5e_tls_add(struct net_device *netdev, struct sock *sk,
goto free_flow;
if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
- struct mlx5e_tls_offload_context *tx_ctx =
+ struct mlx5e_tls_offload_context_tx *tx_ctx =
mlx5e_get_tls_tx_context(tls_ctx);
u32 swid;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
index b82f4de..e26222a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
@@ -49,19 +49,19 @@ struct mlx5e_tls {
struct mlx5e_tls_sw_stats sw_stats;
};
-struct mlx5e_tls_offload_context {
+struct mlx5e_tls_offload_context_tx {
struct tls_offload_context_tx base;
u32 expected_seq;
__be32 swid;
};
-static inline struct mlx5e_tls_offload_context *
+static inline struct mlx5e_tls_offload_context_tx *
mlx5e_get_tls_tx_context(struct tls_context *tls_ctx)
{
- BUILD_BUG_ON(sizeof(struct mlx5e_tls_offload_context) >
+ BUILD_BUG_ON(sizeof(struct mlx5e_tls_offload_context_tx) >
TLS_OFFLOAD_CONTEXT_SIZE_TX);
return container_of(tls_offload_ctx_tx(tls_ctx),
- struct mlx5e_tls_offload_context,
+ struct mlx5e_tls_offload_context_tx,
base);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
index 15aef71..c96196f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
@@ -73,7 +73,7 @@ static int mlx5e_tls_add_metadata(struct sk_buff *skb, __be32 swid)
return 0;
}
-static int mlx5e_tls_get_sync_data(struct mlx5e_tls_offload_context *context,
+static int mlx5e_tls_get_sync_data(struct mlx5e_tls_offload_context_tx *context,
u32 tcp_seq, struct sync_info *info)
{
int remaining, i = 0, ret = -EINVAL;
@@ -161,7 +161,7 @@ static void mlx5e_tls_complete_sync_skb(struct sk_buff *skb,
}
static struct sk_buff *
-mlx5e_tls_handle_ooo(struct mlx5e_tls_offload_context *context,
+mlx5e_tls_handle_ooo(struct mlx5e_tls_offload_context_tx *context,
struct mlx5e_txqsq *sq, struct sk_buff *skb,
struct mlx5e_tx_wqe **wqe,
u16 *pi,
@@ -239,7 +239,7 @@ struct sk_buff *mlx5e_tls_handle_tx_skb(struct net_device *netdev,
u16 *pi)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
- struct mlx5e_tls_offload_context *context;
+ struct mlx5e_tls_offload_context_tx *context;
struct tls_context *tls_ctx;
u32 expected_seq;
int datalen;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 07/19] tls: Split tls_sw_release_resources_rx
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
This patch splits tls_sw_release_resources_rx into two functions one
which releases all inner software tls structures and another that also
frees the containing structure.
In TLS_DEVICE we will need to release the software structures without
freeeing the containing structure, which contains other information.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
include/net/tls.h | 1 +
net/tls/tls_sw.c | 10 +++++++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/include/net/tls.h b/include/net/tls.h
index 49b8922..7a485de 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -223,6 +223,7 @@ int tls_sw_sendpage(struct sock *sk, struct page *page,
void tls_sw_close(struct sock *sk, long timeout);
void tls_sw_free_resources_tx(struct sock *sk);
void tls_sw_free_resources_rx(struct sock *sk);
+void tls_sw_release_resources_rx(struct sock *sk);
int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len);
unsigned int tls_sw_poll(struct file *file, struct socket *sock,
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 99d0347..86e22bc 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1039,7 +1039,7 @@ void tls_sw_free_resources_tx(struct sock *sk)
kfree(ctx);
}
-void tls_sw_free_resources_rx(struct sock *sk)
+void tls_sw_release_resources_rx(struct sock *sk)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
@@ -1058,6 +1058,14 @@ void tls_sw_free_resources_rx(struct sock *sk)
strp_done(&ctx->strp);
lock_sock(sk);
}
+}
+
+void tls_sw_free_resources_rx(struct sock *sk)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+
+ tls_sw_release_resources_rx(sk);
kfree(ctx);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 01/19] net: Add decrypted field to skb
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm, Ilya Lesokhin
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
The decrypted bit is propogated to cloned/copied skbs.
This will be used later by the inline crypto receive side offload
of tls.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
---
include/linux/skbuff.h | 7 ++++++-
net/core/skbuff.c | 6 ++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 7601838..3ceb8dc 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -630,6 +630,7 @@ enum {
* @hash: the packet hash
* @queue_mapping: Queue mapping for multiqueue devices
* @xmit_more: More SKBs are pending for this queue
+ * @decrypted: Decrypted SKB
* @ndisc_nodetype: router type (from link layer)
* @ooo_okay: allow the mapping of a socket to a queue to be changed
* @l4_hash: indicate hash is a canonical 4-tuple hash over transport
@@ -736,7 +737,11 @@ struct sk_buff {
peeked:1,
head_frag:1,
xmit_more:1,
- __unused:1; /* one bit hole */
+#ifdef CONFIG_TLS_DEVICE
+ decrypted:1;
+#else
+ __unused:1;
+#endif
/* fields enclosed in headers_start/headers_end are copied
* using a single memcpy() in __copy_skb_header()
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c4e24ac..cfd6c6f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -805,6 +805,9 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
* It is not yet because we do not want to have a 16 bit hole
*/
new->queue_mapping = old->queue_mapping;
+#ifdef CONFIG_TLS_DEVICE
+ new->decrypted = old->decrypted;
+#endif
memcpy(&new->headers_start, &old->headers_start,
offsetof(struct sk_buff, headers_end) -
@@ -865,6 +868,9 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
C(head_frag);
C(data);
C(truesize);
+#ifdef CONFIG_TLS_DEVICE
+ C(decrypted);
+#endif
refcount_set(&n->users, 1);
atomic_inc(&(skb_shinfo(skb)->dataref));
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 04/19] tcp: Don't coalesce decrypted and encrypted SKBs
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm, Ilya Lesokhin
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
Prevent coalescing of decrypted and encrypted SKBs in GRO
and TCP layer.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
---
net/ipv4/tcp_input.c | 12 ++++++++++++
net/ipv4/tcp_offload.c | 3 +++
2 files changed, 15 insertions(+)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 814ea43..f89d86a 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4343,6 +4343,11 @@ static bool tcp_try_coalesce(struct sock *sk,
if (TCP_SKB_CB(from)->seq != TCP_SKB_CB(to)->end_seq)
return false;
+#ifdef CONFIG_TLS_DEVICE
+ if (from->decrypted != to->decrypted)
+ return false;
+#endif
+
if (!skb_try_coalesce(to, from, fragstolen, &delta))
return false;
@@ -4872,6 +4877,9 @@ void tcp_rbtree_insert(struct rb_root *root, struct sk_buff *skb)
break;
memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
+#ifdef CONFIG_TLS_DEVICE
+ nskb->decrypted = skb->decrypted;
+#endif
TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start;
if (list)
__skb_queue_before(list, skb, nskb);
@@ -4899,6 +4907,10 @@ void tcp_rbtree_insert(struct rb_root *root, struct sk_buff *skb)
skb == tail ||
(TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)))
goto end;
+#ifdef CONFIG_TLS_DEVICE
+ if (skb->decrypted != nskb->decrypted)
+ goto end;
+#endif
}
}
}
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index f5aee64..870b0a3 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -262,6 +262,9 @@ struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb)
flush |= (len - 1) >= mss;
flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq);
+#ifdef CONFIG_TLS_DEVICE
+ flush |= p->decrypted ^ skb->decrypted;
+#endif
if (flush || skb_gro_receive(p, skb)) {
mss = 1;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 19/19] net/mlx5e: Kconfig, mutually exclude compilation of TLS and IPsec accel
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
We currently have no devices that support both TLS and IPsec using the
accel framework, and the current code does not support both IPsec and
TLS. This patch prevents such combinations.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
index 2545296..d3e8c70 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
@@ -93,6 +93,7 @@ config MLX5_EN_TLS
depends on TLS_DEVICE
depends on TLS=y || MLX5_CORE=m
depends on MLX5_ACCEL
+ depends on !MLX5_EN_IPSEC
default n
---help---
Build support for TLS cryptography-offload accelaration in the NIC.
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 13/19] net/mlx5e: TLS, add innova rx support
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm, Ilya Lesokhin
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
Add the mlx5 implementation of the TLS Rx routines to add/del TLS
contexts, also add the tls_dev_resync_rx routine
to work with the TLS inline Rx crypto offload infrastructure.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/en_accel/tls.c | 46 +++++++++++++++-------
.../net/ethernet/mellanox/mlx5/core/en_accel/tls.h | 15 +++++++
2 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
index 7fb9c75..68368c9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
@@ -110,9 +110,7 @@ static int mlx5e_tls_add(struct net_device *netdev, struct sock *sk,
u32 caps = mlx5_accel_tls_device_caps(mdev);
int ret = -ENOMEM;
void *flow;
-
- if (direction != TLS_OFFLOAD_CTX_DIR_TX)
- return -EINVAL;
+ u32 swid;
flow = kzalloc(MLX5_ST_SZ_BYTES(tls_flow), GFP_KERNEL);
if (!flow)
@@ -122,18 +120,23 @@ static int mlx5e_tls_add(struct net_device *netdev, struct sock *sk,
if (ret)
goto free_flow;
+ ret = mlx5_accel_tls_add_flow(mdev, flow, crypto_info,
+ start_offload_tcp_sn, &swid,
+ direction == TLS_OFFLOAD_CTX_DIR_TX);
+ if (ret < 0)
+ goto free_flow;
+
if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
struct mlx5e_tls_offload_context_tx *tx_ctx =
mlx5e_get_tls_tx_context(tls_ctx);
- u32 swid;
-
- ret = mlx5_accel_tls_add_tx_flow(mdev, flow, crypto_info,
- start_offload_tcp_sn, &swid);
- if (ret < 0)
- goto free_flow;
tx_ctx->swid = htonl(swid);
tx_ctx->expected_seq = start_offload_tcp_sn;
+ } else {
+ struct mlx5e_tls_offload_context_rx *rx_ctx =
+ mlx5e_get_tls_rx_context(tls_ctx);
+
+ rx_ctx->handle = htonl(swid);
}
return 0;
@@ -147,19 +150,32 @@ static void mlx5e_tls_del(struct net_device *netdev,
enum tls_offload_ctx_dir direction)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
+ unsigned int handle;
- if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
- u32 swid = ntohl(mlx5e_get_tls_tx_context(tls_ctx)->swid);
+ handle = ntohl((direction == TLS_OFFLOAD_CTX_DIR_TX) ?
+ mlx5e_get_tls_tx_context(tls_ctx)->swid :
+ mlx5e_get_tls_rx_context(tls_ctx)->handle);
- mlx5_accel_tls_del_tx_flow(priv->mdev, swid);
- } else {
- netdev_err(netdev, "unsupported direction %d\n", direction);
- }
+ mlx5_accel_tls_del_flow(priv->mdev, handle,
+ direction == TLS_OFFLOAD_CTX_DIR_TX);
+}
+
+static void mlx5e_tls_resync_rx(struct net_device *netdev, struct sock *sk,
+ u32 seq, u64 rcd_sn)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_tls_offload_context_rx *rx_ctx;
+
+ rx_ctx = mlx5e_get_tls_rx_context(tls_ctx);
+
+ mlx5_accel_tls_resync_rx(priv->mdev, rx_ctx->handle, seq, rcd_sn);
}
static const struct tlsdev_ops mlx5e_tls_ops = {
.tls_dev_add = mlx5e_tls_add,
.tls_dev_del = mlx5e_tls_del,
+ .tls_dev_resync_rx = mlx5e_tls_resync_rx,
};
void mlx5e_tls_build_netdev(struct mlx5e_priv *priv)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
index e26222a..2d40ede 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
@@ -65,6 +65,21 @@ struct mlx5e_tls_offload_context_tx {
base);
}
+struct mlx5e_tls_offload_context_rx {
+ struct tls_offload_context_rx base;
+ __be32 handle;
+};
+
+static inline struct mlx5e_tls_offload_context_rx *
+mlx5e_get_tls_rx_context(struct tls_context *tls_ctx)
+{
+ BUILD_BUG_ON(sizeof(struct mlx5e_tls_offload_context_rx) >
+ TLS_OFFLOAD_CONTEXT_SIZE_RX);
+ return container_of(tls_offload_ctx_rx(tls_ctx),
+ struct mlx5e_tls_offload_context_rx,
+ base);
+}
+
void mlx5e_tls_build_netdev(struct mlx5e_priv *priv);
int mlx5e_tls_init(struct mlx5e_priv *priv);
void mlx5e_tls_cleanup(struct mlx5e_priv *priv);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 14/19] net/mlx5e: TLS, add Innova TLS rx data path
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm, Ilya Lesokhin
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
Implement the TLS rx offload data path according to the
requirements of the TLS generic NIC offload infrastructure.
Special metadata ethertype is used to pass information to
the hardware.
When hardware loses synchronization a special resync request
metadata message is used to request resync.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
---
.../mellanox/mlx5/core/en_accel/tls_rxtx.c | 112 ++++++++++++++++++++-
.../mellanox/mlx5/core/en_accel/tls_rxtx.h | 3 +
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 6 ++
3 files changed, 118 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
index c96196f..d460fda 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
@@ -33,6 +33,12 @@
#include "en_accel/tls.h"
#include "en_accel/tls_rxtx.h"
+#include <net/inet6_hashtables.h>
+#include <linux/ipv6.h>
+
+#define SYNDROM_DECRYPTED 0x30
+#define SYNDROM_RESYNC_REQUEST 0x31
+#define SYNDROM_AUTH_FAILED 0x32
#define SYNDROME_OFFLOAD_REQUIRED 32
#define SYNDROME_SYNC 33
@@ -44,10 +50,26 @@ struct sync_info {
skb_frag_t frags[MAX_SKB_FRAGS];
};
-struct mlx5e_tls_metadata {
+struct recv_metadata_content {
+ u8 syndrome;
+ u8 reserved;
+ __be32 sync_seq;
+} __packed;
+
+struct send_metadata_content {
/* One byte of syndrome followed by 3 bytes of swid */
__be32 syndrome_swid;
__be16 first_seq;
+} __packed;
+
+struct mlx5e_tls_metadata {
+ union {
+ /* from fpga to host */
+ struct recv_metadata_content recv;
+ /* from host to fpga */
+ struct send_metadata_content send;
+ unsigned char raw[6];
+ } __packed content;
/* packet type ID field */
__be16 ethertype;
} __packed;
@@ -68,7 +90,8 @@ static int mlx5e_tls_add_metadata(struct sk_buff *skb, __be32 swid)
2 * ETH_ALEN);
eth->h_proto = cpu_to_be16(MLX5E_METADATA_ETHER_TYPE);
- pet->syndrome_swid = htonl(SYNDROME_OFFLOAD_REQUIRED << 24) | swid;
+ pet->content.send.syndrome_swid =
+ htonl(SYNDROME_OFFLOAD_REQUIRED << 24) | swid;
return 0;
}
@@ -149,7 +172,7 @@ static void mlx5e_tls_complete_sync_skb(struct sk_buff *skb,
pet = (struct mlx5e_tls_metadata *)(nskb->data + sizeof(struct ethhdr));
memcpy(pet, &syndrome, sizeof(syndrome));
- pet->first_seq = htons(tcp_seq);
+ pet->content.send.first_seq = htons(tcp_seq);
/* MLX5 devices don't care about the checksum partial start, offset
* and pseudo header
@@ -276,3 +299,86 @@ struct sk_buff *mlx5e_tls_handle_tx_skb(struct net_device *netdev,
out:
return skb;
}
+
+static int tls_update_resync_sn(struct net_device *netdev,
+ struct sk_buff *skb,
+ struct mlx5e_tls_metadata *mdata)
+{
+ struct sock *sk = NULL;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ __be32 seq;
+
+ if (mdata->ethertype != htons(ETH_P_IP))
+ return -EINVAL;
+
+ iph = (struct iphdr *)(mdata + 1);
+
+ th = ((void *)iph) + iph->ihl * 4;
+
+ if (iph->version == 4) {
+ sk = inet_lookup_established(dev_net(netdev), &tcp_hashinfo,
+ iph->saddr, th->source, iph->daddr,
+ th->dest, netdev->ifindex);
+#if IS_ENABLED(CONFIG_IPV6)
+ } else {
+ struct ipv6hdr *ipv6h = (struct ipv6hdr *)iph;
+
+ sk = __inet6_lookup_established(dev_net(netdev), &tcp_hashinfo,
+ &ipv6h->saddr, th->source,
+ &ipv6h->daddr, th->dest,
+ netdev->ifindex, 0);
+#endif
+ }
+ if (!sk || sk->sk_state == TCP_TIME_WAIT)
+ goto out;
+
+ skb->sk = sk;
+ skb->destructor = sock_edemux;
+
+ memcpy(&seq, &mdata->content.recv.sync_seq, sizeof(seq));
+ tls_offload_rx_resync_request(sk, seq);
+out:
+ return 0;
+}
+
+void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
+ u32 *cqe_bcnt)
+{
+ struct mlx5e_tls_metadata *mdata;
+ struct ethhdr *old_eth;
+ struct ethhdr *new_eth;
+ __be16 *ethtype;
+
+ /* Detect inline metadata */
+ if (skb->len < ETH_HLEN + MLX5E_METADATA_ETHER_LEN)
+ return;
+ ethtype = (__be16 *)(skb->data + ETH_ALEN * 2);
+ if (*ethtype != cpu_to_be16(MLX5E_METADATA_ETHER_TYPE))
+ return;
+
+ /* Use the metadata */
+ mdata = (struct mlx5e_tls_metadata *)(skb->data + ETH_HLEN);
+ switch (mdata->content.recv.syndrome) {
+ case SYNDROM_DECRYPTED:
+ skb->decrypted = 1;
+ break;
+ case SYNDROM_RESYNC_REQUEST:
+ tls_update_resync_sn(netdev, skb, mdata);
+ break;
+ case SYNDROM_AUTH_FAILED:
+ /* Authentication failure will be observed and verified by kTLS */
+ break;
+ default:
+ /* Bypass the metadata header to others */
+ return;
+ }
+
+ /* Remove the metadata from the buffer */
+ old_eth = (struct ethhdr *)skb->data;
+ new_eth = (struct ethhdr *)(skb->data + MLX5E_METADATA_ETHER_LEN);
+ memmove(new_eth, old_eth, 2 * ETH_ALEN);
+ /* Ethertype is already in its new place */
+ skb_pull_inline(skb, MLX5E_METADATA_ETHER_LEN);
+ *cqe_bcnt -= MLX5E_METADATA_ETHER_LEN;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.h
index 405dfd3..311667e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.h
@@ -45,6 +45,9 @@ struct sk_buff *mlx5e_tls_handle_tx_skb(struct net_device *netdev,
struct mlx5e_tx_wqe **wqe,
u16 *pi);
+void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
+ u32 *cqe_bcnt);
+
#endif /* CONFIG_MLX5_EN_TLS */
#endif /* __MLX5E_TLS_RXTX_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 79e7d9b..847e195 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -44,6 +44,7 @@
#include "en_rep.h"
#include "ipoib/ipoib.h"
#include "en_accel/ipsec_rxtx.h"
+#include "en_accel/tls_rxtx.h"
#include "lib/clock.h"
static inline bool mlx5e_rx_hw_stamp(struct hwtstamp_config *config)
@@ -751,6 +752,11 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
struct net_device *netdev = rq->netdev;
skb->mac_len = ETH_HLEN;
+
+#ifdef CONFIG_MLX5_EN_TLS
+ mlx5e_tls_handle_rx_skb(netdev, skb, &cqe_bcnt);
+#endif
+
if (lro_num_seg > 1) {
mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt);
skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 net-next 16/19] net/mlx5e: TLS, build TLS netdev from capabilities
From: Boris Pismenny @ 2018-07-12 19:25 UTC (permalink / raw)
To: davem; +Cc: netdev, davejwatson, aviadye, borisp, saeedm
In-Reply-To: <1531423557-30926-1-git-send-email-borisp@mellanox.com>
This patch enables TLS Rx based on available HW capabilities.
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
index 541e6f4..eddd7702 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
@@ -183,13 +183,27 @@ static void mlx5e_tls_resync_rx(struct net_device *netdev, struct sock *sk,
void mlx5e_tls_build_netdev(struct mlx5e_priv *priv)
{
+ u32 caps = mlx5_accel_tls_device_caps(priv->mdev);
struct net_device *netdev = priv->netdev;
if (!mlx5_accel_is_tls_device(priv->mdev))
return;
- netdev->features |= NETIF_F_HW_TLS_TX;
- netdev->hw_features |= NETIF_F_HW_TLS_TX;
+ if (caps & MLX5_ACCEL_TLS_TX) {
+ netdev->features |= NETIF_F_HW_TLS_TX;
+ netdev->hw_features |= NETIF_F_HW_TLS_TX;
+ }
+
+ if (caps & MLX5_ACCEL_TLS_RX) {
+ netdev->features |= NETIF_F_HW_TLS_RX;
+ netdev->hw_features |= NETIF_F_HW_TLS_RX;
+ }
+
+ if (!(caps & MLX5_ACCEL_TLS_LRO)) {
+ netdev->features &= ~NETIF_F_LRO;
+ netdev->hw_features &= ~NETIF_F_LRO;
+ }
+
netdev->tlsdev_ops = &mlx5e_tls_ops;
}
--
1.8.3.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox