#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
+#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/delay.h>
#define GEM_MODULE_NAME "gem"
#define PFX GEM_MODULE_NAME ": "
-static struct pci_device_id gem_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(gem_pci_tbl) = {
{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
cmd |= (MIF_FRAME_TAMSB);
writel(cmd, gp->regs + MIF_FRAME);
- while (limit--) {
+ while (--limit) {
cmd = readl(gp->regs + MIF_FRAME);
if (cmd & MIF_FRAME_TALSB)
break;
static inline int _phy_read(struct net_device *dev, int mii_id, int reg)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
return __phy_read(gp, mii_id, reg);
}
static inline void _phy_write(struct net_device *dev, int mii_id, int reg, int val)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
__phy_write(gp, mii_id, reg, val & 0xffff);
}
gp->net_stats.rx_packets++;
gp->net_stats.rx_bytes += len;
- gp->dev->last_rx = jiffies;
next:
entry = NEXT_RX(entry);
gp->status = readl(gp->regs + GREG_STAT);
} while (gp->status & GREG_STAT_NAPI);
- __netif_rx_complete(dev, napi);
+ __napi_complete(napi);
gem_enable_ints(gp);
spin_unlock_irqrestore(&gp->lock, flags);
static irqreturn_t gem_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
/* Swallow interrupts when shutting the chip down, though
spin_lock_irqsave(&gp->lock, flags);
- if (netif_rx_schedule_prep(dev, &gp->napi)) {
+ if (napi_schedule_prep(&gp->napi)) {
u32 gem_status = readl(gp->regs + GREG_STAT);
if (gem_status == 0) {
}
gp->status = gem_status;
gem_disable_ints(gp);
- __netif_rx_schedule(dev, &gp->napi);
+ __napi_schedule(&gp->napi);
}
spin_unlock_irqrestore(&gp->lock, flags);
static void gem_tx_timeout(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
if (!gp->running) {
return 0;
}
-static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
int entry;
u64 ctrl;
unsigned long flags;
(csum_stuff_off << 21));
}
- local_irq_save(flags);
- if (!spin_trylock(&gp->tx_lock)) {
+ if (!spin_trylock_irqsave(&gp->tx_lock, flags)) {
/* Tell upper layer to requeue */
- local_irq_restore(flags);
return NETDEV_TX_LOCKED;
}
/* We raced with gem_do_stop() */
if (limit-- <= 0)
break;
}
- if (limit <= 0)
+ if (limit < 0)
printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
gp->dev->name);
}
break;
} while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST));
- if (limit <= 0)
+ if (limit < 0)
printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes)
int i;
if ((gp->dev->flags & IFF_ALLMULTI) ||
- (gp->dev->mc_count > 256)) {
+ (netdev_mc_count(gp->dev) > 256)) {
for (i=0; i<16; i++)
writel(0xffff, gp->regs + MAC_HASH0 + (i << 2));
rxcfg |= MAC_RXCFG_HFE;
for (i = 0; i < 16; i++)
hash_table[i] = 0;
- for (i = 0; i < gp->dev->mc_count; i++) {
+ for (i = 0; i < netdev_mc_count(gp->dev); i++) {
char *addrs = dmi->dmi_addr;
dmi = dmi->next;
mif_cfg &= ~MIF_CFG_PSELECT;
writel(mif_cfg, gp->regs + MIF_CFG);
} else {
- gp->phy_type = phy_serialink;
+#ifdef CONFIG_SPARC
+ const char *p;
+
+ p = of_get_property(gp->of_node, "shared-pins", NULL);
+ if (p && !strcmp(p, "serdes"))
+ gp->phy_type = phy_serdes;
+ else
+#endif
+ gp->phy_type = phy_serialink;
}
if (gp->phy_type == phy_mii_mdio1 ||
gp->phy_type == phy_mii_mdio0) {
static int gem_do_start(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&gp->lock, flags);
gp->running = 1;
+ napi_enable(&gp->napi);
+
if (gp->lstate == link_up) {
netif_carrier_on(gp->dev);
gem_set_link_modes(gp);
spin_lock_irqsave(&gp->lock, flags);
spin_lock(&gp->tx_lock);
+ napi_disable(&gp->napi);
+
gp->running = 0;
gem_reset(gp);
gem_clean_rings(gp);
static void gem_do_stop(struct net_device *dev, int wol)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&gp->lock, flags);
static int gem_open(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
int rc = 0;
mutex_lock(&gp->pm_mutex);
if (!gp->asleep)
rc = gem_do_start(dev);
gp->opened = (rc == 0);
- if (gp->opened)
- napi_enable(&gp->napi);
mutex_unlock(&gp->pm_mutex);
static int gem_close(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
mutex_lock(&gp->pm_mutex);
static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
mutex_lock(&gp->pm_mutex);
static int gem_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
printk(KERN_INFO "%s: resuming\n", dev->name);
/* Re-attach net device */
netif_device_attach(dev);
-
- napi_enable(&gp->napi);
}
spin_lock_irqsave(&gp->lock, flags);
static struct net_device_stats *gem_get_stats(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
struct net_device_stats *stats = &gp->net_stats;
spin_lock_irq(&gp->lock);
static int gem_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *macaddr = (struct sockaddr *) addr;
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned char *e = &dev->dev_addr[0];
if (!is_valid_ether_addr(macaddr->sa_data))
static void gem_set_multicast(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
u32 rxcfg, rxcfg_new;
int limit = 10000;
static int gem_change_mtu(struct net_device *dev, int new_mtu)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
return -EINVAL;
static void gem_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1) {
cmd->speed = 0;
cmd->duplex = cmd->port = cmd->phy_address =
cmd->transceiver = cmd->autoneg = 0;
+
+ /* serdes means usually a Fibre connector, with most fixed */
+ if (gp->phy_type == phy_serdes) {
+ cmd->port = PORT_FIBRE;
+ cmd->supported = (SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE | SUPPORTED_Autoneg |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+ cmd->advertising = cmd->supported;
+ cmd->transceiver = XCVR_INTERNAL;
+ if (gp->lstate == link_up)
+ cmd->speed = SPEED_1000;
+ cmd->duplex = DUPLEX_FULL;
+ cmd->autoneg = 1;
+ }
}
cmd->maxtxpkt = cmd->maxrxpkt = 0;
static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
/* Verify the settings we care about. */
if (cmd->autoneg != AUTONEG_ENABLE &&
static int gem_nway_reset(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
if (!gp->want_autoneg)
return -EINVAL;
static u32 gem_get_msglevel(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
return gp->msg_enable;
}
static void gem_set_msglevel(struct net_device *dev, u32 value)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
gp->msg_enable = value;
}
static void gem_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
/* Add more when I understand how to program the chip */
if (gp->has_wol) {
static int gem_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
if (!gp->has_wol)
return -EOPNOTSUPP;
static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(ifr);
int rc = -EOPNOTSUPP;
unsigned long flags;
break;
case SIOCSMIIREG: /* Write MII PHY register. */
- if (!capable(CAP_NET_ADMIN))
- rc = -EPERM;
- else if (!gp->running)
+ if (!gp->running)
rc = -EAGAIN;
else {
__phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
struct net_device *dev = pci_get_drvdata(pdev);
if (dev) {
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unregister_netdev(dev);
}
}
+static const struct net_device_ops gem_netdev_ops = {
+ .ndo_open = gem_open,
+ .ndo_stop = gem_close,
+ .ndo_start_xmit = gem_start_xmit,
+ .ndo_get_stats = gem_get_stats,
+ .ndo_set_multicast_list = gem_set_multicast,
+ .ndo_do_ioctl = gem_ioctl,
+ .ndo_tx_timeout = gem_tx_timeout,
+ .ndo_change_mtu = gem_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = gem_set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = gem_poll_controller,
+#endif
+};
+
static int __devinit gem_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct net_device *dev;
struct gem *gp;
int err, pci_using_dac;
- DECLARE_MAC_BUF(mac);
if (gem_version_printed++ == 0)
printk(KERN_INFO "%s", version);
*/
if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_GEM &&
- !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
pci_using_dac = 1;
} else {
- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, "
"aborting.\n");
}
SET_NETDEV_DEV(dev, &pdev->dev);
- gp = dev->priv;
+ gp = netdev_priv(dev);
err = pci_request_regions(pdev, DRV_NAME);
if (err) {
if (gem_get_device_address(gp))
goto err_out_free_consistent;
- dev->open = gem_open;
- dev->stop = gem_close;
- dev->hard_start_xmit = gem_start_xmit;
- dev->get_stats = gem_get_stats;
- dev->set_multicast_list = gem_set_multicast;
- dev->do_ioctl = gem_ioctl;
+ dev->netdev_ops = &gem_netdev_ops;
netif_napi_add(dev, &gp->napi, gem_poll, 64);
dev->ethtool_ops = &gem_ethtool_ops;
- dev->tx_timeout = gem_tx_timeout;
dev->watchdog_timeo = 5 * HZ;
- dev->change_mtu = gem_change_mtu;
dev->irq = pdev->irq;
dev->dma = 0;
- dev->set_mac_address = gem_set_mac_address;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = gem_poll_controller;
-#endif
/* Set that now, in case PM kicks in now */
pci_set_drvdata(pdev, dev);
goto err_out_free_consistent;
}
- printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet "
- "%s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
+ dev->name, dev->dev_addr);
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1)