Merge branch 'siocghwtstamp' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next
Ben Hutchings says:
====================
SIOCGHWTSTAMP ioctl
1. Add the SIOCGHWTSTAMP ioctl and update the timestamping
documentation.
2. Implement SIOCGHWTSTAMP in most drivers that support SIOCSHWTSTAMP.
3. Add a test program to exercise SIOC{G,S}HWTSTAMP.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
	
	
This commit is contained in:
		
				commit
				
					
						426e1fa31e
					
				
			
		
					 23 changed files with 423 additions and 100 deletions
				
			
		|  | @ -85,7 +85,7 @@ Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support | |||
| by the network device and will be empty without that support. | ||||
| 
 | ||||
| 
 | ||||
| SIOCSHWTSTAMP: | ||||
| SIOCSHWTSTAMP, SIOCGHWTSTAMP: | ||||
| 
 | ||||
| Hardware time stamping must also be initialized for each device driver | ||||
| that is expected to do hardware time stamping. The parameter is defined in | ||||
|  | @ -115,6 +115,10 @@ Only a processes with admin rights may change the configuration. User | |||
| space is responsible to ensure that multiple processes don't interfere | ||||
| with each other and that the settings are reset. | ||||
| 
 | ||||
| Any process can read the actual configuration by passing this | ||||
| structure to ioctl(SIOCGHWTSTAMP) in the same way.  However, this has | ||||
| not been implemented in all drivers. | ||||
| 
 | ||||
