summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/pensando/ionic
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-07-26 22:07:35 +0100
committerMark Brown <broonie@kernel.org>2026-07-26 22:07:35 +0100
commitb4669b7a027d6cb271dc4ebf44b7f7a7186119ad (patch)
treefd55b5345d39c35c5676a2e67edd3e486dab2147 /drivers/net/ethernet/pensando/ionic
parent531c5716ada91d2f852ac1b9447cb29095a0003b (diff)
parent9b66c9af7172ffcf727214fa0ebe9a5e1ed6eb16 (diff)
downloadlinux-next-b4669b7a027d6cb271dc4ebf44b7f7a7186119ad.tar.gz
linux-next-b4669b7a027d6cb271dc4ebf44b7f7a7186119ad.zip
Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git
# Conflicts: # drivers/infiniband/hw/irdma/verbs.c
Diffstat (limited to 'drivers/net/ethernet/pensando/ionic')
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_ethtool.c12
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_if.h1
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.c5
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.h3
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_phc.c63
5 files changed, 71 insertions, 13 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
index c4ab4b5caa0a..fc8c50e8f365 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
@@ -1041,10 +1041,14 @@ static int ionic_get_ts_info(struct net_device *netdev,
info->phc_index = ptp_clock_index(lif->phc->ptp);
- info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
- SOF_TIMESTAMPING_TX_HARDWARE |
- SOF_TIMESTAMPING_RX_HARDWARE |
- SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE;
+
+ if (!(lif->hw_features & IONIC_ETH_HW_TIMESTAMP))
+ return 0;
+
+ info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
/* tx modes */
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h
index 0a201422d0c5..6afc1fc3c7ed 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_if.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h
@@ -1181,6 +1181,7 @@ enum ionic_eth_hw_features {
IONIC_ETH_HW_TX_CSUM_GENEVE = BIT(18),
IONIC_ETH_HW_TSO_GENEVE = BIT(19),
IONIC_ETH_HW_TIMESTAMP = BIT(20),
+ IONIC_ETH_HW_RDMA_TIMESTAMP = BIT(21),
};
/**
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index fd3ee9820531..af4aadd96cb9 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1500,7 +1500,8 @@ static int ionic_set_nic_features(struct ionic_lif *lif,
ctx.cmd.lif_setattr.features = ionic_netdev_features_to_nic(features);
if (lif->phc)
- ctx.cmd.lif_setattr.features |= cpu_to_le64(IONIC_ETH_HW_TIMESTAMP);
+ ctx.cmd.lif_setattr.features |= lif->ionic->ident.lif.eth.config.features &
+ cpu_to_le64(IONIC_ETH_HW_TIMESTAMP | IONIC_ETH_HW_RDMA_TIMESTAMP);
err = ionic_adminq_post_wait(lif, &ctx);
if (err)
@@ -1551,6 +1552,8 @@ static int ionic_set_nic_features(struct ionic_lif *lif,
dev_dbg(dev, "feature ETH_HW_TSO_UDP_CSUM\n");
if (lif->hw_features & IONIC_ETH_HW_TIMESTAMP)
dev_dbg(dev, "feature ETH_HW_TIMESTAMP\n");
+ if (lif->hw_features & IONIC_ETH_HW_RDMA_TIMESTAMP)
+ dev_dbg(dev, "feature ETH_HW_RDMA_TIMESTAMP\n");
return 0;
}
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index d34692462036..e790f6b9441e 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -248,7 +248,7 @@ struct ionic_lif {
};
struct ionic_phc {
- spinlock_t lock; /* lock for cc and tc */
+ spinlock_t lock; /* lock for state_page, cc and tc */
struct cyclecounter cc;
struct timecounter tc;
@@ -261,6 +261,7 @@ struct ionic_phc {
long aux_work_delay;
struct ptp_clock_info ptp_info;
+ struct ib_uverbs_clock_info *state_page;
struct ptp_clock *ptp;
struct ionic_lif *lif;
};
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_phc.c b/drivers/net/ethernet/pensando/ionic/ionic_phc.c
index 05b44fc482f8..4b8d80a55b72 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_phc.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_phc.c
@@ -3,6 +3,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <uapi/rdma/ib_user_verbs.h>
#include "ionic.h"
#include "ionic_bus.h"
@@ -77,7 +78,8 @@ static int ionic_lif_hwstamp_set_ts_config(struct ionic_lif *lif,
bool rx_all;
__le64 mask;
- if (!lif->phc || !lif->phc->ptp)
+ if (!lif->phc || !lif->phc->ptp ||
+ !(lif->hw_features & IONIC_ETH_HW_TIMESTAMP))
return -EOPNOTSUPP;
mutex_lock(&lif->phc->config_lock);
@@ -210,7 +212,8 @@ int ionic_hwstamp_set(struct net_device *netdev,
struct ionic_lif *lif = netdev_priv(netdev);
int err;
- if (!lif->phc || !lif->phc->ptp)
+ if (!lif->phc || !lif->phc->ptp ||
+ !(lif->hw_features & IONIC_ETH_HW_TIMESTAMP))
return -EOPNOTSUPP;
mutex_lock(&lif->queue_lock);
@@ -228,7 +231,8 @@ void ionic_lif_hwstamp_replay(struct ionic_lif *lif)
{
int err;
- if (!lif->phc || !lif->phc->ptp)
+ if (!lif->phc || !lif->phc->ptp ||
+ !(lif->hw_features & IONIC_ETH_HW_TIMESTAMP))
return;
mutex_lock(&lif->queue_lock);
@@ -242,7 +246,8 @@ void ionic_lif_hwstamp_recreate_queues(struct ionic_lif *lif)
{
int err;
- if (!lif->phc || !lif->phc->ptp)
+ if (!lif->phc || !lif->phc->ptp ||
+ !(lif->hw_features & IONIC_ETH_HW_TIMESTAMP))
return;
mutex_lock(&lif->phc->config_lock);
@@ -267,7 +272,8 @@ int ionic_hwstamp_get(struct net_device *netdev,
{
struct ionic_lif *lif = netdev_priv(netdev);
- if (!lif->phc || !lif->phc->ptp)
+ if (!lif->phc || !lif->phc->ptp ||
+ !(lif->hw_features & IONIC_ETH_HW_TIMESTAMP))
return -EOPNOTSUPP;
mutex_lock(&lif->phc->config_lock);
@@ -329,6 +335,26 @@ static int ionic_setphc_cmd(struct ionic_phc *phc, struct ionic_admin_ctx *ctx)
return ionic_adminq_post(phc->lif, ctx);
}
+static void ionic_phc_state_page_update(struct ionic_phc *phc)
+{
+ struct ib_uverbs_clock_info *state = phc->state_page;
+ u32 sign;
+
+ /* read current sign */
+ sign = smp_load_acquire(&state->sign) & ~1;
+
+ /* make sign odd for updating */
+ smp_store_mb(state->sign, sign | 1);
+
+ state->cycles = phc->tc.cycle_last;
+ state->nsec = phc->tc.nsec;
+ state->frac = phc->tc.frac;
+ state->mult = phc->cc.mult;
+
+ /* make sign the next even number for update completed */
+ smp_store_release(&state->sign, sign + 2);
+}
+
static int ionic_phc_adjfine(struct ptp_clock_info *info, long scaled_ppm)
{
struct ionic_phc *phc = container_of(info, struct ionic_phc, ptp_info);
@@ -356,6 +382,8 @@ static int ionic_phc_adjfine(struct ptp_clock_info *info, long scaled_ppm)
timecounter_read(&phc->tc);
phc->cc.mult = adj;
+ ionic_phc_state_page_update(phc);
+
/* Setphc commands are posted in-order, sequenced by phc->lock. We
* need to drop the lock before waiting for the command to complete.
*/
@@ -381,6 +409,8 @@ static int ionic_phc_adjtime(struct ptp_clock_info *info, s64 delta)
timecounter_adjtime(&phc->tc, delta);
+ ionic_phc_state_page_update(phc);
+
/* Setphc commands are posted in-order, sequenced by phc->lock. We
* need to drop the lock before waiting for the command to complete.
*/
@@ -410,6 +440,8 @@ static int ionic_phc_settime64(struct ptp_clock_info *info,
timecounter_init(&phc->tc, &phc->cc, ns);
+ ionic_phc_state_page_update(phc);
+
/* Setphc commands are posted in-order, sequenced by phc->lock. We
* need to drop the lock before waiting for the command to complete.
*/
@@ -467,6 +499,8 @@ static long ionic_phc_aux_work(struct ptp_clock_info *info)
/* update point-in-time basis to now */
timecounter_read(&phc->tc);
+ ionic_phc_state_page_update(phc);
+
/* Setphc commands are posted in-order, sequenced by phc->lock. We
* need to drop the lock before waiting for the command to complete.
*/
@@ -506,7 +540,8 @@ static const struct ptp_clock_info ionic_ptp_info = {
void ionic_lif_register_phc(struct ionic_lif *lif)
{
- if (!lif->phc || !(lif->hw_features & IONIC_ETH_HW_TIMESTAMP))
+ if (!lif->phc ||
+ !(lif->hw_features & (IONIC_ETH_HW_TIMESTAMP | IONIC_ETH_HW_RDMA_TIMESTAMP)))
return;
lif->phc->ptp = ptp_clock_register(&lif->phc->ptp_info, lif->ionic->dev);
@@ -545,13 +580,19 @@ void ionic_lif_alloc_phc(struct ionic_lif *lif)
return;
features = le64_to_cpu(ionic->ident.lif.eth.config.features);
- if (!(features & IONIC_ETH_HW_TIMESTAMP))
+ if (!(features & (IONIC_ETH_HW_TIMESTAMP | IONIC_ETH_HW_RDMA_TIMESTAMP)))
return;
phc = devm_kzalloc(ionic->dev, sizeof(*phc), GFP_KERNEL);
if (!phc)
return;
+ phc->state_page = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!phc->state_page) {
+ devm_kfree(ionic->dev, phc);
+ return;
+ }
+
phc->lif = lif;
phc->cc.read = ionic_cc_read;
@@ -563,6 +604,7 @@ void ionic_lif_alloc_phc(struct ionic_lif *lif)
dev_err(lif->ionic->dev,
"Invalid device PHC mask multiplier %u, disabling HW timestamp support\n",
phc->cc.mult);
+ free_page((unsigned long)phc->state_page);
devm_kfree(lif->ionic->dev, phc);
lif->phc = NULL;
return;
@@ -646,6 +688,12 @@ void ionic_lif_alloc_phc(struct ionic_lif *lif)
*/
phc->ptp_info.max_adj = NORMAL_PPB;
+ phc->state_page->mask = phc->cc.mask;
+ phc->state_page->shift = phc->cc.shift;
+ phc->state_page->overflow_period = delay;
+
+ ionic_phc_state_page_update(phc);
+
lif->phc = phc;
}
@@ -656,6 +704,7 @@ void ionic_lif_free_phc(struct ionic_lif *lif)
mutex_destroy(&lif->phc->config_lock);
+ free_page((unsigned long)lif->phc->state_page);
devm_kfree(lif->ionic->dev, lif->phc);
lif->phc = NULL;
}