mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	qede: Add support for PTP resource locking.
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>
This commit is contained in:
		
							parent
							
								
									db82f70e4c
								
							
						
					
					
						commit
						035744975a
					
				| @ -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); | 	edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION); | ||||||
| 
 | 
 | ||||||
| 	/* PTP not supported on VFs */ | 	/* PTP not supported on VFs */ | ||||||
| 	if (!is_vf) { | 	if (!is_vf) | ||||||
| 		rc = qede_ptp_register_phc(edev); | 		qede_ptp_enable(edev, true); | ||||||
| 		if (rc) { |  | ||||||
| 			DP_NOTICE(edev, "Cannot register PHC\n"); |  | ||||||
| 			goto err5; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	edev->ops->register_ops(cdev, &qede_ll_ops, edev); | 	edev->ops->register_ops(cdev, &qede_ll_ops, edev); | ||||||
| 
 | 
 | ||||||
| @ -928,8 +923,6 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, | |||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| err5: |  | ||||||
| 	unregister_netdev(edev->ndev); |  | ||||||
| err4: | err4: | ||||||
| 	qede_roce_dev_remove(edev); | 	qede_roce_dev_remove(edev); | ||||||
| err3: | err3: | ||||||
| @ -980,7 +973,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) | |||||||
| 	unregister_netdev(ndev); | 	unregister_netdev(ndev); | ||||||
| 	cancel_delayed_work_sync(&edev->sp_task); | 	cancel_delayed_work_sync(&edev->sp_task); | ||||||
| 
 | 
 | ||||||
| 	qede_ptp_remove(edev); | 	qede_ptp_disable(edev); | ||||||
| 
 | 
 | ||||||
| 	qede_roce_dev_remove(edev); | 	qede_roce_dev_remove(edev); | ||||||
| 
 | 
 | ||||||
| @ -1877,8 +1870,6 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, | |||||||
| 	qede_roce_dev_event_close(edev); | 	qede_roce_dev_event_close(edev); | ||||||
| 	edev->state = QEDE_STATE_CLOSED; | 	edev->state = QEDE_STATE_CLOSED; | ||||||
| 
 | 
 | ||||||
| 	qede_ptp_stop(edev); |  | ||||||
| 
 |  | ||||||
| 	/* Close OS Tx */ | 	/* Close OS Tx */ | ||||||
| 	netif_tx_disable(edev->ndev); | 	netif_tx_disable(edev->ndev); | ||||||
| 	netif_carrier_off(edev->ndev); | 	netif_carrier_off(edev->ndev); | ||||||
| @ -1987,13 +1978,10 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode, | |||||||
| 
 | 
 | ||||||
| 	qede_roce_dev_event_open(edev); | 	qede_roce_dev_event_open(edev); | ||||||
| 
 | 
 | ||||||
| 	qede_ptp_start(edev, (mode == QEDE_LOAD_NORMAL)); |  | ||||||
| 
 |  | ||||||
| 	edev->state = QEDE_STATE_OPEN; | 	edev->state = QEDE_STATE_OPEN; | ||||||
| 
 | 
 | ||||||
| 	DP_INFO(edev, "Ending successfully qede load\n"); | 	DP_INFO(edev, "Ending successfully qede load\n"); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	goto out; | 	goto out; | ||||||
| err4: | err4: | ||||||
| 	qede_sync_free_irqs(edev); | 	qede_sync_free_irqs(edev); | ||||||
|  | |||||||
| @ -206,21 +206,6 @@ static u64 qede_ptp_read_cc(const struct cyclecounter *cc) | |||||||
| 	return phc_cycles; | 	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) | static int qede_ptp_cfg_filters(struct qede_dev *edev) | ||||||
| { | { | ||||||
| 	struct qede_ptp *ptp = edev->ptp; | 	struct qede_ptp *ptp = edev->ptp; | ||||||
| @ -324,61 +309,6 @@ int qede_ptp_hw_ts(struct qede_dev *edev, struct ifreq *ifr) | |||||||
| 			    sizeof(config)) ? -EFAULT : 0; | 			    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) | int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *info) | ||||||
| { | { | ||||||
| 	struct qede_ptp *ptp = edev->ptp; | 	struct qede_ptp *ptp = edev->ptp; | ||||||
| @ -417,8 +347,7 @@ int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *info) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Called during unload, to stop PTP-related stuff */ | void qede_ptp_disable(struct qede_dev *edev) | ||||||
| void qede_ptp_stop(struct qede_dev *edev) |  | ||||||
| { | { | ||||||
| 	struct qede_ptp *ptp; | 	struct qede_ptp *ptp; | ||||||
| 
 | 
 | ||||||
| @ -426,6 +355,11 @@ void qede_ptp_stop(struct qede_dev *edev) | |||||||
| 	if (!ptp) | 	if (!ptp) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | 	if (ptp->clock) { | ||||||
|  | 		ptp_clock_unregister(ptp->clock); | ||||||
|  | 		ptp->clock = NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* Cancel PTP work queue. Should be done after the Tx queues are
 | 	/* Cancel PTP work queue. Should be done after the Tx queues are
 | ||||||
| 	 * drained to prevent additional scheduling. | 	 * drained to prevent additional scheduling. | ||||||
| 	 */ | 	 */ | ||||||
| @ -439,11 +373,54 @@ void qede_ptp_stop(struct qede_dev *edev) | |||||||
| 	spin_lock_bh(&ptp->lock); | 	spin_lock_bh(&ptp->lock); | ||||||
| 	ptp->ops->disable(edev->cdev); | 	ptp->ops->disable(edev->cdev); | ||||||
| 	spin_unlock_bh(&ptp->lock); | 	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; | 	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); | 	ptp = kzalloc(sizeof(*ptp), GFP_KERNEL); | ||||||
| 	if (!ptp) { | 	if (!ptp) { | ||||||
| @ -454,14 +431,19 @@ int qede_ptp_register_phc(struct qede_dev *edev) | |||||||
| 	ptp->edev = edev; | 	ptp->edev = edev; | ||||||
| 	ptp->ops = edev->ops->ptp; | 	ptp->ops = edev->ops->ptp; | ||||||
| 	if (!ptp->ops) { | 	if (!ptp->ops) { | ||||||
| 		kfree(ptp); | 		DP_INFO(edev, "PTP enable failed\n"); | ||||||
| 		edev->ptp = NULL; | 		rc = -EIO; | ||||||
| 		DP_ERR(edev, "PTP clock registeration failed\n"); | 		goto err1; | ||||||
| 		return -EIO; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	edev->ptp = ptp; | 	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 */ | 	/* Fill the ptp_clock_info struct and register PTP clock */ | ||||||
| 	ptp->clock_info.owner = THIS_MODULE; | 	ptp->clock_info.owner = THIS_MODULE; | ||||||
| 	snprintf(ptp->clock_info.name, 16, "%s", edev->ndev->name); | 	snprintf(ptp->clock_info.name, 16, "%s", edev->ndev->name); | ||||||
| @ -478,13 +460,21 @@ int qede_ptp_register_phc(struct qede_dev *edev) | |||||||
| 
 | 
 | ||||||
| 	ptp->clock = ptp_clock_register(&ptp->clock_info, &edev->pdev->dev); | 	ptp->clock = ptp_clock_register(&ptp->clock_info, &edev->pdev->dev); | ||||||
| 	if (IS_ERR(ptp->clock)) { | 	if (IS_ERR(ptp->clock)) { | ||||||
| 		ptp->clock = NULL; | 		rc = -EINVAL; | ||||||
| 		kfree(ptp); |  | ||||||
| 		edev->ptp = NULL; |  | ||||||
| 		DP_ERR(edev, "PTP clock registeration failed\n"); | 		DP_ERR(edev, "PTP clock registeration failed\n"); | ||||||
|  | 		goto err2; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	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) | void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb) | ||||||
|  | |||||||
| @ -40,10 +40,8 @@ | |||||||
| void qede_ptp_rx_ts(struct qede_dev *edev, struct sk_buff *skb); | 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); | 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); | 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_disable(struct qede_dev *edev); | ||||||
| void qede_ptp_stop(struct qede_dev *edev); | int qede_ptp_enable(struct qede_dev *edev, bool init_tc); | ||||||
| void qede_ptp_remove(struct qede_dev *edev); |  | ||||||
| int qede_ptp_register_phc(struct qede_dev *edev); |  | ||||||
| int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *ts); | 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, | static inline void qede_ptp_record_rx_ts(struct qede_dev *edev, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 sudarsana.kalluru@cavium.com
						sudarsana.kalluru@cavium.com