mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	ionic: add ts_config replay
Split the call into ionic_lif_hwstamp_set() to have two separate interfaces, one from the ioctl() for changing the configuration and one for replaying the current configuration after a FW RESET. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									99b5bea04f
								
							
						
					
					
						commit
						829600ce5e
					
				| @ -2993,7 +2993,7 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif) | ||||
| 	dev_info(ionic->dev, "FW Up: LIFs restarted\n"); | ||||
| 
 | ||||
| 	/* restore the hardware timestamping queues */ | ||||
| 	ionic_lif_hwstamp_set(lif, NULL); | ||||
| 	ionic_lif_hwstamp_replay(lif); | ||||
| 
 | ||||
| 	return; | ||||
| 
 | ||||
|  | ||||
| @ -302,6 +302,7 @@ int ionic_lif_identify(struct ionic *ionic, u8 lif_type, | ||||
| int ionic_lif_size(struct ionic *ionic); | ||||
| 
 | ||||
| #if IS_ENABLED(CONFIG_PTP_1588_CLOCK) | ||||
| int ionic_lif_hwstamp_replay(struct ionic_lif *lif); | ||||
| int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr); | ||||
| int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr); | ||||
| ktime_t ionic_lif_phc_ktime(struct ionic_lif *lif, u64 counter); | ||||
| @ -310,6 +311,11 @@ void ionic_lif_unregister_phc(struct ionic_lif *lif); | ||||
| void ionic_lif_alloc_phc(struct ionic_lif *lif); | ||||
| void ionic_lif_free_phc(struct ionic_lif *lif); | ||||
| #else | ||||
| static inline int ionic_lif_hwstamp_replay(struct ionic_lif *lif) | ||||
| { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
| 
 | ||||
| static inline int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) | ||||
| { | ||||
| 	return -EOPNOTSUPP; | ||||
|  | ||||
| @ -64,10 +64,12 @@ static u64 ionic_hwstamp_rx_filt(int config_rx_filter) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) | ||||
| static int ionic_lif_hwstamp_set_ts_config(struct ionic_lif *lif, | ||||
| 					   struct hwtstamp_config *new_ts) | ||||
| { | ||||
| 	struct ionic *ionic = lif->ionic; | ||||
| 	struct hwtstamp_config config; | ||||
| 	struct hwtstamp_config *config; | ||||
| 	struct hwtstamp_config ts; | ||||
| 	int tx_mode = 0; | ||||
| 	u64 rx_filt = 0; | ||||
| 	int err, err2; | ||||
| @ -77,18 +79,23 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) | ||||
| 	if (!lif->phc || !lif->phc->ptp) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (ifr) { | ||||
| 		if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) | ||||
| 			return -EFAULT; | ||||
| 	if (new_ts) { | ||||
| 		config = new_ts; | ||||
| 	} else { | ||||
| 		/* if called with ifr == NULL, behave as if called with the
 | ||||
| 		 * current ts_config from the initial cleared state. | ||||
| 		/* If called with new_ts == NULL, replay the previous request
 | ||||
| 		 * primarily for recovery after a FW_RESET. | ||||
| 		 * We saved the previous configuration request info, so copy | ||||
| 		 * the previous request for reference, clear the current state | ||||
| 		 * to match the device's reset state, and run with it. | ||||
| 		 */ | ||||
| 		memcpy(&config, &lif->phc->ts_config, sizeof(config)); | ||||
| 		memset(&lif->phc->ts_config, 0, sizeof(config)); | ||||
| 		config = &ts; | ||||
| 		memcpy(config, &lif->phc->ts_config, sizeof(*config)); | ||||
| 		memset(&lif->phc->ts_config, 0, sizeof(lif->phc->ts_config)); | ||||
| 		lif->phc->ts_config_tx_mode = 0; | ||||
| 		lif->phc->ts_config_rx_filt = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	tx_mode = ionic_hwstamp_tx_mode(config.tx_type); | ||||
| 	tx_mode = ionic_hwstamp_tx_mode(config->tx_type); | ||||
| 	if (tx_mode < 0) | ||||
| 		return tx_mode; | ||||
| 
 | ||||
| @ -96,18 +103,18 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) | ||||
| 	if ((ionic->ident.lif.eth.hwstamp_tx_modes & mask) != mask) | ||||
| 		return -ERANGE; | ||||
| 
 | ||||
