|
@@ -34,6 +34,7 @@
|
|
|
#include "qed_dev_api.h"
|
|
|
#include "qed_hw.h"
|
|
|
#include "qed_l2.h"
|
|
|
+#include "qed_mcp.h"
|
|
|
#include "qed_ptp.h"
|
|
|
#include "qed_reg_addr.h"
|
|
|
|
|
@@ -45,6 +46,82 @@
|
|
|
#define QED_DRIFT_CNTR_DIRECTION_SHIFT 31
|
|
|
#define QED_TIMESTAMP_MASK BIT(16)
|
|
|
|
|
|
+static enum qed_resc_lock qed_ptcdev_to_resc(struct qed_hwfn *p_hwfn)
|
|
|
+{
|
|
|
+ switch (qed_device_get_port_id(p_hwfn->cdev)) {
|
|
|
+ case 0:
|
|
|
+ return QED_RESC_LOCK_PTP_PORT0;
|
|
|
+ case 1:
|
|
|
+ return QED_RESC_LOCK_PTP_PORT1;
|
|
|
+ case 2:
|
|
|
+ return QED_RESC_LOCK_PTP_PORT2;
|
|
|
+ case 3:
|
|
|
+ return QED_RESC_LOCK_PTP_PORT3;
|
|
|
+ default:
|
|
|
+ return QED_RESC_LOCK_RESC_INVALID;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int qed_ptp_res_lock(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
|
|
|
+{
|
|
|
+ struct qed_resc_lock_params params;
|
|
|
+ enum qed_resc_lock resource;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ resource = qed_ptcdev_to_resc(p_hwfn);
|
|
|
+ if (resource == QED_RESC_LOCK_RESC_INVALID)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ qed_mcp_resc_lock_default_init(¶ms, NULL, resource, true);
|
|
|
+
|
|
|
+ rc = qed_mcp_resc_lock(p_hwfn, p_ptt, ¶ms);
|
|
|
+ if (rc && rc != -EINVAL) {
|
|
|
+ return rc;
|
|
|
+ } else if (rc == -EINVAL) {
|
|
|
+ /* MFW doesn't support resource locking, first PF on the port
|
|
|
+ * has lock ownership.
|
|
|
+ */
|
|
|
+ if (p_hwfn->abs_pf_id < p_hwfn->cdev->num_ports_in_engines)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ DP_INFO(p_hwfn, "PF doesn't have lock ownership\n");
|
|
|
+ return -EBUSY;
|
|
|
+ } else if (!rc && !params.b_granted) {
|
|
|
+ DP_INFO(p_hwfn, "Failed to acquire ptp resource lock\n");
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
+static int qed_ptp_res_unlock(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
|
|
|
+{
|
|
|
+ struct qed_resc_unlock_params params;
|
|
|
+ enum qed_resc_lock resource;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ resource = qed_ptcdev_to_resc(p_hwfn);
|
|
|
+ if (resource == QED_RESC_LOCK_RESC_INVALID)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ qed_mcp_resc_lock_default_init(NULL, ¶ms, resource, true);
|
|
|
+
|
|
|
+ rc = qed_mcp_resc_unlock(p_hwfn, p_ptt, ¶ms);
|
|
|
+ if (rc == -EINVAL) {
|
|
|
+ /* MFW doesn't support locking, first PF has lock ownership */
|
|
|
+ if (p_hwfn->abs_pf_id < p_hwfn->cdev->num_ports_in_engines) {
|
|
|
+ rc = 0;
|
|
|
+ } else {
|
|
|
+ DP_INFO(p_hwfn, "PF doesn't have lock ownership\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ } else if (rc) {
|
|
|
+ DP_INFO(p_hwfn, "Failed to release the ptp resource lock\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
/* Read Rx timestamp */
|
|
|
static int qed_ptp_hw_read_rx_ts(struct qed_dev *cdev, u64 *timestamp)
|
|
|
{
|
|
@@ -249,6 +326,14 @@ static int qed_ptp_hw_enable(struct qed_dev *cdev)
|
|
|
{
|
|
|
struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
|
|
|
struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ rc = qed_ptp_res_lock(p_hwfn, p_ptt);
|
|
|
+ if (rc) {
|
|
|
+ DP_INFO(p_hwfn,
|
|
|
+ "Couldn't acquire the resource lock, skip ptp enable for this PF\n");
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
|
|
|
/* Reset PTP event detection rules - will be configured in the IOCTL */
|
|
|
qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_PARAM_MASK, 0x7FF);
|
|
@@ -305,6 +390,8 @@ static int qed_ptp_hw_disable(struct qed_dev *cdev)
|
|
|
struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
|
|
|
struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt;
|
|
|
|
|
|
+ qed_ptp_res_unlock(p_hwfn, p_ptt);
|
|
|
+
|
|
|
/* Reset PTP event detection rules */
|
|
|
qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_PARAM_MASK, 0x7FF);
|
|
|
qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_RULE_MASK, 0x3FFF);
|