| /* possible values for hwtstamp_config->tx_type */ | ||||
| enum { | ||||
| 	/* | ||||
|  | @ -157,7 +161,8 @@ DEVICE IMPLEMENTATION | |||
| 
 | ||||
| A driver which supports hardware time stamping must support the | ||||
| SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with | ||||
| the actual values as described in the section on SIOCSHWTSTAMP. | ||||
| the actual values as described in the section on SIOCSHWTSTAMP.  It | ||||
| should also support SIOCGHWTSTAMP. | ||||
| 
 | ||||
| Time stamps for received packets must be stored in the skb. To get a pointer | ||||
| to the shared time stamp structure of the skb call skb_hwtstamps(). Then | ||||
|  |  | |||
|  | @ -1 +1,2 @@ | |||
| timestamping | ||||
| hwtstamp_config | ||||
|  |  | |||
|  | @ -2,12 +2,13 @@ | |||
| obj- := dummy.o | ||||
| 
 | ||||
| # List of programs to build
 | ||||
| hostprogs-y := timestamping | ||||
| hostprogs-y := timestamping hwtstamp_config | ||||
| 
 | ||||
| # Tell kbuild to always build the programs
 | ||||
| always := $(hostprogs-y) | ||||
| 
 | ||||
| HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include | ||||
| HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include | ||||
| 
 | ||||
| clean: | ||||
| 	rm -f timestamping | ||||
| 	rm -f timestamping hwtstamp_config | ||||
|  |  | |||
							
								
								
									
										134
									
								
								Documentation/networking/timestamping/hwtstamp_config.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								Documentation/networking/timestamping/hwtstamp_config.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,134 @@ | |||
| /* Test program for SIOC{G,S}HWTSTAMP
 | ||||
|  * Copyright 2013 Solarflare Communications | ||||
|  * Author: Ben Hutchings | ||||
|  */ | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include <sys/socket.h> | ||||
| #include <sys/ioctl.h> | ||||
| 
 | ||||
| #include <linux/if.h> | ||||
| #include <linux/net_tstamp.h> | ||||
| #include <linux/sockios.h> | ||||
| 
 | ||||
| static int | ||||
| lookup_value(const char **names, int size, const char *name) | ||||
| { | ||||
| 	int value; | ||||
| 
 | ||||
| 	for (value = 0; value < size; value++) | ||||
| 		if (names[value] && strcasecmp(names[value], name) == 0) | ||||
| 			return value; | ||||
| 
 | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| static const char * | ||||
| lookup_name(const char **names, int size, int value) | ||||
| { | ||||
| 	return (value >= 0 && value < size) ? names[value] : NULL; | ||||
| } | ||||
| 
 | ||||
| static void list_names(FILE *f, const char **names, int size) | ||||
| { | ||||
| 	int value; | ||||
| 
 | ||||
| 	for (value = 0; value < size; value++) | ||||
| 		if (names[value]) | ||||
| 			fprintf(f, "    %s\n", names[value]); | ||||
| } | ||||
| 
 | ||||
| static const char *tx_types[] = { | ||||
| #define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name | ||||
| 	TX_TYPE(OFF), | ||||
| 	TX_TYPE(ON), | ||||
| 	TX_TYPE(ONESTEP_SYNC) | ||||
| #undef TX_TYPE | ||||
| }; | ||||
| #define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0]))) | ||||
| 
 | ||||
| static const char *rx_filters[] = { | ||||
| #define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name | ||||
| 	RX_FILTER(NONE), | ||||
| 	RX_FILTER(ALL), | ||||
| 	RX_FILTER(SOME), | ||||
| 	RX_FILTER(PTP_V1_L4_EVENT), | ||||
| 	RX_FILTER(PTP_V1_L4_SYNC), | ||||
| 	RX_FILTER(PTP_V1_L4_DELAY_REQ), | ||||
| 	RX_FILTER(PTP_V2_L4_EVENT), | ||||
| 	RX_FILTER(PTP_V2_L4_SYNC), | ||||
| 	RX_FILTER(PTP_V2_L4_DELAY_REQ), | ||||
| 	RX_FILTER(PTP_V2_L2_EVENT), | ||||
| 	RX_FILTER(PTP_V2_L2_SYNC), | ||||
| 	RX_FILTER(PTP_V2_L2_DELAY_REQ), | ||||
| 	RX_FILTER(PTP_V2_EVENT), | ||||
| 	RX_FILTER(PTP_V2_SYNC), | ||||
| 	RX_FILTER(PTP_V2_DELAY_REQ), | ||||
| #undef RX_FILTER | ||||
| }; | ||||
| #define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0]))) | ||||
| 
 | ||||
| static void usage(void) | ||||
| { | ||||
| 	fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n" | ||||
| 	      "tx_type is any of (case-insensitive):\n", | ||||
| 	      stderr); | ||||
| 	list_names(stderr, tx_types, N_TX_TYPES); | ||||
| 	fputs("rx_filter is any of (case-insensitive):\n", stderr); | ||||
| 	list_names(stderr, rx_filters, N_RX_FILTERS); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	struct ifreq ifr; | ||||
| 	struct hwtstamp_config config; | ||||
| 	const char *name; | ||||
| 	int sock; | ||||
| 
 | ||||
| 	if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) { | ||||
| 		usage(); | ||||
| 		return 2; | ||||
| 	} | ||||
| 
 | ||||
| 	if (argc == 4) { | ||||
| 		config.flags = 0; | ||||
| 		config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]); | ||||
| 		config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]); | ||||
| 		if (config.tx_type < 0 || config.rx_filter < 0) { | ||||
| 			usage(); | ||||
| 			return 2; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	sock = socket(AF_INET, SOCK_DGRAM, 0); | ||||
| 	if (sock < 0) { | ||||
| 		perror("socket"); | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	strcpy(ifr.ifr_name, argv[1]); | ||||
| 	ifr.ifr_data = (caddr_t)&config; | ||||
| 
 | ||||
| 	if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) { | ||||
| 		perror("ioctl"); | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	printf("flags = %#x\n", config.flags); | ||||
| 	name = lookup_name(tx_types, N_TX_TYPES, config.tx_type); | ||||
| 	if (name) | ||||
| 		printf("tx_type = %s\n", name); | ||||
| 	else | ||||
| 		printf("tx_type = %d\n", config.tx_type); | ||||
| 	name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter); | ||||
| 	if (name) | ||||
| 		printf("rx_filter = %s\n", name); | ||||
| 	else | ||||
| 		printf("rx_filter = %d\n", config.rx_filter); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -667,8 +667,8 @@ static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result) | |||
| 	return 1000000000UL / ppn; | ||||
| } | ||||
| 
 | ||||
| static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, | ||||
| 		struct ifreq *ifr, int cmd) | ||||
| static int bfin_mac_hwtstamp_set(struct net_device *netdev, | ||||
| 				 struct ifreq *ifr) | ||||
| { | ||||
| 	struct hwtstamp_config config; | ||||
| 	struct bfin_mac_local *lp = netdev_priv(netdev); | ||||
|  | @ -824,6 +824,16 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, | |||
| 		-EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int bfin_mac_hwtstamp_get(struct net_device *netdev, | ||||
| 				 struct ifreq *ifr) | ||||
| { | ||||
| 	struct bfin_mac_local *lp = netdev_priv(netdev); | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &lp->stamp_cfg, | ||||
| 			    sizeof(lp->stamp_cfg)) ? | ||||
| 		-EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) | ||||
| { | ||||
| 	struct bfin_mac_local *lp = netdev_priv(netdev); | ||||
|  | @ -1062,7 +1072,8 @@ static void bfin_phc_release(struct bfin_mac_local *lp) | |||
| #else | ||||
| # define bfin_mac_hwtstamp_is_none(cfg) 0 | ||||
| # define bfin_mac_hwtstamp_init(dev) | ||||
| # define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP) | ||||
| # define bfin_mac_hwtstamp_set(dev, ifr) (-EOPNOTSUPP) | ||||
| # define bfin_mac_hwtstamp_get(dev, ifr) (-EOPNOTSUPP) | ||||
| # define bfin_rx_hwtstamp(dev, skb) | ||||
| # define bfin_tx_hwtstamp(dev, skb) | ||||
| # define bfin_phc_init(netdev, dev) 0 | ||||
|  | @ -1496,7 +1507,9 @@ static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
| 
 | ||||
| 	switch (cmd) { | ||||
| 	case SIOCSHWTSTAMP: | ||||
| 		return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd); | ||||
| 		return bfin_mac_hwtstamp_set(netdev, ifr); | ||||
| 	case SIOCGHWTSTAMP: | ||||
| 		return bfin_mac_hwtstamp_get(netdev, ifr); | ||||
| 	default: | ||||
| 		if (lp->phydev) | ||||
| 			return phy_mii_ioctl(lp->phydev, ifr, cmd); | ||||
|  |  | |||
|  | @ -13594,14 +13594,13 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| static int tg3_hwtstamp_ioctl(struct net_device *dev, | ||||
| 			      struct ifreq *ifr, int cmd) | ||||
| static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct tg3 *tp = netdev_priv(dev); | ||||
| 	struct hwtstamp_config stmpconf; | ||||
| 
 | ||||
| 	if (!tg3_flag(tp, PTP_CAPABLE)) | ||||
| 		return -EINVAL; | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) | ||||
| 		return -EFAULT; | ||||
|  | @ -13682,6 +13681,67 @@ static int tg3_hwtstamp_ioctl(struct net_device *dev, | |||
| 		-EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int tg3_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct tg3 *tp = netdev_priv(dev); | ||||
| 	struct hwtstamp_config stmpconf; | ||||
| 
 | ||||
| 	if (!tg3_flag(tp, PTP_CAPABLE)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	stmpconf.flags = 0; | ||||
| 	stmpconf.tx_type = (tg3_flag(tp, TX_TSTAMP_EN) ? | ||||
| 			    HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF); | ||||
| 
 | ||||
| 	switch (tp->rxptpctl) { | ||||
| 	case 0: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_NONE; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_ALL_V1_EVENTS: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_SYNC_EVNT: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_DELAY_REQ: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_SYNC_EVNT: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_DELAY_REQ: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_DELAY_REQ: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ; | ||||
| 		break; | ||||
| 	case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_DELAY_REQ: | ||||
| 		stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; | ||||
| 		break; | ||||
| 	default: | ||||
| 		WARN_ON_ONCE(1); | ||||
| 		return -ERANGE; | ||||
| 	} | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? | ||||
| 		-EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | ||||
| { | ||||
| 	struct mii_ioctl_data *data = if_mii(ifr); | ||||
|  | @ -13735,7 +13795,10 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 		return err; | ||||
| 
 | ||||
| 	case SIOCSHWTSTAMP: | ||||
| 		return tg3_hwtstamp_ioctl(dev, ifr, cmd); | ||||
| 		return tg3_hwtstamp_set(dev, ifr); | ||||
| 
 | ||||
| 	case SIOCGHWTSTAMP: | ||||
| 		return tg3_hwtstamp_get(dev, ifr); | ||||
| 
 | ||||
| 	default: | ||||
| 		/* do nothing */ | ||||
|  |  | |||
|  | @ -339,7 +339,8 @@ struct fec_enet_private { | |||
| 
 | ||||
| void fec_ptp_init(struct platform_device *pdev); | ||||
| void fec_ptp_start_cyclecounter(struct net_device *ndev); | ||||
| int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd); | ||||
| int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); | ||||
| int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); | ||||
| 
 | ||||
| /****************************************************************************/ | ||||
| #endif /* FEC_H */ | ||||
|  |  | |||
|  | @ -1683,8 +1683,12 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) | |||
| 	if (!phydev) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	if (cmd == SIOCSHWTSTAMP && fep->bufdesc_ex) | ||||
| 		return fec_ptp_ioctl(ndev, rq, cmd); | ||||
| 	if (fep->bufdesc_ex) { | ||||
| 		if (cmd == SIOCSHWTSTAMP) | ||||
| 			return fec_ptp_set(ndev, rq); | ||||
| 		if (cmd == SIOCGHWTSTAMP) | ||||
| 			return fec_ptp_get(ndev, rq); | ||||
| 	} | ||||
| 
 | ||||