| 	rx_filt = ionic_hwstamp_rx_filt(config.rx_filter); | ||||
| 	rx_all = config.rx_filter != HWTSTAMP_FILTER_NONE && !rx_filt; | ||||
| 	rx_filt = ionic_hwstamp_rx_filt(config->rx_filter); | ||||
| 	rx_all = config->rx_filter != HWTSTAMP_FILTER_NONE && !rx_filt; | ||||
| 
 | ||||
| 	mask = cpu_to_le64(rx_filt); | ||||
| 	if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) != mask) { | ||||
| 		rx_filt = 0; | ||||
| 		rx_all = true; | ||||
| 		config.rx_filter = HWTSTAMP_FILTER_ALL; | ||||
| 		config->rx_filter = HWTSTAMP_FILTER_ALL; | ||||
| 	} | ||||
| 
 | ||||
| 	dev_dbg(ionic->dev, "config_rx_filter %d rx_filt %#llx rx_all %d\n", | ||||
| 		config.rx_filter, rx_filt, rx_all); | ||||
| 		config->rx_filter, rx_filt, rx_all); | ||||
| 
 | ||||
| 	mutex_lock(&lif->phc->config_lock); | ||||
| 
 | ||||
| @ -141,15 +148,7 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) | ||||
| 			goto err_rxall; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ifr) { | ||||
| 		err = copy_to_user(ifr->ifr_data, &config, sizeof(config)); | ||||
| 		if (err) { | ||||
| 			err = -EFAULT; | ||||
| 			goto err_final; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	memcpy(&lif->phc->ts_config, &config, sizeof(config)); | ||||
| 	memcpy(&lif->phc->ts_config, config, sizeof(*config)); | ||||
| 	lif->phc->ts_config_rx_filt = rx_filt; | ||||
| 	lif->phc->ts_config_tx_mode = tx_mode; | ||||
| 
 | ||||
| @ -157,14 +156,6 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| err_final: | ||||
| 	if (rx_all != (lif->phc->ts_config.rx_filter == HWTSTAMP_FILTER_ALL)) { | ||||
| 		rx_all = lif->phc->ts_config.rx_filter == HWTSTAMP_FILTER_ALL; | ||||
| 		err2 = ionic_lif_config_hwstamp_rxq_all(lif, rx_all); | ||||
| 		if (err2) | ||||
| 			dev_err(ionic->dev, | ||||
| 				"Failed to revert all-rxq timestamp config: %d\n", err2); | ||||
| 	} | ||||
| err_rxall: | ||||
| 	if (rx_filt != lif->phc->ts_config_rx_filt) { | ||||
| 		rx_filt = lif->phc->ts_config_rx_filt; | ||||
| @ -188,6 +179,37 @@ err_queues: | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) | ||||
| { | ||||
| 	struct hwtstamp_config config; | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	err = ionic_lif_hwstamp_set_ts_config(lif, &config); | ||||
| 	if (err) { | ||||
| 		netdev_info(lif->netdev, "hwstamp set failed: %d\n", err); | ||||
| 		return err; | ||||
| 	} | ||||
| 
 | ||||
| 	if (copy_to_user(ifr->ifr_data, &config, sizeof(config))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int ionic_lif_hwstamp_replay(struct ionic_lif *lif) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = ionic_lif_hwstamp_set_ts_config(lif, NULL); | ||||
| 	if (err) | ||||
| 		netdev_info(lif->netdev, "hwstamp replay failed: %d\n", err); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr) | ||||
| { | ||||
| 	struct hwtstamp_config config; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Shannon Nelson
						Shannon Nelson