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:
David S. Miller 2013-12-05 19:45:14 -05:00
commit 426e1fa31e
23 changed files with 423 additions and 100 deletions

View File

@ -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

View File

@ -1 +1,2 @@
timestamping
hwtstamp_config

View File

@ -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

View 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;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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

View File

@ -795,8 +795,7 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
/**

View File

@ -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) &&

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -373,7 +373,7 @@ static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb)
__raw_writel(TX_SNAPSHOT_LOCKED, &regs->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);
}

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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: