Skip to content

Commit

Permalink
qede: Add support for PTP resource locking.
Browse files Browse the repository at this point in the history
The patch adds necessary changes to the driver to use qed resource
locking functionality. Currently the ptp initialization is spread
between driver probe/open implementations, associated APIs are
qede_ptp_register_phc()/qede_ptp_start(). Clubbed this functionality
into single API qed_ptp_enable() to simplify the usage of qed resource
locking implementation. The new API will be invoked in the probe path.
Similarly the ptp clean-up code is moved to qede_ptp_disable() which
gets invoked in the driver unload path.

Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
sudarsana.kalluru@cavium.com authored and David S. Miller committed Apr 27, 2017
1 parent db82f70 commit 0357449
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 99 deletions.
18 changes: 3 additions & 15 deletions drivers/net/ethernet/qlogic/qede/qede_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -907,13 +907,8 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION);

/* PTP not supported on VFs */
if (!is_vf) {
rc = qede_ptp_register_phc(edev);
if (rc) {
DP_NOTICE(edev, "Cannot register PHC\n");
goto err5;
}
}
if (!is_vf)
qede_ptp_enable(edev, true);

edev->ops->register_ops(cdev, &qede_ll_ops, edev);

Expand All @@ -928,8 +923,6 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,

return 0;

err5:
unregister_netdev(edev->ndev);
err4:
qede_roce_dev_remove(edev);
err3:
Expand Down Expand Up @@ -980,7 +973,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
unregister_netdev(ndev);
cancel_delayed_work_sync(&edev->sp_task);

qede_ptp_remove(edev);
qede_ptp_disable(edev);

qede_roce_dev_remove(edev);

Expand Down Expand Up @@ -1877,8 +1870,6 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
qede_roce_dev_event_close(edev);
edev->state = QEDE_STATE_CLOSED;

qede_ptp_stop(edev);

/* Close OS Tx */
netif_tx_disable(edev->ndev);
netif_carrier_off(edev->ndev);
Expand Down Expand Up @@ -1987,13 +1978,10 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,

qede_roce_dev_event_open(edev);

qede_ptp_start(edev, (mode == QEDE_LOAD_NORMAL));

edev->state = QEDE_STATE_OPEN;

DP_INFO(edev, "Ending successfully qede load\n");


goto out;
err4:
qede_sync_free_irqs(edev);
Expand Down
150 changes: 70 additions & 80 deletions drivers/net/ethernet/qlogic/qede/qede_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,21 +206,6 @@ static u64 qede_ptp_read_cc(const struct cyclecounter *cc)
return phc_cycles;
}

static void qede_ptp_init_cc(struct qede_dev *edev)
{
struct qede_ptp *ptp;

ptp = edev->ptp;
if (!ptp)
return;

memset(&ptp->cc, 0, sizeof(ptp->cc));
ptp->cc.read = qede_ptp_read_cc;
ptp->cc.mask = CYCLECOUNTER_MASK(64);
ptp->cc.shift = 0;
ptp->cc.mult = 1;
}

static int qede_ptp_cfg_filters(struct qede_dev *edev)
{
struct qede_ptp *ptp = edev->ptp;
Expand Down Expand Up @@ -324,61 +309,6 @@ int qede_ptp_hw_ts(struct qede_dev *edev, struct ifreq *ifr)
sizeof(config)) ? -EFAULT : 0;
}

/* Called during load, to initialize PTP-related stuff */
static void qede_ptp_init(struct qede_dev *edev, bool init_tc)
{
struct qede_ptp *ptp;
int rc;

ptp = edev->ptp;
if (!ptp)
return;

spin_lock_init(&ptp->lock);

/* Configure PTP in HW */
rc = ptp->ops->enable(edev->cdev);
if (rc) {
DP_ERR(edev, "Stopping PTP initialization\n");
return;
}

/* Init work queue for Tx timestamping */
INIT_WORK(&ptp->work, qede_ptp_task);

/* Init cyclecounter and timecounter. This is done only in the first
* load. If done in every load, PTP application will fail when doing
* unload / load (e.g. MTU change) while it is running.
*/
if (init_tc) {
qede_ptp_init_cc(edev);
timecounter_init(&ptp->tc, &ptp->cc,
ktime_to_ns(ktime_get_real()));
}

DP_VERBOSE(edev, QED_MSG_DEBUG, "PTP initialization is successful\n");
}

void qede_ptp_start(struct qede_dev *edev, bool init_tc)
{
qede_ptp_init(edev, init_tc);
qede_ptp_cfg_filters(edev);
}

void qede_ptp_remove(struct qede_dev *edev)
{
struct qede_ptp *ptp;

ptp = edev->ptp;
if (ptp && ptp->clock) {
ptp_clock_unregister(ptp->clock);
ptp->clock = NULL;
}

kfree(ptp);
edev->ptp = NULL;
}