| 	return phy_mii_ioctl(phydev, rq, cmd); | ||||
| } | ||||
|  |  | |||
|  | @ -274,7 +274,7 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, | |||
|  * @ifreq: ioctl data | ||||
|  * @cmd: particular ioctl requested | ||||
|  */ | ||||
| int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) | ||||
| int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct fec_enet_private *fep = netdev_priv(ndev); | ||||
| 
 | ||||
|  | @ -321,6 +321,20 @@ int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) | |||
| 	    -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct fec_enet_private *fep = netdev_priv(ndev); | ||||
| 	struct hwtstamp_config config; | ||||
| 
 | ||||
| 	config.flags = 0; | ||||
| 	config.tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; | ||||
| 	config.rx_filter = (fep->hwts_rx_en ? | ||||
| 			    HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? | ||||
| 		-EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * fec_time_keep - call timecounter_read every second to avoid timer overrun | ||||
|  *                 because ENET just support 32bit counter, will timeout in 4s | ||||
|  |  | |||
|  | @ -795,8 +795,7 @@ err_grp_init: | |||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int gfar_hwtstamp_ioctl(struct net_device *netdev, | ||||
| 			       struct ifreq *ifr, int cmd) | ||||
| static int gfar_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct hwtstamp_config config; | ||||
| 	struct gfar_private *priv = netdev_priv(netdev); | ||||
|  | @ -845,7 +844,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev, | |||
| 		-EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| /* Ioctl MII Interface */ | ||||
| static int gfar_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct hwtstamp_config config; | ||||
| 	struct gfar_private *priv = netdev_priv(netdev); | ||||
| 
 | ||||
| 	config.flags = 0; | ||||
| 	config.tx_type = priv->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; | ||||
| 	config.rx_filter = (priv->hwts_rx_en ? | ||||
| 			    HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? | ||||
| 		-EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||||
| { | ||||
| 	struct gfar_private *priv = netdev_priv(dev); | ||||
|  | @ -854,7 +866,9 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (cmd == SIOCSHWTSTAMP) | ||||
| 		return gfar_hwtstamp_ioctl(dev, rq, cmd); | ||||
| 		return gfar_hwtstamp_set(dev, rq); | ||||
| 	if (cmd == SIOCGHWTSTAMP) | ||||
| 		return gfar_hwtstamp_get(dev, rq); | ||||
| 
 | ||||
| 	if (!priv->phydev) | ||||
| 		return -ENODEV; | ||||
|  |  | |||
|  | @ -5790,7 +5790,7 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, | |||
|  * specified. Matching the kind of event packet is not supported, with the | ||||
|  * exception of "all V2 events regardless of level 2 or 4". | ||||
|  **/ | ||||
| static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) | ||||
| static int e1000e_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct e1000_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct hwtstamp_config config; | ||||
|  | @ -5825,6 +5825,14 @@ static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) | |||
| 			    sizeof(config)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int e1000e_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct e1000_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &adapter->hwtstamp_config, | ||||
| 			    sizeof(adapter->hwtstamp_config)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||||
| { | ||||
| 	switch (cmd) { | ||||
|  | @ -5833,7 +5841,9 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
| 	case SIOCSMIIREG: | ||||
| 		return e1000_mii_ioctl(netdev, ifr, cmd); | ||||
| 	case SIOCSHWTSTAMP: | ||||
| 		return e1000e_hwtstamp_ioctl(netdev, ifr); | ||||
| 		return e1000e_hwtstamp_set(netdev, ifr); | ||||
| 	case SIOCGHWTSTAMP: | ||||
| 		return e1000e_hwtstamp_get(netdev, ifr); | ||||
| 	default: | ||||
| 		return -EOPNOTSUPP; | ||||
| 	} | ||||
|  |  | |||
|  | @ -2025,7 +2025,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) | ||||
| static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct mlx4_en_priv *priv = netdev_priv(dev); | ||||
| 	struct mlx4_en_dev *mdev = priv->mdev; | ||||
|  | @ -2084,11 +2084,21 @@ static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
| 			    sizeof(config)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int mlx4_en_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct mlx4_en_priv *priv = netdev_priv(dev); | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &priv->hwtstamp_config, | ||||
| 			    sizeof(priv->hwtstamp_config)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | ||||
| { | ||||
| 	switch (cmd) { | ||||
| 	case SIOCSHWTSTAMP: | ||||
| 		return mlx4_en_hwtstamp_ioctl(dev, ifr); | ||||
| 		return mlx4_en_hwtstamp_set(dev, ifr); | ||||
| 	case SIOCGHWTSTAMP: | ||||
| 		return mlx4_en_hwtstamp_get(dev, ifr); | ||||
| 	default: | ||||
| 		return -EOPNOTSUPP; | ||||
| 	} | ||||
|  |  | |||
|  | @ -3189,7 +3189,7 @@ static enum vxge_hw_status vxge_timestamp_config(struct __vxge_hw_device *devh) | |||
| 	return status; | ||||
| } | ||||
| 
 | ||||
| static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) | ||||
| static int vxge_hwtstamp_set(struct vxgedev *vdev, void __user *data) | ||||
| { | ||||
| 	struct hwtstamp_config config; | ||||
| 	int i; | ||||
|  | @ -3250,6 +3250,21 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int vxge_hwtstamp_get(struct vxgedev *vdev, void __user *data) | ||||
| { | ||||
| 	struct hwtstamp_config config; | ||||
| 
 | ||||
| 	config.flags = 0; | ||||
| 	config.tx_type = HWTSTAMP_TX_OFF; | ||||
| 	config.rx_filter = (vdev->rx_hwts ? | ||||
| 			    HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); | ||||
| 
 | ||||
| 	if (copy_to_user(data, &config, sizeof(config))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * vxge_ioctl | ||||
|  * @dev: Device pointer. | ||||
|  | @ -3263,19 +3278,15 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) | |||
| static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||||
| { | ||||
| 	struct vxgedev *vdev = netdev_priv(dev); | ||||
| 	int ret; | ||||
| 
 | ||||
| 	switch (cmd) { | ||||
| 	case SIOCSHWTSTAMP: | ||||
| 		ret = vxge_hwtstamp_ioctl(vdev, rq->ifr_data); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 		break; | ||||
| 		return vxge_hwtstamp_set(vdev, rq->ifr_data); | ||||
| 	case SIOCGHWTSTAMP: | ||||
| 		return vxge_hwtstamp_get(vdev, rq->ifr_data); | ||||
| 	default: | ||||
| 		return -EOPNOTSUPP; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -1847,7 +1847,9 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) | |||
| 	struct mii_ioctl_data *data = if_mii(ifr); | ||||
| 
 | ||||
| 	if (cmd == SIOCSHWTSTAMP) | ||||
| 		return efx_ptp_ioctl(efx, ifr, cmd); | ||||
| 		return efx_ptp_set_ts_config(efx, ifr); | ||||
| 	if (cmd == SIOCGHWTSTAMP) | ||||
| 		return efx_ptp_get_ts_config(efx, ifr); | ||||
| 
 | ||||
| 	/* Convert phy_id from older PRTAD/DEVAD format */ | ||||
| 	if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) && | ||||
|  |  | |||
|  | @ -555,7 +555,8 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, | |||
| 
 | ||||
| struct ethtool_ts_info; | ||||
| void efx_ptp_probe(struct efx_nic *efx); | ||||
| int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd); | ||||
| int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); | ||||
| int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); | ||||
| void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); | ||||
| bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); | ||||
| int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); | ||||
|  |  | |||
|  | @ -1231,7 +1231,7 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) | |||
| 			       1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); | ||||
| } | ||||
| 
 | ||||
| int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd) | ||||
| int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr) | ||||
| { | ||||
| 	struct hwtstamp_config config; | ||||
| 	int rc; | ||||
|  | @ -1251,6 +1251,15 @@ int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd) | |||
| 		? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr) | ||||
| { | ||||
| 	if (!efx->ptp_data) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &efx->ptp_data->config, | ||||
| 			    sizeof(efx->ptp_data->config)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static void ptp_event_failure(struct efx_nic *efx, int expected_frag_len) | ||||
| { | ||||
| 	struct efx_ptp_data *ptp = efx->ptp_data; | ||||
|  |  | |||
|  | @ -1322,7 +1322,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv) | |||
| 	__raw_writel(ETH_P_1588, &priv->regs->ts_ltype); | ||||
| } | ||||
| 
 | ||||
| static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) | ||||
| static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct cpsw_priv *priv = netdev_priv(dev); | ||||
| 	struct cpts *cpts = priv->cpts; | ||||
|  | @ -1383,6 +1383,24 @@ static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
| 	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct cpsw_priv *priv = netdev_priv(dev); | ||||
| 	struct cpts *cpts = priv->cpts; | ||||
| 	struct hwtstamp_config cfg; | ||||
| 
 | ||||
| 	if (priv->version != CPSW_VERSION_1 && | ||||
| 	    priv->version != CPSW_VERSION_2) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	cfg.flags = 0; | ||||
| 	cfg.tx_type = cpts->tx_enable ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; | ||||
| 	cfg.rx_filter = (cpts->rx_enable ? | ||||
| 			 HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE); | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| #endif /*CONFIG_TI_CPTS*/ | ||||
| 
 | ||||
