static ssize_t gfar_set_rx_stash_index(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar __iomem *regs = priv->gfargrp[0].regs; unsigned short index = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) return count; local_irq_save(flags); lock_rx_qs(priv); if (index > priv->rx_stash_size) goto out; if (index == priv->rx_stash_index) goto out; priv->rx_stash_index = index; temp = gfar_read(®s->attreli); temp &= ~ATTRELI_EI_MASK; temp |= ATTRELI_EI(index); gfar_write(®s->attreli, temp); out: unlock_rx_qs(priv); local_irq_restore(flags); return count; }
/* Write value to the PHY at mii_id at register regnum, * on the bus, waiting until the write is done before returning. * All PHY configuration is done through the TSEC1 MIIM regs */ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; /* Set the PHY address and the register address we want to write */ gfar_write(®s->miimadd, (mii_id << 8) | regnum); /* Write out the value we want */ gfar_write(®s->miimcon, value); /* Wait for the transaction to finish */ while (gfar_read(®s->miimind) & MIIMIND_BUSY) cpu_relax(); return 0; }
static ssize_t gfar_set_rx_stash_size(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar __iomem *regs = priv->gfargrp[0].regs; unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) return count; local_irq_save(flags); lock_rx_qs(priv); if (length > priv->rx_buffer_size) goto out; if (length == priv->rx_stash_size) goto out; priv->rx_stash_size = length; temp = gfar_read(®s->attreli); temp &= ~ATTRELI_EL_MASK; temp |= ATTRELI_EL(length); gfar_write(®s->attreli, temp); /* Turn stashing on/off as appropriate */ temp = gfar_read(®s->attr); if (length) temp |= ATTR_BUFSTASH; else temp &= ~(ATTR_BUFSTASH); gfar_write(®s->attr, temp); out: unlock_rx_qs(priv); local_irq_restore(flags); return count; }
/* Read the bus for PHY at addr mii_id, register regnum, and * return the value. Clears miimcom first. All PHY * Operation done on the bus attached to the local interface, * which may be different from the generic mdio bus * This is helpful in programming interfaces like * the TBI which, inturn, control interfaces like onchip SERDES * and are always tied to the local mdio pins, which may not be the * same as system mdio bus, used for controlling the external PHYs, for example. */ int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum) { u16 value; /* Set the PHY address and the register address we want to read */ gfar_write(®s->miimadd, (mii_id << 8) | regnum); /* Clear miimcom, and then initiate a read */ gfar_write(®s->miimcom, 0); gfar_write(®s->miimcom, MII_READ_COMMAND); /* Wait for the transaction to finish */ while (gfar_read(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) cpu_relax(); /* Grab the value of the register from miimstat */ value = gfar_read(®s->miimstat); return value; }
static ssize_t gfar_set_rx_stash_size(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) return count; spin_lock_irqsave(&priv->rxlock, flags); if (length > priv->rx_buffer_size) goto out; if (length == priv->rx_stash_size) goto out; priv->rx_stash_size = length; temp = gfar_read(&priv->regs->attreli); temp &= ~ATTRELI_EL_MASK; temp |= ATTRELI_EL(length); gfar_write(&priv->regs->attreli, temp); temp = gfar_read(&priv->regs->attr); if (length) temp |= ATTR_BUFSTASH; else temp &= ~(ATTR_BUFSTASH); gfar_write(&priv->regs->attr, temp); out: spin_unlock_irqrestore(&priv->rxlock, flags); return count; }
/* Change the coalescing values. * Both cvals->*_usecs and cvals->*_frames have to be > 0 * in order for coalescing to be active */ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { struct gfar_private *priv = netdev_priv(dev); if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) return -EOPNOTSUPP; /* Set up rx coalescing */ if ((cvals->rx_coalesce_usecs == 0) || (cvals->rx_max_coalesced_frames == 0)) priv->rxcoalescing = 0; else priv->rxcoalescing = 1; priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs); priv->rxcount = cvals->rx_max_coalesced_frames; /* Set up tx coalescing */ if ((cvals->tx_coalesce_usecs == 0) || (cvals->tx_max_coalesced_frames == 0)) priv->txcoalescing = 0; else priv->txcoalescing = 1; priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs); priv->txcount = cvals->tx_max_coalesced_frames; if (priv->rxcoalescing) gfar_write(&priv->regs->rxic, mk_ic_value(priv->rxcount, priv->rxtime)); else gfar_write(&priv->regs->rxic, 0); if (priv->txcoalescing) gfar_write(&priv->regs->txic, mk_ic_value(priv->txcount, priv->txtime)); else gfar_write(&priv->regs->txic, 0); return 0; }
/* configuration has to be done through the TSEC1 MIIM regs */ int read_phy_reg(struct net_device *dev, int mii_id, int regnum) { struct gfar_private *priv = netdev_priv(dev); struct gfar *regbase = priv->phyregs; u16 value; /* Set the PHY address and the register address we want to read */ gfar_write(®base->miimadd, (mii_id << 8) | regnum); /* Clear miimcom, and then initiate a read */ gfar_write(®base->miimcom, 0); gfar_write(®base->miimcom, MII_READ_COMMAND); /* Wait for the transaction to finish */ while (gfar_read(®base->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) cpu_relax(); /* Grab the value of the register from miimstat */ value = gfar_read(®base->miimstat); return value; }
static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, const char *buf, size_t count) { struct net_device *dev = to_net_dev(cdev); struct gfar_private *priv = netdev_priv(dev); unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; spin_lock_irqsave(&priv->rxlock, flags); if (length > priv->rx_buffer_size) return count; if (length == priv->rx_stash_size) return count; priv->rx_stash_size = length; temp = gfar_read(&priv->regs->attreli); temp &= ~ATTRELI_EL_MASK; temp |= ATTRELI_EL(length); gfar_write(&priv->regs->attreli, temp); /* Turn stashing on/off as appropriate */ temp = gfar_read(&priv->regs->attr); if (length) temp |= ATTR_BUFSTASH; else temp &= ~(ATTR_BUFSTASH); gfar_write(&priv->regs->attr, temp); spin_unlock_irqrestore(&priv->rxlock, flags); return count; }
static ssize_t gfar_set_bd_stash(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar __iomem *regs = priv->gfargrp[0].regs; int new_setting = 0; u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) return count; /* Find out the new setting */ if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) new_setting = 1; else if (!strncmp("off", buf, count - 1) || !strncmp("0", buf, count - 1)) new_setting = 0; else return count; local_irq_save(flags); lock_rx_qs(priv); /* Set the new stashing value */ priv->bd_stash_en = new_setting; temp = gfar_read(®s->attr); if (new_setting) temp |= ATTR_BDSTASH; else temp &= ~(ATTR_BDSTASH); gfar_write(®s->attr, temp); unlock_rx_qs(priv); local_irq_restore(flags); return count; }
static ssize_t gfar_set_bd_stash(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); int new_setting = 0; u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) return count; if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) new_setting = 1; else if (!strncmp("off", buf, count - 1) || !strncmp("0", buf, count - 1)) new_setting = 0; else return count; spin_lock_irqsave(&priv->rxlock, flags); priv->bd_stash_en = new_setting; temp = gfar_read(&priv->regs->attr); if (new_setting) temp |= ATTR_BDSTASH; else temp &= ~(ATTR_BDSTASH); gfar_write(&priv->regs->attr, temp); spin_unlock_irqrestore(&priv->rxlock, flags); return count; }
/************************************************************************************************** Syntax: static void p2020_tsec_set_hardware_reg_configuration Parameters: Remarks: set p2020 etsec registers configurations for hardware Return Value: ***************************************************************************************************/ void p2020_tsec_set_hardware_reg_configuration(struct net_device *dev) { struct dev_mc_list *mc_ptr; struct gfar_private *priv = netdev_priv(dev); struct gfar *regs = priv->gfargrp[0].regs; u32 tempval; //Zoya [04 апр. 2014 г.] ///Ошибка! не работает??? // Set RCTRL to PROMISC mode printk("++Enable Promis mode for %s\n\r", dev->name); tempval = gfar_read(®s->rctrl); tempval |= RCTRL_PROM; gfar_write(®s->rctrl, tempval); /* printk("++Enable Multicast Frame for eth2\n\r++"); //Set multicast frames incoming packet gfar_write(®s->igaddr0, 0xffffffff); gfar_write(®s->igaddr1, 0xffffffff); gfar_write(®s->igaddr2, 0xffffffff); gfar_write(®s->igaddr3, 0xffffffff); gfar_write(®s->igaddr4, 0xffffffff); gfar_write(®s->igaddr5, 0xffffffff); gfar_write(®s->igaddr6, 0xffffffff); gfar_write(®s->igaddr7, 0xffffffff); gfar_write(®s->gaddr0, 0xffffffff); gfar_write(®s->gaddr1, 0xffffffff); gfar_write(®s->gaddr2, 0xffffffff); gfar_write(®s->gaddr3, 0xffffffff); gfar_write(®s->gaddr4, 0xffffffff); gfar_write(®s->gaddr5, 0xffffffff); gfar_write(®s->gaddr6, 0xffffffff); gfar_write(®s->gaddr7, 0xffffffff); */ }
static int gfar_spauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { struct gfar_private *priv = netdev_priv(dev); struct phy_device *phydev = priv->phydev; struct gfar __iomem *regs = priv->gfargrp[0].regs; u32 oldadv, newadv; if (!phydev) return -ENODEV; if (!(phydev->supported & SUPPORTED_Pause) || (!(phydev->supported & SUPPORTED_Asym_Pause) && (epause->rx_pause != epause->tx_pause))) return -EINVAL; priv->rx_pause_en = priv->tx_pause_en = 0; if (epause->rx_pause) { priv->rx_pause_en = 1; if (epause->tx_pause) { priv->tx_pause_en = 1; /* FLOW_CTRL_RX & TX */ newadv = ADVERTISED_Pause; } else /* FLOW_CTLR_RX */ newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause; } else if (epause->tx_pause) { priv->tx_pause_en = 1; /* FLOW_CTLR_TX */ newadv = ADVERTISED_Asym_Pause; } else newadv = 0; if (epause->autoneg) priv->pause_aneg_en = 1; else priv->pause_aneg_en = 0; oldadv = phydev->advertising & (ADVERTISED_Pause | ADVERTISED_Asym_Pause); if (oldadv != newadv) { phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); phydev->advertising |= newadv; if (phydev->autoneg) /* inform link partner of our * new flow ctrl settings */ return phy_start_aneg(phydev); if (!epause->autoneg) { u32 tempval; tempval = gfar_read(®s->maccfg1); tempval &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); priv->tx_actual_en = 0; if (priv->tx_pause_en) { priv->tx_actual_en = 1; tempval |= MACCFG1_TX_FLOW; } if (priv->rx_pause_en) tempval |= MACCFG1_RX_FLOW; gfar_write(®s->maccfg1, tempval); } } return 0; }
/* Change the coalescing values. * Both cvals->*_usecs and cvals->*_frames have to be > 0 * in order for coalescing to be active */ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { struct gfar_private *priv = netdev_priv(dev); if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) return -EOPNOTSUPP; /* Set up rx coalescing */ if ((cvals->rx_coalesce_usecs == 0) || (cvals->rx_max_coalesced_frames == 0)) priv->rxcoalescing = 0; else priv->rxcoalescing = 1; if (NULL == priv->phydev) return -ENODEV; /* Check the bounds of the values */ if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) { pr_info("Coalescing is limited to %d microseconds\n", GFAR_MAX_COAL_USECS); return -EINVAL; } if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { pr_info("Coalescing is limited to %d frames\n", GFAR_MAX_COAL_FRAMES); return -EINVAL; } priv->rxic = mk_ic_value(cvals->rx_max_coalesced_frames, gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs)); /* Set up tx coalescing */ if ((cvals->tx_coalesce_usecs == 0) || (cvals->tx_max_coalesced_frames == 0)) priv->txcoalescing = 0; else priv->txcoalescing = 1; /* Check the bounds of the values */ if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { pr_info("Coalescing is limited to %d microseconds\n", GFAR_MAX_COAL_USECS); return -EINVAL; } if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { pr_info("Coalescing is limited to %d frames\n", GFAR_MAX_COAL_FRAMES); return -EINVAL; } priv->txic = mk_ic_value(cvals->tx_max_coalesced_frames, gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); gfar_write(&priv->regs->rxic, 0); if (priv->rxcoalescing) gfar_write(&priv->regs->rxic, priv->rxic); gfar_write(&priv->regs->txic, 0); if (priv->txcoalescing) gfar_write(&priv->regs->txic, priv->txic); return 0; }