int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *info)
{
struct qede_ptp *ptp = edev->ptp;
Expand Down Expand Up @@ -417,15 +347,19 @@ int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *info)
return 0;
}

/* Called during unload, to stop PTP-related stuff */
void qede_ptp_stop(struct qede_dev *edev)
void qede_ptp_disable(struct qede_dev *edev)
{
struct qede_ptp *ptp;

ptp = edev->ptp;
if (!ptp)
return;

if (ptp->clock) {
ptp_clock_unregister(ptp->clock);
ptp->clock = NULL;
}

/* Cancel PTP work queue. Should be done after the Tx queues are
* drained to prevent additional scheduling.
*/
Expand All @@ -439,11 +373,54 @@ void qede_ptp_stop(struct qede_dev *edev)
spin_lock_bh(&ptp->lock);
ptp->ops->disable(edev->cdev);
spin_unlock_bh(&ptp->lock);

kfree(ptp);
edev->ptp = NULL;
}

int qede_ptp_register_phc(struct qede_dev *edev)
static int qede_ptp_init(struct qede_dev *edev, bool init_tc)
{
struct qede_ptp *ptp;
int rc;

ptp = edev->ptp;
if (!ptp)
return -EINVAL;

spin_lock_init(&ptp->lock);

/* Configure PTP in HW */
rc = ptp->ops->enable(edev->cdev);
if (rc) {
DP_INFO(edev, "PTP HW enable failed\n");
return rc;
}

/* Init work queue for Tx timestamping */
INIT_WORK(&ptp->work, qede_ptp_task);

/* Init cyclecounter and timecounter. This is done only in the first
* load. If done in every load, PTP application will fail when doing
* unload / load (e.g. MTU change) while it is running.
*/
if (init_tc) {
memset(&ptp->cc, 0, sizeof(ptp->cc));
ptp->cc.read = qede_ptp_read_cc;
ptp->cc.mask = CYCLECOUNTER_MASK(64);
ptp->cc.shift = 0;
ptp->cc.mult = 1;

timecounter_init(&ptp->tc, &ptp->cc,
ktime_to_ns(ktime_get_real()));
}

return rc;
}

int qede_ptp_enable(struct qede_dev *edev, bool init_tc)
{
struct qede_ptp *ptp;
int rc;

ptp = kzalloc(sizeof(*ptp), GFP_KERNEL);
if (!ptp) {
Expand All @@ -454,14 +431,19 @@ int qede_ptp_register_phc(struct qede_dev *edev)
ptp->edev = edev;
ptp->ops = edev->ops->ptp;
if (!ptp->ops) {
kfree(ptp);
edev->ptp = NULL;
DP_ERR(edev, "PTP clock registeration failed\n");
return -EIO;
DP_INFO(edev, "PTP enable failed\n");
rc = -EIO;
goto err1;
}

edev->ptp = ptp;

rc = qede_ptp_init(edev, init_tc);
if (rc)
goto err1;

qede_ptp_cfg_filters(edev);

/* Fill the ptp_clock_info struct and register PTP clock */
ptp->clock_info.owner = THIS_MODULE;
snprintf(ptp->clock_info.name, 16, "%s", edev->ndev->name);
Expand All @@ -478,13 +460,21 @@ int qede_ptp_register_phc(struct qede_dev *edev)

ptp->clock = ptp_clock_register(&ptp->clock_info, &edev->pdev->dev);
if (IS_ERR(ptp->clock)) {
ptp->clock = NULL;
kfree(ptp);
edev->ptp = NULL;
rc = -EINVAL;
DP_ERR(edev, "PTP clock registeration failed\n");
goto err2;
}

return 0;

err2:
qede_ptp_disable(edev);
ptp->clock = NULL;
err1:
kfree(ptp);
edev->ptp = NULL;

return rc;
}

void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb)
Expand Down
6 changes: 2 additions & 4 deletions drivers/net/ethernet/qlogic/qede/qede_ptp.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@
void qede_ptp_rx_ts(struct qede_dev *edev, struct sk_buff *skb);
void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb);
int qede_ptp_hw_ts(struct qede_dev *edev, struct ifreq *req);
void qede_ptp_start(struct qede_dev *edev, bool init_tc);
void qede_ptp_stop(struct qede_dev *edev);
void qede_ptp_remove(struct qede_dev *edev);
int qede_ptp_register_phc(struct qede_dev *edev);
void qede_ptp_disable(struct qede_dev *edev);
int qede_ptp_enable(struct qede_dev *edev, bool init_tc);
int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *ts);

static inline void qede_ptp_record_rx_ts(struct qede_dev *edev,
Expand Down

0 comments on commit 0357449

Please sign in to comment.