| static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | ||||
|  | @ -1397,7 +1415,9 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | |||
| 	switch (cmd) { | ||||
| #ifdef CONFIG_TI_CPTS | ||||
| 	case SIOCSHWTSTAMP: | ||||
| 		return cpsw_hwtstamp_ioctl(dev, req); | ||||
| 		return cpsw_hwtstamp_set(dev, req); | ||||
| 	case SIOCGHWTSTAMP: | ||||
| 		return cpsw_hwtstamp_get(dev, req); | ||||
| #endif | ||||
| 	case SIOCGMIIPHY: | ||||
| 		data->phy_id = priv->slaves[slave_no].phy->addr; | ||||
|  |  | |||
|  | @ -481,8 +481,7 @@ static void tile_tx_timestamp(struct sk_buff *skb, int instance) | |||
| } | ||||
| 
 | ||||
| /* Use ioctl() to enable or disable TX or RX timestamping. */ | ||||
| static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq, | ||||
| 			       int cmd) | ||||
| static int tile_hwtstamp_set(struct net_device *dev, struct ifreq *rq) | ||||
| { | ||||
| #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||||
| 	struct hwtstamp_config config; | ||||
|  | @ -535,6 +534,21 @@ static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq, | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| static int tile_hwtstamp_get(struct net_device *dev, struct ifreq *rq) | ||||
| { | ||||
| #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||||
| 	struct tile_net_priv *priv = netdev_priv(dev); | ||||
| 
 | ||||
| 	if (copy_to_user(rq->ifr_data, &priv->stamp_cfg, | ||||
| 			 sizeof(priv->stamp_cfg))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return 0; | ||||
| #else | ||||
| 	return -EOPNOTSUPP; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static inline bool filter_packet(struct net_device *dev, void *buf) | ||||
| { | ||||
| 	/* Filter packets received before we're up. */ | ||||
|  | @ -2098,7 +2112,9 @@ static void tile_net_tx_timeout(struct net_device *dev) | |||
| static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||||
| { | ||||
| 	if (cmd == SIOCSHWTSTAMP) | ||||
| 		return tile_hwtstamp_ioctl(dev, rq, cmd); | ||||
| 		return tile_hwtstamp_set(dev, rq); | ||||
| 	if (cmd == SIOCGHWTSTAMP) | ||||
| 		return tile_hwtstamp_get(dev, rq); | ||||
| 
 | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
|  |  | |||
|  | @ -373,7 +373,7 @@ static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb) | |||
| 	__raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); | ||||
| } | ||||
| 
 | ||||
| static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||||
| static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct hwtstamp_config cfg; | ||||
| 	struct ixp46x_ts_regs *regs; | ||||
|  | @ -417,6 +417,32 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
| 	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) | ||||
| { | ||||
| 	struct hwtstamp_config cfg; | ||||
| 	struct port *port = netdev_priv(netdev); | ||||
| 
 | ||||
| 	cfg.flags = 0; | ||||
| 	cfg.tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; | ||||
| 
 | ||||
| 	switch (port->hwts_rx_en) { | ||||
| 	case 0: | ||||
| 		cfg.rx_filter = HWTSTAMP_FILTER_NONE; | ||||
| 		break; | ||||
| 	case PTP_SLAVE_MODE: | ||||
| 		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; | ||||
| 		break; | ||||
| 	case PTP_MASTER_MODE: | ||||
| 		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; | ||||
| 		break; | ||||
| 	default: | ||||
| 		WARN_ON_ONCE(1); | ||||
| 		return -ERANGE; | ||||
| 	} | ||||
| 
 | ||||
| 	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; | ||||
| } | ||||
| 
 | ||||
| static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, | ||||
| 			   int write, u16 cmd) | ||||
| { | ||||
|  | @ -959,8 +985,12 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | |||
| 	if (!netif_running(dev)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP) | ||||
| 		return hwtstamp_ioctl(dev, req, cmd); | ||||
| 	if (cpu_is_ixp46x()) { | ||||
| 		if (cmd == SIOCSHWTSTAMP) | ||||
| 			return hwtstamp_set(dev, req); | ||||
| 		if (cmd == SIOCGHWTSTAMP) | ||||
| 			return hwtstamp_get(dev, req); | ||||
| 	} | ||||
| 
 | ||||
| 	return phy_mii_ioctl(port->phydev, req, cmd); | ||||
| } | ||||
|  |  | |||
|  | @ -26,17 +26,17 @@ enum { | |||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct hwtstamp_config - %SIOCSHWTSTAMP parameter | ||||
|  * struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter | ||||
|  * | ||||
|  * @flags:	no flags defined right now, must be zero | ||||
|  * @flags:	no flags defined right now, must be zero for %SIOCSHWTSTAMP | ||||
|  * @tx_type:	one of HWTSTAMP_TX_* | ||||
|  * @rx_type:	one of one of HWTSTAMP_FILTER_* | ||||
|  * @rx_filter:	one of HWTSTAMP_FILTER_* | ||||
|  * | ||||
|  * %SIOCSHWTSTAMP expects a &struct ifreq with a ifr_data pointer to | ||||
|  * this structure. dev_ifsioc() in the kernel takes care of the | ||||
|  * translation between 32 bit userspace and 64 bit kernel. The | ||||
|  * structure is intentionally chosen so that it has the same layout on | ||||
|  * 32 and 64 bit systems, don't break this! | ||||
|  * %SIOCGHWTSTAMP and %SIOCSHWTSTAMP expect a &struct ifreq with a | ||||
|  * ifr_data pointer to this structure.  For %SIOCSHWTSTAMP, if the | ||||
|  * driver or hardware does not support the requested @rx_filter value, | ||||
|  * the driver may use a more general filter mode.  In this case | ||||
|  * @rx_filter will indicate the actual mode on return. | ||||
|  */ | ||||
| struct hwtstamp_config { | ||||
| 	int flags; | ||||
|  |  | |||
|  | @ -125,7 +125,8 @@ | |||
| #define SIOCBRDELIF	0x89a3		/* remove interface from bridge */ | ||||
| 
 | ||||
| /* hardware time stamping: parameters in linux/net_tstamp.h */ | ||||
| #define SIOCSHWTSTAMP   0x89b0 | ||||
| #define SIOCSHWTSTAMP	0x89b0		/* set and get config		*/ | ||||
| #define SIOCGHWTSTAMP	0x89b1		/* get config			*/ | ||||
| 
 | ||||
| /* Device private ioctl calls */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -327,6 +327,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
| 		    cmd == SIOCBRADDIF || | ||||
| 		    cmd == SIOCBRDELIF || | ||||
| 		    cmd == SIOCSHWTSTAMP || | ||||
| 		    cmd == SIOCGHWTSTAMP || | ||||
| 		    cmd == SIOCWANDEV) { | ||||
| 			err = -EOPNOTSUPP; | ||||
| 			if (ops->ndo_do_ioctl) { | ||||
|  | @ -546,6 +547,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
| 	 */ | ||||
| 	default: | ||||
| 		if (cmd == SIOCWANDEV || | ||||
| 		    cmd == SIOCGHWTSTAMP || | ||||
| 		    (cmd >= SIOCDEVPRIVATE && | ||||
| 		     cmd <= SIOCDEVPRIVATE + 15)) { | ||||
| 			dev_load(net, ifr.ifr_name); | ||||
|  |  | |||
							
								
								
									
										57
									
								
								net/socket.c
									
										
									
									
									
								
							
							
						
						
									
										57
									
								
								net/socket.c
									
										
									
									
									
								
							|  | @ -2968,11 +2968,8 @@ static int bond_ioctl(struct net *net, unsigned int cmd, | |||
| 			 struct compat_ifreq __user *ifr32) | ||||
| { | ||||
| 	struct ifreq kifr; | ||||
| 	struct ifreq __user *uifr; | ||||
| 	mm_segment_t old_fs; | ||||
| 	int err; | ||||
| 	u32 data; | ||||
| 	void __user *datap; | ||||
| 
 | ||||
| 	switch (cmd) { | ||||
| 	case SIOCBONDENSLAVE: | ||||
|  | @ -2989,26 +2986,13 @@ static int bond_ioctl(struct net *net, unsigned int cmd, | |||
| 		set_fs(old_fs); | ||||
| 
 | ||||
| 		return err; | ||||
| 	case SIOCBONDSLAVEINFOQUERY: | ||||
| 	case SIOCBONDINFOQUERY: | ||||
| 		uifr = compat_alloc_user_space(sizeof(*uifr)); | ||||
| 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) | ||||
| 			return -EFAULT; | ||||
| 
 | ||||
| 		if (get_user(data, &ifr32->ifr_ifru.ifru_data)) | ||||
| 			return -EFAULT; | ||||
| 
 | ||||
| 		datap = compat_ptr(data); | ||||
| 		if (put_user(datap, &uifr->ifr_ifru.ifru_data)) | ||||
| 			return -EFAULT; | ||||
| 
 | ||||
| 		return dev_ioctl(net, cmd, uifr); | ||||
| 	default: | ||||
| 		return -ENOIOCTLCMD; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, | ||||
| /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ | ||||
| static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, | ||||
| 				 struct compat_ifreq __user *u_ifreq32) | ||||
| { | ||||
| 	struct ifreq __user *u_ifreq64; | ||||
|  | @ -3019,19 +3003,16 @@ static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, | |||
| 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), | ||||
| 			   IFNAMSIZ)) | ||||
| 		return -EFAULT; | ||||
| 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) | ||||
| 	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) | ||||
| 		return -EFAULT; | ||||
| 	data64 = compat_ptr(data32); | ||||
| 
 | ||||
| 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); | ||||
| 
 | ||||
| 	/* Don't check these user accesses, just let that get trapped
 | ||||
| 	 * in the ioctl handler instead. | ||||
| 	 */ | ||||
| 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], | ||||
| 			 IFNAMSIZ)) | ||||
| 		return -EFAULT; | ||||
| 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) | ||||
| 	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return dev_ioctl(net, cmd, u_ifreq64); | ||||
|  | @ -3111,27 +3092,6 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd, | |||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32) | ||||
| { | ||||
| 	void __user *uptr; | ||||
| 	compat_uptr_t uptr32; | ||||
| 	struct ifreq __user *uifr; | ||||
| 
 | ||||
| 	uifr = compat_alloc_user_space(sizeof(*uifr)); | ||||
| 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	if (get_user(uptr32, &uifr32->ifr_data)) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	uptr = compat_ptr(uptr32); | ||||
| 
 | ||||
| 	if (put_user(uptr, &uifr->ifr_data)) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr); | ||||
| } | ||||
| 
 | ||||
| struct rtentry32 { | ||||
| 	u32		rt_pad1; | ||||
| 	struct sockaddr rt_dst;         /* target address               */ | ||||
|  | @ -3243,7 +3203,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | |||
| 	struct net *net = sock_net(sk); | ||||
| 
 | ||||
| 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) | ||||
| 		return siocdevprivate_ioctl(net, cmd, argp); | ||||
| 		return compat_ifr_data_ioctl(net, cmd, argp); | ||||
| 
 | ||||
