Commit 1159da64 authored by David S. Miller's avatar David S. Miller

Merge branch 'bnxt_en-ptp'

Michael Chan says:

====================
bnxt_en: PTP enhancements

This series adds two PTP enhancements.  This first one is to register
the PHC during probe time and keep it registered whether it is in
ifup or ifdown state.  It will get unregistered and possibly
reregistered if the firmware PTP capability changes after firmware
reset.  The second one is to add the 1PPS (one pulse per second)
feature to support input/output of the 1PPS signal.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 63caca1e abf90ac2
......@@ -277,6 +277,8 @@ static const u16 bnxt_async_events_arr[] = {
ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION,
ASYNC_EVENT_CMPL_EVENT_ID_RING_MONITOR_MSG,
ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST,
ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP,
ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT,
};
static struct workqueue_struct *bnxt_pf_wq;
......@@ -2042,6 +2044,19 @@ static u16 bnxt_agg_ring_id_to_grp_idx(struct bnxt *bp, u16 ring_id)
return INVALID_HW_RING_ID;
}
static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2)
{
switch (BNXT_EVENT_ERROR_REPORT_TYPE(data1)) {
case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL:
netdev_err(bp->dev, "1PPS: Received invalid signal on pin%lu from the external source. Please fix the signal and reconfigure the pin\n",
BNXT_EVENT_INVALID_SIGNAL_DATA(data2));
break;
default:
netdev_err(bp->dev, "FW reported unknown error type\n");
break;
}
}
#define BNXT_GET_EVENT_PORT(data) \
((data) & \
ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
......@@ -2202,6 +2217,14 @@ static int bnxt_async_event_process(struct bnxt *bp,
}
goto async_event_process_exit;
}
case ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP: {
bnxt_ptp_pps_event(bp, data1, data2);
goto async_event_process_exit;
}
case ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT: {
bnxt_event_error_report(bp, data1, data2);
goto async_event_process_exit;
}
default:
goto async_event_process_exit;
}
......@@ -7495,9 +7518,14 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
rc = -ENODEV;
goto no_ptp;
}
return 0;
rc = bnxt_ptp_init(bp);
if (!rc)
return 0;
netdev_warn(bp->dev, "PTP initialization failed.\n");
no_ptp:
bnxt_ptp_clear(bp);
kfree(ptp);
bp->ptp_cfg = NULL;
return rc;
......@@ -7540,6 +7568,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
flags_ext = le32_to_cpu(resp->flags_ext);
if (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_EXT_HW_STATS_SUPPORTED)
bp->fw_cap |= BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED;
if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_PTP_PPS_SUPPORTED))
bp->fw_cap |= BNXT_FW_CAP_PTP_PPS;
bp->tx_push_thresh = 0;
if ((flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED) &&
......@@ -7577,6 +7607,7 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
if (flags & FUNC_QCAPS_RESP_FLAGS_PTP_SUPPORTED) {
__bnxt_hwrm_ptp_qcfg(bp);
} else {
bnxt_ptp_clear(bp);
kfree(bp->ptp_cfg);
bp->ptp_cfg = NULL;
}
......@@ -10277,15 +10308,9 @@ static int bnxt_open(struct net_device *dev)
if (rc)
return rc;
if (bnxt_ptp_init(bp)) {
netdev_warn(dev, "PTP initialization failed.\n");
kfree(bp->ptp_cfg);
bp->ptp_cfg = NULL;
}
rc = __bnxt_open_nic(bp, true, true);
if (rc) {
bnxt_hwrm_if_change(bp, false);
bnxt_ptp_clear(bp);
} else {
if (test_and_clear_bit(BNXT_STATE_FW_RESET_DET, &bp->state)) {
if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
......@@ -10376,7 +10401,6 @@ static int bnxt_close(struct net_device *dev)
{
struct bnxt *bp = netdev_priv(dev);
bnxt_ptp_clear(bp);
bnxt_hwmon_close(bp);
bnxt_close_nic(bp, true, true);
bnxt_hwrm_shutdown_link(bp);
......@@ -11363,7 +11387,6 @@ static void bnxt_fw_reset_close(struct bnxt *bp)
bnxt_clear_int_mode(bp);
pci_disable_device(bp->pdev);
}
bnxt_ptp_clear(bp);
__bnxt_close_nic(bp, true, false);
bnxt_vf_reps_free(bp);
bnxt_clear_int_mode(bp);
......@@ -11399,13 +11422,20 @@ static bool is_bnxt_fw_ok(struct bnxt *bp)
static void bnxt_force_fw_reset(struct bnxt *bp)
{
struct bnxt_fw_health *fw_health = bp->fw_health;
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
u32 wait_dsecs;
if (!test_bit(BNXT_STATE_OPEN, &bp->state) ||
test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
return;
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
if (ptp) {
spin_lock_bh(&ptp->ptp_lock);
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
spin_unlock_bh(&ptp->ptp_lock);
} else {
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
}
bnxt_fw_reset_close(bp);
wait_dsecs = fw_health->master_func_wait_dsecs;
if (fw_health->master) {
......@@ -11461,9 +11491,16 @@ void bnxt_fw_reset(struct bnxt *bp)
bnxt_rtnl_lock_sp(bp);
if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
int n = 0, tmo;
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
if (ptp) {
spin_lock_bh(&ptp->ptp_lock);
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
spin_unlock_bh(&ptp->ptp_lock);
} else {
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
}
if (bp->pf.active_vfs &&
!test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
n = bnxt_get_registered_vfs(bp);
......@@ -12136,6 +12173,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
bnxt_reenable_sriov(bp);
bnxt_vf_reps_alloc(bp);
bnxt_vf_reps_open(bp);
bnxt_ptp_reapply_pps(bp);
bnxt_dl_health_recovery_done(bp);
bnxt_dl_health_status_update(bp, true);
rtnl_unlock();
......@@ -12706,6 +12744,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
if (BNXT_PF(bp))
devlink_port_type_clear(&bp->dl_port);
bnxt_ptp_clear(bp);
pci_disable_pcie_error_reporting(pdev);
unregister_netdev(dev);
clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
......@@ -13318,6 +13357,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
bnxt_free_hwrm_short_cmd_req(bp);
bnxt_free_hwrm_resources(bp);
bnxt_ethtool_free(bp);
bnxt_ptp_clear(bp);
kfree(bp->ptp_cfg);
bp->ptp_cfg = NULL;
kfree(bp->fw_health);
......
......@@ -496,6 +496,16 @@ struct rx_tpa_end_cmp_ext {
!!((data1) & \
ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_RECOVERY_ENABLED)
#define BNXT_EVENT_ERROR_REPORT_TYPE(data1) \
(((data1) & \
ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK) >>\
ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT)
#define BNXT_EVENT_INVALID_SIGNAL_DATA(data2) \
(((data2) & \
ASYNC_EVENT_CMPL_ERROR_REPORT_INVALID_SIGNAL_EVENT_DATA2_PIN_ID_MASK) >>\
ASYNC_EVENT_CMPL_ERROR_REPORT_INVALID_SIGNAL_EVENT_DATA2_PIN_ID_SFT)
struct nqe_cn {
__le16 type;
#define NQ_CN_TYPE_MASK 0x3fUL
......@@ -1887,6 +1897,7 @@ struct bnxt {
#define BNXT_FW_CAP_VLAN_RX_STRIP 0x01000000
#define BNXT_FW_CAP_VLAN_TX_INSERT 0x02000000
#define BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED 0x04000000
#define BNXT_FW_CAP_PTP_PPS 0x10000000
#define BNXT_FW_CAP_RING_MONITOR 0x40000000
#define BNXT_NEW_RM(bp) ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
......
......@@ -21,11 +21,62 @@
#define BNXT_PTP_QTS_TX_ENABLES (PORT_TS_QUERY_REQ_ENABLES_PTP_SEQ_ID | \
PORT_TS_QUERY_REQ_ENABLES_TS_REQ_TIMEOUT)
struct pps_pin {
u8 event;
u8 usage;
u8 state;
};
#define TSIO_PIN_VALID(pin) ((pin) < (BNXT_MAX_TSIO_PINS))
#define EVENT_DATA2_PPS_EVENT_TYPE(data2) \
((data2) & ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_EVENT_TYPE)
#define EVENT_DATA2_PPS_PIN_NUM(data2) \
(((data2) & \
ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_PIN_NUMBER_MASK) >>\
ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_PIN_NUMBER_SFT)
#define BNXT_DATA2_UPPER_MSK \
ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_PPS_TIMESTAMP_UPPER_MASK
#define BNXT_DATA2_UPPER_SFT \
(32 - \
ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_PPS_TIMESTAMP_UPPER_SFT)
#define BNXT_DATA1_LOWER_MSK \
ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA1_PPS_TIMESTAMP_LOWER_MASK
#define BNXT_DATA1_LOWER_SFT \
ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA1_PPS_TIMESTAMP_LOWER_SFT
#define EVENT_PPS_TS(data2, data1) \
(((u64)((data2) & BNXT_DATA2_UPPER_MSK) << BNXT_DATA2_UPPER_SFT) |\
(((data1) & BNXT_DATA1_LOWER_MSK) >> BNXT_DATA1_LOWER_SFT))
#define BNXT_PPS_PIN_DISABLE 0
#define BNXT_PPS_PIN_ENABLE 1
#define BNXT_PPS_PIN_NONE 0
#define BNXT_PPS_PIN_PPS_IN 1
#define BNXT_PPS_PIN_PPS_OUT 2
#define BNXT_PPS_PIN_SYNC_IN 3
#define BNXT_PPS_PIN_SYNC_OUT 4
#define BNXT_PPS_EVENT_INTERNAL 1
#define BNXT_PPS_EVENT_EXTERNAL 2
struct bnxt_pps {
u8 num_pins;
#define BNXT_MAX_TSIO_PINS 4
struct pps_pin pins[BNXT_MAX_TSIO_PINS];
};
struct bnxt_ptp_cfg {
struct ptp_clock_info ptp_info;
struct ptp_clock *ptp_clock;
struct cyclecounter cc;
struct timecounter tc;
struct bnxt_pps pps_info;
/* serialize timecounter access */
spinlock_t ptp_lock;
struct sk_buff *tx_skb;
......@@ -71,6 +122,8 @@ do { \
#endif
int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id);
void bnxt_ptp_pps_event(struct bnxt *bp, u32 data1, u32 data2);
void bnxt_ptp_reapply_pps(struct bnxt *bp);
int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr);
int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr);
int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment