aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/xscale/ixp4xx_eth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/xscale/ixp4xx_eth.c')
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c112
1 files changed, 79 insertions, 33 deletions
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index 41a8b5a9849..f7e0f0f7c2e 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -256,10 +256,6 @@ static int ports_open;
static struct port *npe_port_tab[MAX_NPES];
static struct dma_pool *dma_pool;
-static struct sock_filter ptp_filter[] = {
- PTP_FILTER
-};
-
static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
{
u8 *data = skb->data;
@@ -267,7 +263,7 @@ static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
u16 *hi, *id;
u32 lo;
- if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4)
+ if (ptp_classify_raw(skb) != PTP_CLASS_V1_IPV4)
return 0;
offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
@@ -373,7 +369,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;
@@ -389,16 +385,8 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
ch = PORT2CHANNEL(port);
regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
- switch (cfg.tx_type) {
- case HWTSTAMP_TX_OFF:
- port->hwts_tx_en = 0;
- break;
- case HWTSTAMP_TX_ON:
- port->hwts_tx_en = 1;
- break;
- default:
+ if (cfg.tx_type != HWTSTAMP_TX_OFF && cfg.tx_type != HWTSTAMP_TX_ON)
return -ERANGE;
- }
switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE:
@@ -416,6 +404,8 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
return -ERANGE;
}
+ port->hwts_tx_en = cfg.tx_type == HWTSTAMP_TX_ON;
+
/* Clear out any old time stamps. */
__raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED,
&regs->channel[ch].ch_event);
@@ -423,6 +413,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)
{
@@ -965,8 +981,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);
}
@@ -977,11 +997,12 @@ static void ixp4xx_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
struct port *port = netdev_priv(dev);
- strcpy(info->driver, DRV_NAME);
+
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
snprintf(info->fw_version, sizeof(info->fw_version), "%u:%u:%u:%u",
port->firmware[0], port->firmware[1],
port->firmware[2], port->firmware[3]);
- strcpy(info->bus_info, "internal");
+ strlcpy(info->bus_info, "internal", sizeof(info->bus_info));
}
static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -1002,12 +1023,42 @@ static int ixp4xx_nway_reset(struct net_device *dev)
return phy_start_aneg(port->phydev);
}
+int ixp46x_phc_index = -1;
+EXPORT_SYMBOL_GPL(ixp46x_phc_index);
+
+static int ixp4xx_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *info)
+{
+ if (!cpu_is_ixp46x()) {
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;
+ info->phc_index = -1;
+ return 0;
+ }
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->phc_index = ixp46x_phc_index;
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ);
+ return 0;
+}
+
static const struct ethtool_ops ixp4xx_ethtool_ops = {
.get_drvinfo = ixp4xx_get_drvinfo,
.get_settings = ixp4xx_get_settings,
.set_settings = ixp4xx_set_settings,
.nway_reset = ixp4xx_nway_reset,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ixp4xx_get_ts_info,
};
@@ -1072,10 +1123,12 @@ static int init_queues(struct port *port)
{
int i;
- if (!ports_open)
- if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
- POOL_ALLOC_SIZE, 32, 0)))
+ if (!ports_open) {
+ dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+ POOL_ALLOC_SIZE, 32, 0);
+ if (!dma_pool)
return -ENOMEM;
+ }
if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
&port->desc_tab_phys)))
@@ -1347,20 +1400,15 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit eth_init_one(struct platform_device *pdev)
+static int eth_init_one(struct platform_device *pdev)
{
struct port *port;
struct net_device *dev;
- struct eth_plat_info *plat = pdev->dev.platform_data;
+ struct eth_plat_info *plat = dev_get_platdata(&pdev->dev);
u32 regs_phys;
char phy_id[MII_BUS_ID_SIZE + 3];
int err;
- if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
- pr_err("ixp4xx_eth: bad ptp filter\n");
- return -EINVAL;
- }
-
if (!(dev = alloc_etherdev(sizeof(struct port))))
return -ENOMEM;
@@ -1418,7 +1466,7 @@ static int __devinit eth_init_one(struct platform_device *pdev)
snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
mdio_bus->id, plat->phy);
- port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
+ port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link,
PHY_INTERFACE_MODE_MII);
if (IS_ERR(port->phydev)) {
err = PTR_ERR(port->phydev);
@@ -1439,7 +1487,6 @@ err_phy_dis:
phy_disconnect(port->phydev);
err_free_mem:
npe_port_tab[NPE_ID(port->id)] = NULL;
- platform_set_drvdata(pdev, NULL);
release_resource(port->mem_res);
err_npe_rel:
npe_release(port->npe);
@@ -1448,7 +1495,7 @@ err_free:
return err;
}
-static int __devexit eth_remove_one(struct platform_device *pdev)
+static int eth_remove_one(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct port *port = netdev_priv(dev);
@@ -1456,7 +1503,6 @@ static int __devexit eth_remove_one(struct platform_device *pdev)
unregister_netdev(dev);
phy_disconnect(port->phydev);
npe_port_tab[NPE_ID(port->id)] = NULL;
- platform_set_drvdata(pdev, NULL);
npe_release(port->npe);
release_resource(port->mem_res);
free_netdev(dev);