| 	switch (cmd) { | ||||
| 	case SIOCSIFBR: | ||||
|  | @ -3263,8 +3223,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | |||
| 	case SIOCBONDENSLAVE: | ||||
| 	case SIOCBONDRELEASE: | ||||
| 	case SIOCBONDSETHWADDR: | ||||
| 	case SIOCBONDSLAVEINFOQUERY: | ||||
| 	case SIOCBONDINFOQUERY: | ||||
| 	case SIOCBONDCHANGEACTIVE: | ||||
| 		return bond_ioctl(net, cmd, argp); | ||||
| 	case SIOCADDRT: | ||||
|  | @ -3274,8 +3232,11 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | |||
| 		return do_siocgstamp(net, sock, cmd, argp); | ||||
| 	case SIOCGSTAMPNS: | ||||
| 		return do_siocgstampns(net, sock, cmd, argp); | ||||
| 	case SIOCBONDSLAVEINFOQUERY: | ||||
| 	case SIOCBONDINFOQUERY: | ||||
| 	case SIOCSHWTSTAMP: | ||||
| 		return compat_siocshwtstamp(net, argp); | ||||
| 	case SIOCGHWTSTAMP: | ||||
| 		return compat_ifr_data_ioctl(net, cmd, argp); | ||||
| 
 | ||||
| 	case FIOSETOWN: | ||||
| 	case SIOCSPGRP: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 David S. Miller
				David S. Miller