diff options
Diffstat (limited to 'drivers/net/ethernet/amd')
22 files changed, 975 insertions, 878 deletions
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index 9595f1bc535b..7b5df562f30f 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -695,125 +695,105 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget) void __iomem *mmio = lp->mmio; struct sk_buff *skb,*new_skb; int min_pkt_len, status; - unsigned int intr0; int num_rx_pkt = 0; short pkt_len; #if AMD8111E_VLAN_TAG_USED short vtag; #endif - int rx_pkt_limit = budget; - unsigned long flags; - if (rx_pkt_limit <= 0) - goto rx_not_empty; + while (num_rx_pkt < budget) { + status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags); + if (status & OWN_BIT) + break; - do{ - /* process receive packets until we use the quota. - * If we own the next entry, it's a new packet. Send it up. + /* There is a tricky error noted by John Murphy, + * <[email protected]> to Russ Nelson: Even with + * full-sized * buffers it's possible for a + * jabber packet to use two buffers, with only + * the last correctly noting the error. */ - while(1) { - status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags); - if (status & OWN_BIT) - break; - - /* There is a tricky error noted by John Murphy, - * <[email protected]> to Russ Nelson: Even with - * full-sized * buffers it's possible for a - * jabber packet to use two buffers, with only - * the last correctly noting the error. - */ - if(status & ERR_BIT) { - /* resetting flags */ - lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; - goto err_next_pkt; - } - /* check for STP and ENP */ - if(!((status & STP_BIT) && (status & ENP_BIT))){ - /* resetting flags */ - lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; - goto err_next_pkt; - } - pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4; + if (status & ERR_BIT) { + /* resetting flags */ + lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; + goto err_next_pkt; + } + /* check for STP and ENP */ + if (!((status & STP_BIT) && (status & ENP_BIT))){ + /* resetting flags */ + lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; + goto err_next_pkt; + } + pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4; #if AMD8111E_VLAN_TAG_USED - vtag = status & TT_MASK; - /*MAC will strip vlan tag*/ - if (vtag != 0) - min_pkt_len =MIN_PKT_LEN - 4; + vtag = status & TT_MASK; + /* MAC will strip vlan tag */ + if (vtag != 0) + min_pkt_len = MIN_PKT_LEN - 4; else #endif - min_pkt_len =MIN_PKT_LEN; + min_pkt_len = MIN_PKT_LEN; - if (pkt_len < min_pkt_len) { - lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; - lp->drv_rx_errors++; - goto err_next_pkt; - } - if(--rx_pkt_limit < 0) - goto rx_not_empty; - new_skb = netdev_alloc_skb(dev, lp->rx_buff_len); - if (!new_skb) { - /* if allocation fail, - * ignore that pkt and go to next one - */ - lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; - lp->drv_rx_errors++; - goto err_next_pkt; - } + if (pkt_len < min_pkt_len) { + lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; + lp->drv_rx_errors++; + goto err_next_pkt; + } + new_skb = netdev_alloc_skb(dev, lp->rx_buff_len); + if (!new_skb) { + /* if allocation fail, + * ignore that pkt and go to next one + */ + lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; + lp->drv_rx_errors++; + goto err_next_pkt; + } - skb_reserve(new_skb, 2); - skb = lp->rx_skbuff[rx_index]; - pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index], - lp->rx_buff_len-2, PCI_DMA_FROMDEVICE); - skb_put(skb, pkt_len); - lp->rx_skbuff[rx_index] = new_skb; - lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev, - new_skb->data, - lp->rx_buff_len-2, - PCI_DMA_FROMDEVICE); + skb_reserve(new_skb, 2); + skb = lp->rx_skbuff[rx_index]; + pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index], + lp->rx_buff_len-2, PCI_DMA_FROMDEVICE); + skb_put(skb, pkt_len); + lp->rx_skbuff[rx_index] = new_skb; + lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev, + new_skb->data, + lp->rx_buff_len-2, + PCI_DMA_FROMDEVICE); - skb->protocol = eth_type_trans(skb, dev); + skb->protocol = eth_type_trans(skb, dev); #if AMD8111E_VLAN_TAG_USED - if (vtag == TT_VLAN_TAGGED){ - u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info); - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); - } -#endif - netif_receive_skb(skb); - /*COAL update rx coalescing parameters*/ - lp->coal_conf.rx_packets++; - lp->coal_conf.rx_bytes += pkt_len; - num_rx_pkt++; - - err_next_pkt: - lp->rx_ring[rx_index].buff_phy_addr - = cpu_to_le32(lp->rx_dma_addr[rx_index]); - lp->rx_ring[rx_index].buff_count = - cpu_to_le16(lp->rx_buff_len-2); - wmb(); - lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT); - rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK; + if (vtag == TT_VLAN_TAGGED){ + u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info); + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); } - /* Check the interrupt status register for more packets in the - * mean time. Process them since we have not used up our quota. - */ - intr0 = readl(mmio + INT0); - /*Ack receive packets */ - writel(intr0 & RINT0,mmio + INT0); +#endif + napi_gro_receive(napi, skb); + /* COAL update rx coalescing parameters */ + lp->coal_conf.rx_packets++; + lp->coal_conf.rx_bytes += pkt_len; + num_rx_pkt++; + +err_next_pkt: + lp->rx_ring[rx_index].buff_phy_addr + = cpu_to_le32(lp->rx_dma_addr[rx_index]); + lp->rx_ring[rx_index].buff_count = + cpu_to_le16(lp->rx_buff_len-2); + wmb(); + lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT); + rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK; + } - } while(intr0 & RINT0); + if (num_rx_pkt < budget && napi_complete_done(napi, num_rx_pkt)) { + unsigned long flags; - if (rx_pkt_limit > 0) { /* Receive descriptor is empty now */ spin_lock_irqsave(&lp->lock, flags); - __napi_complete(napi); writel(VAL0|RINTEN0, mmio + INTEN0); writel(VAL2 | RDMD0, mmio + CMD0); spin_unlock_irqrestore(&lp->lock, flags); } -rx_not_empty: return num_rx_pkt; } diff --git a/drivers/net/ethernet/amd/amd8111e.h b/drivers/net/ethernet/amd/amd8111e.h index 7cdb18512407..2a57b46fd6a6 100644 --- a/drivers/net/ethernet/amd/amd8111e.h +++ b/drivers/net/ethernet/amd/amd8111e.h @@ -48,7 +48,7 @@ eg., if the value 10011010b is written into the least significant byte of a comm /* 32 bit registers */ #define ASF_STAT 0x00 /* ASF status register */ -#define CHIPID 0x04 /* Chip ID regsiter */ +#define CHIPID 0x04 /* Chip ID register */ #define MIB_DATA 0x10 /* MIB data register */ #define MIB_ADDR 0x14 /* MIB address register */ #define STAT0 0x30 /* Status0 register */ @@ -648,7 +648,7 @@ typedef enum { /* driver ioctl parameters */ #define AMD8111E_REG_DUMP_LEN 13*sizeof(u32) -/* amd8111e desriptor format */ +/* amd8111e descriptor format */ struct amd8111e_tx_dr{ diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c index 796c37a5bbde..c5b81268c284 100644 --- a/drivers/net/ethernet/amd/atarilance.c +++ b/drivers/net/ethernet/amd/atarilance.c @@ -42,8 +42,8 @@ */ -static char version[] = "atarilance.c: v1.3 04/04/96 " - "[email protected]\n"; +static const char version[] = "atarilance.c: v1.3 04/04/96 " + "[email protected]\n"; #include <linux/netdevice.h> #include <linux/etherdevice.h> diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c index 76e5fc7adff5..82cc81385033 100644 --- a/drivers/net/ethernet/amd/declance.c +++ b/drivers/net/ethernet/amd/declance.c @@ -72,7 +72,7 @@ #include <asm/dec/machtype.h> #include <asm/dec/system.h> -static char version[] = +static const char version[] = "declance.c: v0.011 by Linux MIPS DECstation task force\n"; MODULE_AUTHOR("Linux MIPS DECstation task force"); @@ -1276,18 +1276,6 @@ err_out: return ret; } -static void __exit dec_lance_remove(struct device *bdev) -{ - struct net_device *dev = dev_get_drvdata(bdev); - resource_size_t start, len; - - unregister_netdev(dev); - start = to_tc_dev(bdev)->resource.start; - len = to_tc_dev(bdev)->resource.end - start + 1; - release_mem_region(start, len); - free_netdev(dev); -} - /* Find all the lance cards on the system and initialize them */ static int __init dec_lance_platform_probe(void) { @@ -1320,7 +1308,7 @@ static void __exit dec_lance_platform_remove(void) #ifdef CONFIG_TC static int dec_lance_tc_probe(struct device *dev); -static int __exit dec_lance_tc_remove(struct device *dev); +static int dec_lance_tc_remove(struct device *dev); static const struct tc_device_id dec_lance_tc_table[] = { { "DEC ", "PMAD-AA " }, @@ -1334,7 +1322,7 @@ static struct tc_driver dec_lance_tc_driver = { .name = "declance", .bus = &tc_bus_type, .probe = dec_lance_tc_probe, - .remove = __exit_p(dec_lance_tc_remove), + .remove = dec_lance_tc_remove, }, }; @@ -1346,7 +1334,19 @@ static int dec_lance_tc_probe(struct device *dev) return status; } -static int __exit dec_lance_tc_remove(struct device *dev) +static void dec_lance_remove(struct device *bdev) +{ + struct net_device *dev = dev_get_drvdata(bdev); + resource_size_t start, len; + + unregister_netdev(dev); + start = to_tc_dev(bdev)->resource.start; + len = to_tc_dev(bdev)->resource.end - start + 1; + release_mem_region(start, len); + free_netdev(dev); +} + +static int dec_lance_tc_remove(struct device *dev) { put_device(dev); dec_lance_remove(dev); diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c index 61a641f23149..12a6a93d221b 100644 --- a/drivers/net/ethernet/amd/lance.c +++ b/drivers/net/ethernet/amd/lance.c @@ -318,9 +318,9 @@ static int io[MAX_CARDS]; static int dma[MAX_CARDS]; static int irq[MAX_CARDS]; -module_param_array(io, int, NULL, 0); -module_param_array(dma, int, NULL, 0); -module_param_array(irq, int, NULL, 0); +module_param_hw_array(io, int, ioport, NULL, 0); +module_param_hw_array(dma, int, dma, NULL, 0); +module_param_hw_array(irq, int, irq, NULL, 0); module_param(lance_debug, int, 0); MODULE_PARM_DESC(io, "LANCE/PCnet I/O base address(es),required"); MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)"); diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c index 5985bf220a8d..e248d1ab3e47 100644 --- a/drivers/net/ethernet/amd/ni65.c +++ b/drivers/net/ethernet/amd/ni65.c @@ -1227,9 +1227,9 @@ static void set_multicast_list(struct net_device *dev) #ifdef MODULE static struct net_device *dev_ni65; -module_param(irq, int, 0); -module_param(io, int, 0); -module_param(dma, int, 0); +module_param_hw(irq, int, irq, 0); +module_param_hw(io, int, ioport, 0); +module_param_hw(dma, int, dma, 0); MODULE_PARM_DESC(irq, "ni6510 IRQ number (ignored for some cards)"); MODULE_PARM_DESC(io, "ni6510 I/O base address"); MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)"); diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c index b556c926557a..9c152d85840d 100644 --- a/drivers/net/ethernet/amd/nmclan_cs.c +++ b/drivers/net/ethernet/amd/nmclan_cs.c @@ -359,7 +359,6 @@ typedef struct _mace_statistics { typedef struct _mace_private { struct pcmcia_device *p_dev; - struct net_device_stats linux_stats; /* Linux statistics counters */ mace_statistics mace_stats; /* MACE chip statistics counters */ /* restore_multicast_list() state variables */ @@ -879,7 +878,7 @@ static netdev_tx_t mace_start_xmit(struct sk_buff *skb, service a transmit interrupt while we are in here. */ - lp->linux_stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; lp->tx_free_frames--; /* WARNING: Write the _exact_ number of bytes written in the header! */ @@ -967,7 +966,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) fifofc = inb(ioaddr + AM2150_MACE_BASE + MACE_FIFOFC); if ((fifofc & MACE_FIFOFC_XMTFC)==0) { - lp->linux_stats.tx_errors++; + dev->stats.tx_errors++; outb(0xFF, ioaddr + AM2150_XMT_SKIP); } @@ -1016,7 +1015,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) } /* if (xmtfs & MACE_XMTFS_XMTSV) */ - lp->linux_stats.tx_packets++; + dev->stats.tx_packets++; lp->tx_free_frames++; netif_wake_queue(dev); } /* if (status & MACE_IR_XMTINT) */ @@ -1077,7 +1076,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt) " 0x%X.\n", dev->name, rx_framecnt, rx_status); if (rx_status & MACE_RCVFS_RCVSTS) { /* Error, update stats. */ - lp->linux_stats.rx_errors++; + dev->stats.rx_errors++; if (rx_status & MACE_RCVFS_OFLO) { lp->mace_stats.oflo++; } @@ -1114,14 +1113,14 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt) netif_rx(skb); /* Send the packet to the upper (protocol) layers. */ - lp->linux_stats.rx_packets++; - lp->linux_stats.rx_bytes += pkt_len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ continue; } else { pr_debug("%s: couldn't allocate a sk_buff of size" " %d.\n", dev->name, pkt_len); - lp->linux_stats.rx_dropped++; + dev->stats.rx_dropped++; } } outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ @@ -1231,13 +1230,13 @@ static void update_stats(unsigned int ioaddr, struct net_device *dev) lp->mace_stats.rntpc += mace_read(lp, ioaddr, MACE_RNTPC); lp->mace_stats.mpc += mace_read(lp, ioaddr, MACE_MPC); /* At this point, mace_stats is fully updated for this call. - We may now update the linux_stats. */ + We may now update the netdev stats. */ - /* The MACE has no equivalent for linux_stats field which are commented + /* The MACE has no equivalent for netdev stats field which are commented out. */ - /* lp->linux_stats.multicast; */ - lp->linux_stats.collisions = + /* dev->stats.multicast; */ + dev->stats.collisions = lp->mace_stats.rcvcco * 256 + lp->mace_stats.rcvcc; /* Collision: The MACE may retry sending a packet 15 times before giving up. The retry count is in XMTRC. @@ -1245,22 +1244,22 @@ static void update_stats(unsigned int ioaddr, struct net_device *dev) If so, why doesn't the RCVCC record these collisions? */ /* detailed rx_errors: */ - lp->linux_stats.rx_length_errors = + dev->stats.rx_length_errors = lp->mace_stats.rntpco * 256 + lp->mace_stats.rntpc; - /* lp->linux_stats.rx_over_errors */ - lp->linux_stats.rx_crc_errors = lp->mace_stats.fcs; - lp->linux_stats.rx_frame_errors = lp->mace_stats.fram; - lp->linux_stats.rx_fifo_errors = lp->mace_stats.oflo; - lp->linux_stats.rx_missed_errors = + /* dev->stats.rx_over_errors */ + dev->stats.rx_crc_errors = lp->mace_stats.fcs; + dev->stats.rx_frame_errors = lp->mace_stats.fram; + dev->stats.rx_fifo_errors = lp->mace_stats.oflo; + dev->stats.rx_missed_errors = lp->mace_stats.mpco * 256 + lp->mace_stats.mpc; /* detailed tx_errors */ - lp->linux_stats.tx_aborted_errors = lp->mace_stats.rtry; - lp->linux_stats.tx_carrier_errors = lp->mace_stats.lcar; + dev->stats.tx_aborted_errors = lp->mace_stats.rtry; + dev->stats.tx_carrier_errors = lp->mace_stats.lcar; /* LCAR usually results from bad cabling. */ - lp->linux_stats.tx_fifo_errors = lp->mace_stats.uflo; - lp->linux_stats.tx_heartbeat_errors = lp->mace_stats.cerr; - /* lp->linux_stats.tx_window_errors; */ + dev->stats.tx_fifo_errors = lp->mace_stats.uflo; + dev->stats.tx_heartbeat_errors = lp->mace_stats.cerr; + /* dev->stats.tx_window_errors; */ } /* update_stats */ /* ---------------------------------------------------------------------------- @@ -1274,10 +1273,10 @@ static struct net_device_stats *mace_get_stats(struct net_device *dev) update_stats(dev->base_addr, dev); pr_debug("%s: updating the statistics.\n", dev->name); - pr_linux_stats(&lp->linux_stats); + pr_linux_stats(&dev->stats); pr_mace_stats(&lp->mace_stats); - return &lp->linux_stats; + return &dev->stats; } /* net_device_stats */ /* ---------------------------------------------------------------------------- diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index 41e58cca8fee..7f60d17819ce 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -291,7 +291,10 @@ struct pcnet32_private { int options; unsigned int shared_irq:1, /* shared irq possible */ dxsuflo:1, /* disable transmit stop on uflo */ - mii:1; /* mii port available */ + mii:1, /* mii port available */ + autoneg:1, /* autoneg enabled */ + port_tp:1, /* port set to TP */ + fdx:1; /* full duplex enabled */ struct net_device *next; struct mii_if_info mii_if; struct timer_list watchdog_timer; @@ -677,34 +680,126 @@ static void pcnet32_poll_controller(struct net_device *dev) } #endif +/* + * lp->lock must be held. + */ +static int pcnet32_suspend(struct net_device *dev, unsigned long *flags, + int can_sleep) +{ + int csr5; + struct pcnet32_private *lp = netdev_priv(dev); + const struct pcnet32_access *a = lp->a; + ulong ioaddr = dev->base_addr; + int ticks; + + /* really old chips have to be stopped. */ + if (lp->chip_version < PCNET32_79C970A) + return 0; + + /* set SUSPEND (SPND) - CSR5 bit 0 */ + csr5 = a->read_csr(ioaddr, CSR5); + a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND); + + /* poll waiting for bit to be set */ + ticks = 0; + while (!(a->read_csr(ioaddr, CSR5) & CSR5_SUSPEND)) { + spin_unlock_irqrestore(&lp->lock, *flags); + if (can_sleep) + msleep(1); + else + mdelay(1); + spin_lock_irqsave(&lp->lock, *flags); + ticks++; + if (ticks > 200) { + netif_printk(lp, hw, KERN_DEBUG, dev, + "Error getting into suspend!\n"); + return 0; + } + } + return 1; +} + +static void pcnet32_clr_suspend(struct pcnet32_private *lp, ulong ioaddr) +{ + int csr5 = lp->a->read_csr(ioaddr, CSR5); + /* clear SUSPEND (SPND) - CSR5 bit 0 */ + lp->a->write_csr(ioaddr, CSR5, csr5 & ~CSR5_SUSPEND); +} + static int pcnet32_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *cmd) { struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; - int r = -EOPNOTSUPP; + spin_lock_irqsave(&lp->lock, flags); if (lp->mii) { - spin_lock_irqsave(&lp->lock, flags); mii_ethtool_get_link_ksettings(&lp->mii_if, cmd); - spin_unlock_irqrestore(&lp->lock, flags); - r = 0; + } else if (lp->chip_version == PCNET32_79C970A) { + if (lp->autoneg) { + cmd->base.autoneg = AUTONEG_ENABLE; + if (lp->a->read_bcr(dev->base_addr, 4) == 0xc0) + cmd->base.port = PORT_AUI; + else + cmd->base.port = PORT_TP; + } else { + cmd->base.autoneg = AUTONEG_DISABLE; + cmd->base.port = lp->port_tp ? PORT_TP : PORT_AUI; + } + cmd->base.duplex = lp->fdx ? DUPLEX_FULL : DUPLEX_HALF; + cmd->base.speed = SPEED_10; + ethtool_convert_legacy_u32_to_link_mode( + cmd->link_modes.supported, + SUPPORTED_TP | SUPPORTED_AUI); } - return r; + spin_unlock_irqrestore(&lp->lock, flags); + return 0; } static int pcnet32_set_link_ksettings(struct net_device *dev, const struct ethtool_link_ksettings *cmd) { struct pcnet32_private *lp = netdev_priv(dev); + ulong ioaddr = dev->base_addr; unsigned long flags; int r = -EOPNOTSUPP; + int suspended, bcr2, bcr9, csr15; + spin_lock_irqsave(&lp->lock, flags); if (lp->mii) { - spin_lock_irqsave(&lp->lock, flags); r = mii_ethtool_set_link_ksettings(&lp->mii_if, cmd); - spin_unlock_irqrestore(&lp->lock, flags); + } else if (lp->chip_version == PCNET32_79C970A) { + suspended = pcnet32_suspend(dev, &flags, 0); + if (!suspended) + lp->a->write_csr(ioaddr, CSR0, CSR0_STOP); + + lp->autoneg = cmd->base.autoneg == AUTONEG_ENABLE; + bcr2 = lp->a->read_bcr(ioaddr, 2); + if (cmd->base.autoneg == AUTONEG_ENABLE) { + lp->a->write_bcr(ioaddr, 2, bcr2 | 0x0002); + } else { + lp->a->write_bcr(ioaddr, 2, bcr2 & ~0x0002); + + lp->port_tp = cmd->base.port == PORT_TP; + csr15 = lp->a->read_csr(ioaddr, CSR15) & ~0x0180; + if (cmd->base.port == PORT_TP) + csr15 |= 0x0080; + lp->a->write_csr(ioaddr, CSR15, csr15); + lp->init_block->mode = cpu_to_le16(csr15); + + lp->fdx = cmd->base.duplex == DUPLEX_FULL; + bcr9 = lp->a->read_bcr(ioaddr, 9) & ~0x0003; + if (cmd->base.duplex == DUPLEX_FULL) + bcr9 |= 0x0003; + lp->a->write_bcr(ioaddr, 9, bcr9); + } + if (suspended) + pcnet32_clr_suspend(lp, ioaddr); + else if (netif_running(dev)) + pcnet32_restart(dev, CSR0_NORMAL); + r = 0; } + spin_unlock_irqrestore(&lp->lock, flags); return r; } @@ -732,7 +827,14 @@ static u32 pcnet32_get_link(struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); if (lp->mii) { r = mii_link_ok(&lp->mii_if); - } else if (lp->chip_version >= PCNET32_79C970A) { + } else if (lp->chip_version == PCNET32_79C970A) { + ulong ioaddr = dev->base_addr; /* card base I/O address */ + /* only read link if port is set to TP */ + if (!lp->autoneg && lp->port_tp) + r = (lp->a->read_bcr(ioaddr, 4) != 0xc0); + else /* link always up for AUI port or port auto select */ + r = 1; + } else if (lp->chip_version > PCNET32_79C970A) { ulong ioaddr = dev->base_addr; /* card base I/O address */ r = (lp->a->read_bcr(ioaddr, 4) != 0xc0); } else { /* can not detect link on really old chips */ @@ -1070,45 +1172,6 @@ static int pcnet32_set_phys_id(struct net_device *dev, } /* - * lp->lock must be held. - */ -static int pcnet32_suspend(struct net_device *dev, unsigned long *flags, - int can_sleep) -{ - int csr5; - struct pcnet32_private *lp = netdev_priv(dev); - const struct pcnet32_access *a = lp->a; - ulong ioaddr = dev->base_addr; - int ticks; - - /* really old chips have to be stopped. */ - if (lp->chip_version < PCNET32_79C970A) - return 0; - - /* set SUSPEND (SPND) - CSR5 bit 0 */ - csr5 = a->read_csr(ioaddr, CSR5); - a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND); - - /* poll waiting for bit to be set */ - ticks = 0; - while (!(a->read_csr(ioaddr, CSR5) & CSR5_SUSPEND)) { - spin_unlock_irqrestore(&lp->lock, *flags); - if (can_sleep) - msleep(1); - else - mdelay(1); - spin_lock_irqsave(&lp->lock, *flags); - ticks++; - if (ticks > 200) { - netif_printk(lp, hw, KERN_DEBUG, dev, - "Error getting into suspend!\n"); - return 0; - } - } - return 1; -} - -/* * process one receive descriptor entry */ @@ -1350,13 +1413,8 @@ static int pcnet32_poll(struct napi_struct *napi, int budget) pcnet32_restart(dev, CSR0_START); netif_wake_queue(dev); } - spin_unlock_irqrestore(&lp->lock, flags); - - if (work_done < budget) { - spin_lock_irqsave(&lp->lock, flags); - - __napi_complete(napi); + if (work_done < budget && napi_complete_done(napi, work_done)) { /* clear interrupt masks */ val = lp->a->read_csr(ioaddr, CSR3); val &= 0x00ff; @@ -1364,9 +1422,9 @@ static int pcnet32_poll(struct napi_struct *napi, int budget) /* Set interrupt enable. */ lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN); - - spin_unlock_irqrestore(&lp->lock, flags); } + + spin_unlock_irqrestore(&lp->lock, flags); return work_done; } @@ -1430,13 +1488,8 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, } } - if (!(csr0 & CSR0_STOP)) { /* If not stopped */ - int csr5; - - /* clear SUSPEND (SPND) - CSR5 bit 0 */ - csr5 = a->read_csr(ioaddr, CSR5); - a->write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND)); - } + if (!(csr0 & CSR0_STOP)) /* If not stopped */ + pcnet32_clr_suspend(lp, ioaddr); spin_unlock_irqrestore(&lp->lock, flags); } @@ -1817,6 +1870,9 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) lp->options = PCNET32_PORT_ASEL; else lp->options = options_mapping[options[cards_found]]; + /* force default port to TP on 79C970A so link detection can work */ + if (lp->chip_version == PCNET32_79C970A) + lp->options = PCNET32_PORT_10BT; lp->mii_if.dev = dev; lp->mii_if.mdio_read = mdio_read; lp->mii_if.mdio_write = mdio_write; @@ -2068,6 +2124,10 @@ static int pcnet32_open(struct net_device *dev) (u32) (lp->rx_ring_dma_addr), (u32) (lp->init_dma_addr)); + lp->autoneg = !!(lp->options & PCNET32_PORT_ASEL); + lp->port_tp = !!(lp->options & PCNET32_PORT_10BT); + lp->fdx = !!(lp->options & PCNET32_PORT_FD); + /* set/reset autoselect bit */ val = lp->a->read_bcr(ioaddr, 2) & ~2; if (lp->options & PCNET32_PORT_ASEL) @@ -2680,10 +2740,7 @@ static void pcnet32_set_multicast_list(struct net_device *dev) } if (suspended) { - int csr5; - /* clear SUSPEND (SPND) - CSR5 bit 0 */ - csr5 = lp->a->read_csr(ioaddr, CSR5); - lp->a->write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND)); + pcnet32_clr_suspend(lp, ioaddr); } else { lp->a->write_csr(ioaddr, CSR0, CSR0_STOP); pcnet32_restart(dev, CSR0_NORMAL); @@ -2794,6 +2851,13 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) if (lp->mii) { curr_link = mii_link_ok(&lp->mii_if); + } else if (lp->chip_version == PCNET32_79C970A) { + ulong ioaddr = dev->base_addr; /* card base I/O address */ + /* only read link if port is set to TP */ + if (!lp->autoneg && lp->port_tp) + curr_link = (lp->a->read_bcr(ioaddr, 4) != 0xc0); + else /* link always up for AUI port or port auto select */ + curr_link = 1; } else { ulong ioaddr = dev->base_addr; /* card base I/O address */ curr_link = (lp->a->read_bcr(ioaddr, 4) != 0xc0); diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c index 12bb4f1489fc..77b1db267730 100644 --- a/drivers/net/ethernet/amd/sun3lance.c +++ b/drivers/net/ethernet/amd/sun3lance.c @@ -21,7 +21,8 @@ */ -static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey ([email protected])\n"; +static const char version[] = +"sun3lance.c: v1.2 1/12/2001 Sam Creasey ([email protected])\n"; #include <linux/module.h> #include <linux/stddef.h> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 8a280e7d66bd..9795419aac2d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -123,38 +123,13 @@ #define DMA_ISR 0x3008 #define DMA_AXIARCR 0x3010 #define DMA_AXIAWCR 0x3018 +#define DMA_AXIAWARCR 0x301c #define DMA_DSR0 0x3020 #define DMA_DSR1 0x3024 +#define DMA_TXEDMACR 0x3040 +#define DMA_RXEDMACR 0x3044 /* DMA register entry bit positions and sizes */ -#define DMA_AXIARCR_DRC_INDEX 0 -#define DMA_AXIARCR_DRC_WIDTH 4 -#define DMA_AXIARCR_DRD_INDEX 4 -#define DMA_AXIARCR_DRD_WIDTH 2 -#define DMA_AXIARCR_TEC_INDEX 8 -#define DMA_AXIARCR_TEC_WIDTH 4 -#define DMA_AXIARCR_TED_INDEX 12 -#define DMA_AXIARCR_TED_WIDTH 2 -#define DMA_AXIARCR_THC_INDEX 16 -#define DMA_AXIARCR_THC_WIDTH 4 -#define DMA_AXIARCR_THD_INDEX 20 -#define DMA_AXIARCR_THD_WIDTH 2 -#define DMA_AXIAWCR_DWC_INDEX 0 -#define DMA_AXIAWCR_DWC_WIDTH 4 -#define DMA_AXIAWCR_DWD_INDEX 4 -#define DMA_AXIAWCR_DWD_WIDTH 2 -#define DMA_AXIAWCR_RPC_INDEX 8 -#define DMA_AXIAWCR_RPC_WIDTH 4 -#define DMA_AXIAWCR_RPD_INDEX 12 -#define DMA_AXIAWCR_RPD_WIDTH 2 -#define DMA_AXIAWCR_RHC_INDEX 16 -#define DMA_AXIAWCR_RHC_WIDTH 4 -#define DMA_AXIAWCR_RHD_INDEX 20 -#define DMA_AXIAWCR_RHD_WIDTH 2 -#define DMA_AXIAWCR_TDC_INDEX 24 -#define DMA_AXIAWCR_TDC_WIDTH 4 -#define DMA_AXIAWCR_TDD_INDEX 28 -#define DMA_AXIAWCR_TDD_WIDTH 2 #define DMA_ISR_MACIS_INDEX 17 #define DMA_ISR_MACIS_WIDTH 1 #define DMA_ISR_MTLIS_INDEX 16 @@ -163,14 +138,31 @@ #define DMA_MR_INTM_WIDTH 2 #define DMA_MR_SWR_INDEX 0 #define DMA_MR_SWR_WIDTH 1 +#define DMA_RXEDMACR_RDPS_INDEX 0 +#define DMA_RXEDMACR_RDPS_WIDTH 3 +#define DMA_SBMR_AAL_INDEX 12 +#define DMA_SBMR_AAL_WIDTH 1 #define DMA_SBMR_EAME_INDEX 11 #define DMA_SBMR_EAME_WIDTH 1 -#define DMA_SBMR_BLEN_256_INDEX 7 -#define DMA_SBMR_BLEN_256_WIDTH 1 +#define DMA_SBMR_BLEN_INDEX 1 +#define DMA_SBMR_BLEN_WIDTH 7 +#define DMA_SBMR_RD_OSR_LMT_INDEX 16 +#define DMA_SBMR_RD_OSR_LMT_WIDTH 6 #define DMA_SBMR_UNDEF_INDEX 0 #define DMA_SBMR_UNDEF_WIDTH 1 +#define DMA_SBMR_WR_OSR_LMT_INDEX 24 +#define DMA_SBMR_WR_OSR_LMT_WIDTH 6 +#define DMA_TXEDMACR_TDPS_INDEX 0 +#define DMA_TXEDMACR_TDPS_WIDTH 3 /* DMA register values */ +#define DMA_SBMR_BLEN_256 256 +#define DMA_SBMR_BLEN_128 128 +#define DMA_SBMR_BLEN_64 64 +#define DMA_SBMR_BLEN_32 32 +#define DMA_SBMR_BLEN_16 16 +#define DMA_SBMR_BLEN_8 8 +#define DMA_SBMR_BLEN_4 4 #define DMA_DSR_RPS_WIDTH 4 #define DMA_DSR_TPS_WIDTH 4 #define DMA_DSR_Q_WIDTH (DMA_DSR_RPS_WIDTH + DMA_DSR_TPS_WIDTH) @@ -959,6 +951,7 @@ #define XP_DRIVER_INT_RO 0x0064 #define XP_DRIVER_SCRATCH_0 0x0068 #define XP_DRIVER_SCRATCH_1 0x006c +#define XP_INT_REISSUE_EN 0x0074 #define XP_INT_EN 0x0078 #define XP_I2C_MUTEX 0x0080 #define XP_MDIO_MUTEX 0x0084 @@ -984,29 +977,29 @@ #define XP_ECC_CNT1_DESC_DED_WIDTH 8 #define XP_ECC_CNT1_DESC_SEC_INDEX 0 #define XP_ECC_CNT1_DESC_SEC_WIDTH 8 -#define XP_ECC_IER_DESC_DED_INDEX 0 +#define XP_ECC_IER_DESC_DED_INDEX 5 #define XP_ECC_IER_DESC_DED_WIDTH 1 -#define XP_ECC_IER_DESC_SEC_INDEX 1 +#define XP_ECC_IER_DESC_SEC_INDEX 4 #define XP_ECC_IER_DESC_SEC_WIDTH 1 -#define XP_ECC_IER_RX_DED_INDEX 2 +#define XP_ECC_IER_RX_DED_INDEX 3 #define XP_ECC_IER_RX_DED_WIDTH 1 -#define XP_ECC_IER_RX_SEC_INDEX 3 +#define XP_ECC_IER_RX_SEC_INDEX 2 #define XP_ECC_IER_RX_SEC_WIDTH 1 -#define XP_ECC_IER_TX_DED_INDEX 4 +#define XP_ECC_IER_TX_DED_INDEX 1 #define XP_ECC_IER_TX_DED_WIDTH 1 -#define XP_ECC_IER_TX_SEC_INDEX 5 +#define XP_ECC_IER_TX_SEC_INDEX 0 #define XP_ECC_IER_TX_SEC_WIDTH 1 -#define XP_ECC_ISR_DESC_DED_INDEX 0 +#define XP_ECC_ISR_DESC_DED_INDEX 5 #define XP_ECC_ISR_DESC_DED_WIDTH 1 -#define XP_ECC_ISR_DESC_SEC_INDEX 1 +#define XP_ECC_ISR_DESC_SEC_INDEX 4 #define XP_ECC_ISR_DESC_SEC_WIDTH 1 -#define XP_ECC_ISR_RX_DED_INDEX 2 +#define XP_ECC_ISR_RX_DED_INDEX 3 #define XP_ECC_ISR_RX_DED_WIDTH 1 -#define XP_ECC_ISR_RX_SEC_INDEX 3 +#define XP_ECC_ISR_RX_SEC_INDEX 2 #define XP_ECC_ISR_RX_SEC_WIDTH 1 -#define XP_ECC_ISR_TX_DED_INDEX 4 +#define XP_ECC_ISR_TX_DED_INDEX 1 #define XP_ECC_ISR_TX_DED_WIDTH 1 -#define XP_ECC_ISR_TX_SEC_INDEX 5 +#define XP_ECC_ISR_TX_SEC_INDEX 0 #define XP_ECC_ISR_TX_SEC_WIDTH 1 #define XP_I2C_MUTEX_BUSY_INDEX 31 #define XP_I2C_MUTEX_BUSY_WIDTH 1 @@ -1148,8 +1141,8 @@ #define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH 1 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 1 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1 -#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX 2 -#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH 1 +#define RX_PACKET_ATTRIBUTES_LAST_INDEX 2 +#define RX_PACKET_ATTRIBUTES_LAST_WIDTH 1 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1 #define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4 @@ -1158,6 +1151,8 @@ #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1 #define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6 #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1 +#define RX_PACKET_ATTRIBUTES_FIRST_INDEX 7 +#define RX_PACKET_ATTRIBUTES_FIRST_WIDTH 1 #define RX_NORMAL_DESC0_OVT_INDEX 0 #define RX_NORMAL_DESC0_OVT_WIDTH 16 diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c index b3bc87fe3764..45d92304068e 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c @@ -176,8 +176,8 @@ static void xgbe_free_ring_resources(struct xgbe_prv_data *pdata) DBGPR("-->xgbe_free_ring_resources\n"); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; xgbe_free_ring(pdata, channel->tx_ring); xgbe_free_ring(pdata, channel->rx_ring); } @@ -185,34 +185,60 @@ static void xgbe_free_ring_resources(struct xgbe_prv_data *pdata) DBGPR("<--xgbe_free_ring_resources\n"); } +static void *xgbe_alloc_node(size_t size, int node) +{ + void *mem; + + mem = kzalloc_node(size, GFP_KERNEL, node); + if (!mem) + mem = kzalloc(size, GFP_KERNEL); + + return mem; +} + +static void *xgbe_dma_alloc_node(struct device *dev, size_t size, + dma_addr_t *dma, int node) +{ + void *mem; + int cur_node = dev_to_node(dev); + + set_dev_node(dev, node); + mem = dma_alloc_coherent(dev, size, dma, GFP_KERNEL); + set_dev_node(dev, cur_node); + + if (!mem) + mem = dma_alloc_coherent(dev, size, dma, GFP_KERNEL); + + return mem; +} + static int xgbe_init_ring(struct xgbe_prv_data *pdata, struct xgbe_ring *ring, unsigned int rdesc_count) { - DBGPR("-->xgbe_init_ring\n"); + size_t size; if (!ring) return 0; /* Descriptors */ + size = rdesc_count * sizeof(struct xgbe_ring_desc); + ring->rdesc_count = rdesc_count; - ring->rdesc = dma_alloc_coherent(pdata->dev, - (sizeof(struct xgbe_ring_desc) * - rdesc_count), &ring->rdesc_dma, - GFP_KERNEL); + ring->rdesc = xgbe_dma_alloc_node(pdata->dev, size, &ring->rdesc_dma, + ring->node); if (!ring->rdesc) return -ENOMEM; /* Descriptor information */ - ring->rdata = kcalloc(rdesc_count, sizeof(struct xgbe_ring_data), - GFP_KERNEL); + size = rdesc_count * sizeof(struct xgbe_ring_data); + + ring->rdata = xgbe_alloc_node(size, ring->node); if (!ring->rdata) return -ENOMEM; netif_dbg(pdata, drv, pdata->netdev, - "rdesc=%p, rdesc_dma=%pad, rdata=%p\n", - ring->rdesc, &ring->rdesc_dma, ring->rdata); - - DBGPR("<--xgbe_init_ring\n"); + "rdesc=%p, rdesc_dma=%pad, rdata=%p, node=%d\n", + ring->rdesc, &ring->rdesc_dma, ring->rdata, ring->node); return 0; } @@ -223,10 +249,8 @@ static int xgbe_alloc_ring_resources(struct xgbe_prv_data *pdata) unsigned int i; int ret; - DBGPR("-->xgbe_alloc_ring_resources\n"); - - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; netif_dbg(pdata, drv, pdata->netdev, "%s - Tx ring:\n", channel->name); @@ -250,8 +274,6 @@ static int xgbe_alloc_ring_resources(struct xgbe_prv_data *pdata) } } - DBGPR("<--xgbe_alloc_ring_resources\n"); - return 0; err_ring: @@ -261,21 +283,33 @@ err_ring: } static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, - struct xgbe_page_alloc *pa, gfp_t gfp, int order) + struct xgbe_page_alloc *pa, int alloc_order, + int node) { struct page *pages = NULL; dma_addr_t pages_dma; - int ret; + gfp_t gfp; + int order, ret; + +again: + order = alloc_order; /* Try to obtain pages, decreasing order if necessary */ - gfp |= __GFP_COLD | __GFP_COMP | __GFP_NOWARN; + gfp = GFP_ATOMIC | __GFP_COLD | __GFP_COMP | __GFP_NOWARN; while (order >= 0) { - pages = alloc_pages(gfp, order); + pages = alloc_pages_node(node, gfp, order); if (pages) break; order--; } + + /* If we couldn't get local pages, try getting from anywhere */ + if (!pages && (node != NUMA_NO_NODE)) { + node = NUMA_NO_NODE; + goto again; + } + if (!pages) return -ENOMEM; @@ -324,18 +358,17 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata, struct xgbe_ring *ring, struct xgbe_ring_data *rdata) { - int order, ret; + int ret; if (!ring->rx_hdr_pa.pages) { - ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0); + ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, 0, ring->node); if (ret) return ret; } if (!ring->rx_buf_pa.pages) { - order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0); - ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC, - order); + ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, + PAGE_ALLOC_COSTLY_ORDER, ring->node); if (ret) return ret; } @@ -363,8 +396,8 @@ static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata) DBGPR("-->xgbe_wrapper_tx_descriptor_init\n"); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; ring = channel->tx_ring; if (!ring) break; @@ -404,8 +437,8 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) DBGPR("-->xgbe_wrapper_rx_descriptor_init\n"); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; ring = channel->rx_ring; if (!ring) break; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index a7d16db5c4b2..06f953e1e9b2 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -174,58 +174,30 @@ static unsigned int xgbe_riwt_to_usec(struct xgbe_prv_data *pdata, return ret; } -static int xgbe_config_pblx8(struct xgbe_prv_data *pdata) +static int xgbe_config_pbl_val(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; - unsigned int i; - - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_CR, PBLX8, - pdata->pblx8); - - return 0; -} - -static int xgbe_get_tx_pbl_val(struct xgbe_prv_data *pdata) -{ - return XGMAC_DMA_IOREAD_BITS(pdata->channel, DMA_CH_TCR, PBL); -} - -static int xgbe_config_tx_pbl_val(struct xgbe_prv_data *pdata) -{ - struct xgbe_channel *channel; + unsigned int pblx8, pbl; unsigned int i; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; + pblx8 = DMA_PBL_X8_DISABLE; + pbl = pdata->pbl; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, PBL, - pdata->tx_pbl); + if (pdata->pbl > 32) { + pblx8 = DMA_PBL_X8_ENABLE; + pbl >>= 3; } - return 0; -} + for (i = 0; i < pdata->channel_count; i++) { + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_CR, PBLX8, + pblx8); -static int xgbe_get_rx_pbl_val(struct xgbe_prv_data *pdata) -{ - return XGMAC_DMA_IOREAD_BITS(pdata->channel, DMA_CH_RCR, PBL); -} - -static int xgbe_config_rx_pbl_val(struct xgbe_prv_data *pdata) -{ - struct xgbe_channel *channel; - unsigned int i; - - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) - break; + if (pdata->channel[i]->tx_ring) + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, + PBL, pbl); - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, PBL, - pdata->rx_pbl); + if (pdata->channel[i]->rx_ring) + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, + PBL, pbl); } return 0; @@ -233,15 +205,13 @@ static int xgbe_config_rx_pbl_val(struct xgbe_prv_data *pdata) static int xgbe_config_osp_mode(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->tx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, OSP, + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, OSP, pdata->tx_osp_mode); } @@ -292,15 +262,13 @@ static int xgbe_config_tx_threshold(struct xgbe_prv_data *pdata, static int xgbe_config_rx_coalesce(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->rx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RIWT, RWT, + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RIWT, RWT, pdata->rx_riwt); } @@ -314,44 +282,38 @@ static int xgbe_config_tx_coalesce(struct xgbe_prv_data *pdata) static void xgbe_config_rx_buffer_size(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->rx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, RBSZ, + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, RBSZ, pdata->rx_buf_size); } } static void xgbe_config_tso_mode(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->tx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, TSE, 1); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, TSE, 1); } } static void xgbe_config_sph_mode(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->rx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_CR, SPH, 1); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_CR, SPH, 1); } XGMAC_IOWRITE_BITS(pdata, MAC_RCR, HDSMS, XGBE_SPH_HDSMS_SIZE); @@ -651,8 +613,9 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) XGMAC_IOWRITE_BITS(pdata, DMA_MR, INTM, pdata->channel_irq_mode); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; + /* Clear all the interrupts which are set */ dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr); @@ -1323,7 +1286,7 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr, static int xgbe_set_ext_mii_mode(struct xgbe_prv_data *pdata, unsigned int port, enum xgbe_mdio_mode mode) { - unsigned int reg_val = 0; + unsigned int reg_val = XGMAC_IOREAD(pdata, MAC_MDIOCL22R); switch (mode) { case XGBE_MDIO_MODE_CL22: @@ -1497,26 +1460,37 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel) static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata, unsigned int addend) { + unsigned int count = 10000; + /* Set the addend register value and tell the device */ XGMAC_IOWRITE(pdata, MAC_TSAR, addend); XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1); /* Wait for addend update to complete */ - while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG)) + while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG)) udelay(5); + + if (!count) + netdev_err(pdata->netdev, + "timed out updating timestamp addend register\n"); } static void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec, unsigned int nsec) { + unsigned int count = 10000; + /* Set the time values and tell the device */ XGMAC_IOWRITE(pdata, MAC_STSUR, sec); XGMAC_IOWRITE(pdata, MAC_STNUR, nsec); XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1); /* Wait for time update to complete */ - while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT)) + while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT)) udelay(5); + + if (!count) + netdev_err(pdata->netdev, "timed out initializing timestamp\n"); } static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata) @@ -1896,10 +1870,15 @@ static int xgbe_dev_read(struct xgbe_channel *channel) /* Get the header length */ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + FIRST, 1); rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, RX_NORMAL_DESC2, HL); if (rdata->rx.hdr_len) pdata->ext_stats.rx_split_header_packets++; + } else { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + FIRST, 0); } /* Get the RSS hash */ @@ -1922,19 +1901,16 @@ static int xgbe_dev_read(struct xgbe_channel *channel) } } - /* Get the packet length */ - rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); - - if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) { - /* Not all the data has been transferred for this packet */ - XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - INCOMPLETE, 1); + /* Not all the data has been transferred for this packet */ + if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) return 0; - } /* This is the last of the data for this packet */ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - INCOMPLETE, 0); + LAST, 1); + + /* Get the packet length */ + rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); /* Set checksum done indicator as appropriate */ if (netdev->features & NETIF_F_RXCSUM) @@ -2138,37 +2114,38 @@ static int xgbe_flush_tx_queues(struct xgbe_prv_data *pdata) static void xgbe_config_dma_bus(struct xgbe_prv_data *pdata) { + unsigned int sbmr; + + sbmr = XGMAC_IOREAD(pdata, DMA_SBMR); + /* Set enhanced addressing mode */ - XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, EAME, 1); + XGMAC_SET_BITS(sbmr, DMA_SBMR, EAME, 1); /* Set the System Bus mode */ - XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1); - XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN_256, 1); + XGMAC_SET_BITS(sbmr, DMA_SBMR, UNDEF, 1); + XGMAC_SET_BITS(sbmr, DMA_SBMR, BLEN, pdata->blen >> 2); + XGMAC_SET_BITS(sbmr, DMA_SBMR, AAL, pdata->aal); + XGMAC_SET_BITS(sbmr, DMA_SBMR, RD_OSR_LMT, pdata->rd_osr_limit - 1); + XGMAC_SET_BITS(sbmr, DMA_SBMR, WR_OSR_LMT, pdata->wr_osr_limit - 1); + + XGMAC_IOWRITE(pdata, DMA_SBMR, sbmr); + + /* Set descriptor fetching threshold */ + if (pdata->vdata->tx_desc_prefetch) + XGMAC_IOWRITE_BITS(pdata, DMA_TXEDMACR, TDPS, + pdata->vdata->tx_desc_prefetch); + + if (pdata->vdata->rx_desc_prefetch) + XGMAC_IOWRITE_BITS(pdata, DMA_RXEDMACR, RDPS, + pdata->vdata->rx_desc_prefetch); } static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata) { - unsigned int arcache, awcache; - - arcache = 0; - XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, pdata->arcache); - XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRD, pdata->axdomain); - XGMAC_SET_BITS(arcache, DMA_AXIARCR, TEC, pdata->arcache); - XGMAC_SET_BITS(arcache, DMA_AXIARCR, TED, pdata->axdomain); - XGMAC_SET_BITS(arcache, DMA_AXIARCR, THC, pdata->arcache); - XGMAC_SET_BITS(arcache, DMA_AXIARCR, THD, pdata->axdomain); - XGMAC_IOWRITE(pdata, DMA_AXIARCR, arcache); - - awcache = 0; - XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, pdata->awcache); - XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWD, pdata->axdomain); - XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, pdata->awcache); - XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, pdata->axdomain); - XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, pdata->awcache); - XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, pdata->axdomain); - XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDC, pdata->awcache); - XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDD, pdata->axdomain); - XGMAC_IOWRITE(pdata, DMA_AXIAWCR, awcache); + XGMAC_IOWRITE(pdata, DMA_AXIARCR, pdata->arcr); + XGMAC_IOWRITE(pdata, DMA_AXIAWCR, pdata->awcr); + if (pdata->awarcr) + XGMAC_IOWRITE(pdata, DMA_AXIAWARCR, pdata->awarcr); } static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata) @@ -3200,16 +3177,14 @@ static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata, static void xgbe_enable_tx(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; /* Enable each Tx DMA channel */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->tx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 1); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ST, 1); } /* Enable each Tx queue */ @@ -3223,7 +3198,6 @@ static void xgbe_enable_tx(struct xgbe_prv_data *pdata) static void xgbe_disable_tx(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; /* Prepare for Tx DMA channel stop */ @@ -3238,12 +3212,11 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata) XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN, 0); /* Disable each Tx DMA channel */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->tx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 0); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ST, 0); } } @@ -3275,16 +3248,14 @@ static void xgbe_prepare_rx_stop(struct xgbe_prv_data *pdata, static void xgbe_enable_rx(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int reg_val, i; /* Enable each Rx DMA channel */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->rx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 1); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, SR, 1); } /* Enable each Rx queue */ @@ -3302,7 +3273,6 @@ static void xgbe_enable_rx(struct xgbe_prv_data *pdata) static void xgbe_disable_rx(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; /* Disable MAC Rx */ @@ -3319,27 +3289,24 @@ static void xgbe_disable_rx(struct xgbe_prv_data *pdata) XGMAC_IOWRITE(pdata, MAC_RQC0R, 0); /* Disable each Rx DMA channel */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->rx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 0); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, SR, 0); } } static void xgbe_powerup_tx(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; /* Enable each Tx DMA channel */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->tx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 1); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ST, 1); } /* Enable MAC Tx */ @@ -3348,7 +3315,6 @@ static void xgbe_powerup_tx(struct xgbe_prv_data *pdata) static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; /* Prepare for Tx DMA channel stop */ @@ -3359,42 +3325,37 @@ static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata) XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0); /* Disable each Tx DMA channel */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->tx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 0); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ST, 0); } } static void xgbe_powerup_rx(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; /* Enable each Rx DMA channel */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->rx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 1); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, SR, 1); } } static void xgbe_powerdown_rx(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; /* Disable each Rx DMA channel */ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) + for (i = 0; i < pdata->channel_count; i++) { + if (!pdata->channel[i]->rx_ring) break; - XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 0); + XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, SR, 0); } } @@ -3418,9 +3379,7 @@ static int xgbe_init(struct xgbe_prv_data *pdata) xgbe_config_dma_bus(pdata); xgbe_config_dma_cache(pdata); xgbe_config_osp_mode(pdata); - xgbe_config_pblx8(pdata); - xgbe_config_tx_pbl_val(pdata); - xgbe_config_rx_pbl_val(pdata); + xgbe_config_pbl_val(pdata); xgbe_config_rx_coalesce(pdata); xgbe_config_tx_coalesce(pdata); xgbe_config_rx_buffer_size(pdata); @@ -3548,13 +3507,6 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) /* For TX DMA Operating on Second Frame config */ hw_if->config_osp_mode = xgbe_config_osp_mode; - /* For RX and TX PBL config */ - hw_if->config_rx_pbl_val = xgbe_config_rx_pbl_val; - hw_if->get_rx_pbl_val = xgbe_get_rx_pbl_val; - hw_if->config_tx_pbl_val = xgbe_config_tx_pbl_val; - hw_if->get_tx_pbl_val = xgbe_get_tx_pbl_val; - hw_if->config_pblx8 = xgbe_config_pblx8; - /* For MMC statistics support */ hw_if->tx_mmc_int = xgbe_tx_mmc_int; hw_if->rx_mmc_int = xgbe_rx_mmc_int; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 1c87cc204075..ecef3ee87b17 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -118,6 +118,7 @@ #include <linux/spinlock.h> #include <linux/tcp.h> #include <linux/if_vlan.h> +#include <linux/interrupt.h> #include <net/busy_poll.h> #include <linux/clk.h> #include <linux/if_ether.h> @@ -157,81 +158,106 @@ static int xgbe_one_poll(struct napi_struct *, int); static int xgbe_all_poll(struct napi_struct *, int); static void xgbe_stop(struct xgbe_prv_data *); +static void *xgbe_alloc_node(size_t size, int node) +{ + void *mem; + + mem = kzalloc_node(size, GFP_KERNEL, node); + if (!mem) + mem = kzalloc(size, GFP_KERNEL); + + return mem; +} + +static void xgbe_free_channels(struct xgbe_prv_data *pdata) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pdata->channel); i++) { + if (!pdata->channel[i]) + continue; + + kfree(pdata->channel[i]->rx_ring); + kfree(pdata->channel[i]->tx_ring); + kfree(pdata->channel[i]); + + pdata->channel[i] = NULL; + } + + pdata->channel_count = 0; +} + static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel_mem, *channel; - struct xgbe_ring *tx_ring, *rx_ring; + struct xgbe_channel *channel; + struct xgbe_ring *ring; unsigned int count, i; - int ret = -ENOMEM; + unsigned int cpu; + int node; count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); + for (i = 0; i < count; i++) { + /* Attempt to use a CPU on the node the device is on */ + cpu = cpumask_local_spread(i, dev_to_node(pdata->dev)); - channel_mem = kcalloc(count, sizeof(struct xgbe_channel), GFP_KERNEL); - if (!channel_mem) - goto err_channel; - - tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct xgbe_ring), - GFP_KERNEL); - if (!tx_ring) - goto err_tx_ring; + /* Set the allocation node based on the returned CPU */ + node = cpu_to_node(cpu); - rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct xgbe_ring), - GFP_KERNEL); - if (!rx_ring) - goto err_rx_ring; + channel = xgbe_alloc_node(sizeof(*channel), node); + if (!channel) + goto err_mem; + pdata->channel[i] = channel; - for (i = 0, channel = channel_mem; i < count; i++, channel++) { snprintf(channel->name, sizeof(channel->name), "channel-%u", i); channel->pdata = pdata; channel->queue_index = i; channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + (DMA_CH_INC * i); + channel->node = node; + cpumask_set_cpu(cpu, &channel->affinity_mask); if (pdata->per_channel_irq) channel->dma_irq = pdata->channel_irq[i]; if (i < pdata->tx_ring_count) { - spin_lock_init(&tx_ring->lock); - channel->tx_ring = tx_ring++; + ring = xgbe_alloc_node(sizeof(*ring), node); + if (!ring) + goto err_mem; + + spin_lock_init(&ring->lock); + ring->node = node; + + channel->tx_ring = ring; } if (i < pdata->rx_ring_count) { - spin_lock_init(&rx_ring->lock); - channel->rx_ring = rx_ring++; + ring = xgbe_alloc_node(sizeof(*ring), node); + if (!ring) + goto err_mem; + + spin_lock_init(&ring->lock); + ring->node = node; + + channel->rx_ring = ring; } netif_dbg(pdata, drv, pdata->netdev, + "%s: cpu=%u, node=%d\n", channel->name, cpu, node); + + netif_dbg(pdata, drv, pdata->netdev, "%s: dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n", channel->name, channel->dma_regs, channel->dma_irq, channel->tx_ring, channel->rx_ring); } - pdata->channel = channel_mem; pdata->channel_count = count; return 0; -err_rx_ring: - kfree(tx_ring); - -err_tx_ring: - kfree(channel_mem); - -err_channel: - return ret; -} - -static void xgbe_free_channels(struct xgbe_prv_data *pdata) -{ - if (!pdata->channel) - return; - - kfree(pdata->channel->rx_ring); - kfree(pdata->channel->tx_ring); - kfree(pdata->channel); +err_mem: + xgbe_free_channels(pdata); - pdata->channel = NULL; - pdata->channel_count = 0; + return -ENOMEM; } static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring) @@ -300,12 +326,10 @@ static void xgbe_enable_rx_tx_int(struct xgbe_prv_data *pdata, static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) - xgbe_enable_rx_tx_int(pdata, channel); + for (i = 0; i < pdata->channel_count; i++) + xgbe_enable_rx_tx_int(pdata, pdata->channel[i]); } static void xgbe_disable_rx_tx_int(struct xgbe_prv_data *pdata, @@ -328,12 +352,10 @@ static void xgbe_disable_rx_tx_int(struct xgbe_prv_data *pdata, static void xgbe_disable_rx_tx_ints(struct xgbe_prv_data *pdata) { - struct xgbe_channel *channel; unsigned int i; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) - xgbe_disable_rx_tx_int(pdata, channel); + for (i = 0; i < pdata->channel_count; i++) + xgbe_disable_rx_tx_int(pdata, pdata->channel[i]); } static bool xgbe_ecc_sec(struct xgbe_prv_data *pdata, unsigned long *period, @@ -381,9 +403,9 @@ static bool xgbe_ecc_ded(struct xgbe_prv_data *pdata, unsigned long *period, return false; } -static irqreturn_t xgbe_ecc_isr(int irq, void *data) +static void xgbe_ecc_isr_task(unsigned long data) { - struct xgbe_prv_data *pdata = data; + struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; unsigned int ecc_isr; bool stop = false; @@ -434,12 +456,26 @@ out: /* Clear all ECC interrupts */ XP_IOWRITE(pdata, XP_ECC_ISR, ecc_isr); - return IRQ_HANDLED; + /* Reissue interrupt if status is not clear */ + if (pdata->vdata->irq_reissue_support) + XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 1); } -static irqreturn_t xgbe_isr(int irq, void *data) +static irqreturn_t xgbe_ecc_isr(int irq, void *data) { struct xgbe_prv_data *pdata = data; + + if (pdata->isr_as_tasklet) + tasklet_schedule(&pdata->tasklet_ecc); + else + xgbe_ecc_isr_task((unsigned long)pdata); + + return IRQ_HANDLED; +} + +static void xgbe_isr_task(unsigned long data) +{ + struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_channel *channel; unsigned int dma_isr, dma_ch_isr; @@ -460,7 +496,7 @@ static irqreturn_t xgbe_isr(int irq, void *data) if (!(dma_isr & (1 << i))) continue; - channel = pdata->channel + i; + channel = pdata->channel[i]; dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); netif_dbg(pdata, intr, pdata->netdev, "DMA_CH%u_ISR=%#010x\n", @@ -542,15 +578,36 @@ static irqreturn_t xgbe_isr(int irq, void *data) isr_done: /* If there is not a separate AN irq, handle it here */ if (pdata->dev_irq == pdata->an_irq) - pdata->phy_if.an_isr(irq, pdata); + pdata->phy_if.an_isr(pdata); /* If there is not a separate ECC irq, handle it here */ if (pdata->vdata->ecc_support && (pdata->dev_irq == pdata->ecc_irq)) - xgbe_ecc_isr(irq, pdata); + xgbe_ecc_isr_task((unsigned long)pdata); /* If there is not a separate I2C irq, handle it here */ if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq)) - pdata->i2c_if.i2c_isr(irq, pdata); + pdata->i2c_if.i2c_isr(pdata); + + /* Reissue interrupt if status is not clear */ + if (pdata->vdata->irq_reissue_support) { + unsigned int reissue_mask; + + reissue_mask = 1 << 0; + if (!pdata->per_channel_irq) + reissue_mask |= 0xffff < 4; + + XP_IOWRITE(pdata, XP_INT_REISSUE_EN, reissue_mask); + } +} + +static irqreturn_t xgbe_isr(int irq, void *data) +{ + struct xgbe_prv_data *pdata = data; + + if (pdata->isr_as_tasklet) + tasklet_schedule(&pdata->tasklet_dev); + else + xgbe_isr_task((unsigned long)pdata); return IRQ_HANDLED; } @@ -639,8 +696,8 @@ static void xgbe_init_timers(struct xgbe_prv_data *pdata) setup_timer(&pdata->service_timer, xgbe_service_timer, (unsigned long)pdata); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; if (!channel->tx_ring) break; @@ -661,8 +718,8 @@ static void xgbe_stop_timers(struct xgbe_prv_data *pdata) del_timer_sync(&pdata->service_timer); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; if (!channel->tx_ring) break; @@ -780,8 +837,8 @@ static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) unsigned int i; if (pdata->per_channel_irq) { - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; if (add) netif_napi_add(pdata->netdev, &channel->napi, xgbe_one_poll, NAPI_POLL_WEIGHT); @@ -803,8 +860,8 @@ static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del) unsigned int i; if (pdata->per_channel_irq) { - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; napi_disable(&channel->napi); if (del) @@ -825,6 +882,10 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) unsigned int i; int ret; + tasklet_init(&pdata->tasklet_dev, xgbe_isr_task, (unsigned long)pdata); + tasklet_init(&pdata->tasklet_ecc, xgbe_ecc_isr_task, + (unsigned long)pdata); + ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, netdev->name, pdata); if (ret) { @@ -846,8 +907,8 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) if (!pdata->per_channel_irq) return 0; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; snprintf(channel->dma_irq_name, sizeof(channel->dma_irq_name) - 1, "%s-TxRx-%u", netdev_name(netdev), @@ -861,14 +922,21 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) channel->dma_irq); goto err_dma_irq; } + + irq_set_affinity_hint(channel->dma_irq, + &channel->affinity_mask); } return 0; err_dma_irq: /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ - for (i--, channel--; i < pdata->channel_count; i--, channel--) + for (i--; i < pdata->channel_count; i--) { + channel = pdata->channel[i]; + + irq_set_affinity_hint(channel->dma_irq, NULL); devm_free_irq(pdata->dev, channel->dma_irq, channel); + } if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq)) devm_free_irq(pdata->dev, pdata->ecc_irq, pdata); @@ -892,9 +960,12 @@ static void xgbe_free_irqs(struct xgbe_prv_data *pdata) if (!pdata->per_channel_irq) return; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; + + irq_set_affinity_hint(channel->dma_irq, NULL); devm_free_irq(pdata->dev, channel->dma_irq, channel); + } } void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata) @@ -929,16 +1000,14 @@ void xgbe_init_rx_coalesce(struct xgbe_prv_data *pdata) static void xgbe_free_tx_data(struct xgbe_prv_data *pdata) { struct xgbe_desc_if *desc_if = &pdata->desc_if; - struct xgbe_channel *channel; struct xgbe_ring *ring; struct xgbe_ring_data *rdata; unsigned int i, j; DBGPR("-->xgbe_free_tx_data\n"); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - ring = channel->tx_ring; + for (i = 0; i < pdata->channel_count; i++) { + ring = pdata->channel[i]->tx_ring; if (!ring) break; @@ -954,16 +1023,14 @@ static void xgbe_free_tx_data(struct xgbe_prv_data *pdata) static void xgbe_free_rx_data(struct xgbe_prv_data *pdata) { struct xgbe_desc_if *desc_if = &pdata->desc_if; - struct xgbe_channel *channel; struct xgbe_ring *ring; struct xgbe_ring_data *rdata; unsigned int i, j; DBGPR("-->xgbe_free_rx_data\n"); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - ring = channel->rx_ring; + for (i = 0; i < pdata->channel_count; i++) { + ring = pdata->channel[i]->rx_ring; if (!ring) break; @@ -1131,16 +1198,16 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) hw_if->disable_tx(pdata); hw_if->disable_rx(pdata); + phy_if->phy_stop(pdata); + xgbe_free_irqs(pdata); xgbe_napi_disable(pdata, 1); - phy_if->phy_stop(pdata); - hw_if->exit(pdata); - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; if (!channel->tx_ring) continue; @@ -1211,6 +1278,10 @@ static void xgbe_tx_tstamp(struct work_struct *work) u64 nsec; unsigned long flags; + spin_lock_irqsave(&pdata->tstamp_lock, flags); + if (!pdata->tx_tstamp_skb) + goto unlock; + if (pdata->tx_tstamp) { nsec = timecounter_cyc2time(&pdata->tstamp_tc, pdata->tx_tstamp); @@ -1222,8 +1293,9 @@ static void xgbe_tx_tstamp(struct work_struct *work) dev_kfree_skb_any(pdata->tx_tstamp_skb); - spin_lock_irqsave(&pdata->tstamp_lock, flags); pdata->tx_tstamp_skb = NULL; + +unlock: spin_unlock_irqrestore(&pdata->tstamp_lock, flags); } @@ -1267,6 +1339,7 @@ static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, case HWTSTAMP_FILTER_NONE: break; + case HWTSTAMP_FILTER_NTP_ALL: case HWTSTAMP_FILTER_ALL: XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENALL, 1); XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); @@ -1389,8 +1462,7 @@ static void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata, spin_unlock_irqrestore(&pdata->tstamp_lock, flags); } - if (!XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) - skb_tx_timestamp(skb); + skb_tx_timestamp(skb); } static void xgbe_prep_vlan(struct sk_buff *skb, struct xgbe_packet_data *packet) @@ -1622,7 +1694,7 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len); - channel = pdata->channel + skb->queue_mapping; + channel = pdata->channel[skb->queue_mapping]; txq = netdev_get_tx_queue(netdev, channel->queue_index); ring = channel->tx_ring; packet = &ring->packet_data; @@ -1761,8 +1833,8 @@ static void xgbe_tx_timeout(struct net_device *netdev) schedule_work(&pdata->restart_work); } -static struct rtnl_link_stats64 *xgbe_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *s) +static void xgbe_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *s) { struct xgbe_prv_data *pdata = netdev_priv(netdev); struct xgbe_mmc_stats *pstats = &pdata->mmc_stats; @@ -1788,8 +1860,6 @@ static struct rtnl_link_stats64 *xgbe_get_stats64(struct net_device *netdev, s->tx_dropped = netdev->stats.tx_dropped; DBGPR("<--%s\n", __func__); - - return s; } static int xgbe_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, @@ -1834,9 +1904,10 @@ static void xgbe_poll_controller(struct net_device *netdev) DBGPR("-->xgbe_poll_controller\n"); if (pdata->per_channel_irq) { - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; xgbe_dma_isr(channel->dma_irq, channel); + } } else { disable_irq(pdata->dev_irq); xgbe_isr(pdata->dev_irq, pdata); @@ -1847,7 +1918,8 @@ static void xgbe_poll_controller(struct net_device *netdev) } #endif /* End CONFIG_NET_POLL_CONTROLLER */ -static int xgbe_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, +static int xgbe_setup_tc(struct net_device *netdev, u32 handle, u32 chain_index, + __be16 proto, struct tc_to_netdev *tc_to_netdev) { struct xgbe_prv_data *pdata = netdev_priv(netdev); @@ -1856,7 +1928,8 @@ static int xgbe_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, if (tc_to_netdev->type != TC_SETUP_MQPRIO) return -EINVAL; - tc = tc_to_netdev->tc; + tc_to_netdev->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS; + tc = tc_to_netdev->mqprio->num_tc; if (tc > pdata->hw_feat.tc_cnt) return -EINVAL; @@ -1973,13 +2046,12 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, { struct sk_buff *skb; u8 *packet; - unsigned int copy_len; skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len); if (!skb) return NULL; - /* Start with the header buffer which may contain just the header + /* Pull in the header buffer which may contain just the header * or the header plus data */ dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base, @@ -1988,30 +2060,49 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, packet = page_address(rdata->rx.hdr.pa.pages) + rdata->rx.hdr.pa.pages_offset; - copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : len; - copy_len = min(rdata->rx.hdr.dma_len, copy_len); - skb_copy_to_linear_data(skb, packet, copy_len); - skb_put(skb, copy_len); - - len -= copy_len; - if (len) { - /* Add the remaining data as a frag */ - dma_sync_single_range_for_cpu(pdata->dev, - rdata->rx.buf.dma_base, - rdata->rx.buf.dma_off, - rdata->rx.buf.dma_len, - DMA_FROM_DEVICE); - - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, - rdata->rx.buf.pa.pages, - rdata->rx.buf.pa.pages_offset, - len, rdata->rx.buf.dma_len); - rdata->rx.buf.pa.pages = NULL; - } + skb_copy_to_linear_data(skb, packet, len); + skb_put(skb, len); return skb; } +static unsigned int xgbe_rx_buf1_len(struct xgbe_ring_data *rdata, + struct xgbe_packet_data *packet) +{ + /* Always zero if not the first descriptor */ + if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, FIRST)) + return 0; + + /* First descriptor with split header, return header length */ + if (rdata->rx.hdr_len) + return rdata->rx.hdr_len; + + /* First descriptor but not the last descriptor and no split header, + * so the full buffer was used + */ + if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) + return rdata->rx.hdr.dma_len; + + /* First descriptor and last descriptor and no split header, so + * calculate how much of the buffer was used + */ + return min_t(unsigned int, rdata->rx.hdr.dma_len, rdata->rx.len); +} + +static unsigned int xgbe_rx_buf2_len(struct xgbe_ring_data *rdata, + struct xgbe_packet_data *packet, + unsigned int len) +{ + /* Always the full buffer if not the last descriptor */ + if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) + return rdata->rx.buf.dma_len; + + /* Last descriptor so calculate how much of the buffer was used + * for the last bit of data + */ + return rdata->rx.len - len; +} + static int xgbe_tx_poll(struct xgbe_channel *channel) { struct xgbe_prv_data *pdata = channel->pdata; @@ -2094,8 +2185,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) struct napi_struct *napi; struct sk_buff *skb; struct skb_shared_hwtstamps *hwtstamps; - unsigned int incomplete, error, context_next, context; - unsigned int len, rdesc_len, max_len; + unsigned int last, error, context_next, context; + unsigned int len, buf1_len, buf2_len, max_len; unsigned int received = 0; int packet_count = 0; @@ -2105,7 +2196,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) if (!ring) return 0; - incomplete = 0; + last = 0; context_next = 0; napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; @@ -2139,9 +2230,8 @@ read_again: received++; ring->cur++; - incomplete = XGMAC_GET_BITS(packet->attributes, - RX_PACKET_ATTRIBUTES, - INCOMPLETE); + last = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + LAST); context_next = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, CONTEXT_NEXT); @@ -2150,7 +2240,7 @@ read_again: CONTEXT); /* Earlier error, just drain the remaining data */ - if ((incomplete || context_next) && error) + if ((!last || context_next) && error) goto read_again; if (error || packet->errors) { @@ -2162,16 +2252,22 @@ read_again: } if (!context) { - /* Length is cumulative, get this descriptor's length */ - rdesc_len = rdata->rx.len - len; - len += rdesc_len; + /* Get the data length in the descriptor buffers */ + buf1_len = xgbe_rx_buf1_len(rdata, packet); + len += buf1_len; + buf2_len = xgbe_rx_buf2_len(rdata, packet, len); + len += buf2_len; - if (rdesc_len && !skb) { + if (!skb) { skb = xgbe_create_skb(pdata, napi, rdata, - rdesc_len); - if (!skb) + buf1_len); + if (!skb) { error = 1; - } else if (rdesc_len) { + goto skip_data; + } + } + + if (buf2_len) { dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.buf.dma_base, rdata->rx.buf.dma_off, @@ -2181,13 +2277,14 @@ read_again: skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rdata->rx.buf.pa.pages, rdata->rx.buf.pa.pages_offset, - rdesc_len, + buf2_len, rdata->rx.buf.dma_len); rdata->rx.buf.pa.pages = NULL; } } - if (incomplete || context_next) +skip_data: + if (!last || context_next) goto read_again; if (!skb) @@ -2245,7 +2342,7 @@ next_packet: } /* Check if we need to save state before leaving */ - if (received && (incomplete || context_next)) { + if (received && (!last || context_next)) { rdata = XGBE_GET_DESC_DATA(ring, ring->cur); rdata->state_saved = 1; rdata->state.skb = skb; @@ -2274,10 +2371,7 @@ static int xgbe_one_poll(struct napi_struct *napi, int budget) processed = xgbe_rx_poll(channel, budget); /* If we processed everything, we are done */ - if (processed < budget) { - /* Turn off polling */ - napi_complete_done(napi, processed); - + if ((processed < budget) && napi_complete_done(napi, processed)) { /* Enable Tx and Rx interrupts */ if (pdata->channel_irq_mode) xgbe_enable_rx_tx_int(pdata, channel); @@ -2306,8 +2400,9 @@ static int xgbe_all_poll(struct napi_struct *napi, int budget) do { last_processed = processed; - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; + /* Cleanup Tx ring first */ xgbe_tx_poll(channel); @@ -2319,10 +2414,7 @@ static int xgbe_all_poll(struct napi_struct *napi, int budget) } while ((processed < budget) && (processed != last_processed)); /* If we processed everything, we are done */ - if (processed < budget) { - /* Turn off polling */ - napi_complete_done(napi, processed); - + if ((processed < budget) && napi_complete_done(napi, processed)) { /* Enable Tx and Rx interrupts */ xgbe_enable_rx_tx_ints(pdata); } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 920566a3a599..67a2e52ad25d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -247,7 +247,7 @@ static int xgbe_set_pauseparam(struct net_device *netdev, if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) { netdev_err(netdev, - "autoneg disabled, pause autoneg not avialable\n"); + "autoneg disabled, pause autoneg not available\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c index 0c7088a426e9..4d9062d35930 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c @@ -115,6 +115,7 @@ */ #include <linux/module.h> +#include <linux/interrupt.h> #include <linux/kmod.h> #include <linux/delay.h> #include <linux/completion.h> @@ -273,13 +274,16 @@ static void xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata, XI2C_IOREAD(pdata, IC_CLR_STOP_DET); } -static irqreturn_t xgbe_i2c_isr(int irq, void *data) +static void xgbe_i2c_isr_task(unsigned long data) { struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; struct xgbe_i2c_op_state *state = &pdata->i2c.op_state; unsigned int isr; isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT); + if (!isr) + goto reissue_check; + netif_dbg(pdata, intr, pdata->netdev, "I2C interrupt received: status=%#010x\n", isr); @@ -307,6 +311,21 @@ out: if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET)) complete(&pdata->i2c_complete); +reissue_check: + /* Reissue interrupt if status is not clear */ + if (pdata->vdata->irq_reissue_support) + XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 2); +} + +static irqreturn_t xgbe_i2c_isr(int irq, void *data) +{ + struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + + if (pdata->isr_as_tasklet) + tasklet_schedule(&pdata->tasklet_i2c); + else + xgbe_i2c_isr_task((unsigned long)pdata); + return IRQ_HANDLED; } @@ -348,12 +367,11 @@ static void xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr) XI2C_IOWRITE(pdata, IC_TAR, addr); } -static irqreturn_t xgbe_i2c_combined_isr(int irq, struct xgbe_prv_data *pdata) +static irqreturn_t xgbe_i2c_combined_isr(struct xgbe_prv_data *pdata) { - if (!XI2C_IOREAD(pdata, IC_RAW_INTR_STAT)) - return IRQ_HANDLED; + xgbe_i2c_isr_task((unsigned long)pdata); - return xgbe_i2c_isr(irq, pdata); + return IRQ_HANDLED; } static int xgbe_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *op) @@ -444,6 +462,9 @@ static int xgbe_i2c_start(struct xgbe_prv_data *pdata) /* If we have a separate I2C irq, enable it */ if (pdata->dev_irq != pdata->i2c_irq) { + tasklet_init(&pdata->tasklet_i2c, xgbe_i2c_isr_task, + (unsigned long)pdata); + ret = devm_request_irq(pdata->dev, pdata->i2c_irq, xgbe_i2c_isr, 0, pdata->i2c_name, pdata); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 17ac8f9a51a0..500147d9e3c8 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -140,14 +140,16 @@ static void xgbe_default_config(struct xgbe_prv_data *pdata) { DBGPR("-->xgbe_default_config\n"); - pdata->pblx8 = DMA_PBL_X8_ENABLE; + pdata->blen = DMA_SBMR_BLEN_64; + pdata->pbl = DMA_PBL_128; + pdata->aal = 1; + pdata->rd_osr_limit = 8; + pdata->wr_osr_limit = 8; pdata->tx_sf_mode = MTL_TSF_ENABLE; pdata->tx_threshold = MTL_TX_THRESHOLD_64; - pdata->tx_pbl = DMA_PBL_16; pdata->tx_osp_mode = DMA_OSP_ENABLE; pdata->rx_sf_mode = MTL_RSF_DISABLE; pdata->rx_threshold = MTL_RX_THRESHOLD_64; - pdata->rx_pbl = DMA_PBL_16; pdata->pause_autoneg = 1; pdata->tx_pause = 1; pdata->rx_pause = 1; @@ -277,7 +279,11 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) pdata->desc_ded_period = jiffies; /* Issue software reset to device */ - pdata->hw_if.exit(pdata); + ret = pdata->hw_if.exit(pdata); + if (ret) { + dev_err(dev, "software reset failed\n"); + return ret; + } /* Set default configuration data */ xgbe_default_config(pdata); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 4c5b90eea4af..80684914dd8a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -114,6 +114,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/kmod.h> #include <linux/mdio.h> @@ -664,6 +665,10 @@ static void xgbe_an37_isr(struct xgbe_prv_data *pdata) } else { /* Enable AN interrupts */ xgbe_an37_enable_interrupts(pdata); + + /* Reissue interrupt if status is not clear */ + if (pdata->vdata->irq_reissue_support) + XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3); } } @@ -683,10 +688,14 @@ static void xgbe_an73_isr(struct xgbe_prv_data *pdata) } else { /* Enable AN interrupts */ xgbe_an73_enable_interrupts(pdata); + + /* Reissue interrupt if status is not clear */ + if (pdata->vdata->irq_reissue_support) + XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3); } } -static irqreturn_t xgbe_an_isr(int irq, void *data) +static void xgbe_an_isr_task(unsigned long data) { struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; @@ -704,13 +713,25 @@ static irqreturn_t xgbe_an_isr(int irq, void *data) default: break; } +} + +static irqreturn_t xgbe_an_isr(int irq, void *data) +{ + struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + + if (pdata->isr_as_tasklet) + tasklet_schedule(&pdata->tasklet_an); + else + xgbe_an_isr_task((unsigned long)pdata); return IRQ_HANDLED; } -static irqreturn_t xgbe_an_combined_isr(int irq, struct xgbe_prv_data *pdata) +static irqreturn_t xgbe_an_combined_isr(struct xgbe_prv_data *pdata) { - return xgbe_an_isr(irq, pdata); + xgbe_an_isr_task((unsigned long)pdata); + + return IRQ_HANDLED; } static void xgbe_an_irq_work(struct work_struct *work) @@ -914,6 +935,10 @@ static void xgbe_an_state_machine(struct work_struct *work) break; } + /* Reissue interrupt if status is not clear */ + if (pdata->vdata->irq_reissue_support) + XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3); + mutex_unlock(&pdata->an_mutex); } @@ -1378,6 +1403,9 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata) /* If we have a separate AN irq, enable it */ if (pdata->dev_irq != pdata->an_irq) { + tasklet_init(&pdata->tasklet_an, xgbe_an_isr_task, + (unsigned long)pdata); + ret = devm_request_irq(pdata->dev, pdata->an_irq, xgbe_an_isr, 0, pdata->an_name, pdata); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c index c2730f15bd8b..1e56ad7bd9a5 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c @@ -122,104 +122,41 @@ #include "xgbe.h" #include "xgbe-common.h" -static int xgbe_config_msi(struct xgbe_prv_data *pdata) +static int xgbe_config_multi_msi(struct xgbe_prv_data *pdata) { - unsigned int msi_count; + unsigned int vector_count; unsigned int i, j; int ret; - msi_count = XGBE_MSIX_BASE_COUNT; - msi_count += max(pdata->rx_ring_count, - pdata->tx_ring_count); - msi_count = roundup_pow_of_two(msi_count); + vector_count = XGBE_MSI_BASE_COUNT; + vector_count += max(pdata->rx_ring_count, + pdata->tx_ring_count); - ret = pci_enable_msi_exact(pdata->pcidev, msi_count); + ret = pci_alloc_irq_vectors(pdata->pcidev, XGBE_MSI_MIN_COUNT, + vector_count, PCI_IRQ_MSI | PCI_IRQ_MSIX); if (ret < 0) { - dev_info(pdata->dev, "MSI request for %u interrupts failed\n", - msi_count); - - ret = pci_enable_msi(pdata->pcidev); - if (ret < 0) { - dev_info(pdata->dev, "MSI enablement failed\n"); - return ret; - } - - msi_count = 1; - } - - pdata->irq_count = msi_count; - - pdata->dev_irq = pdata->pcidev->irq; - - if (msi_count > 1) { - pdata->ecc_irq = pdata->pcidev->irq + 1; - pdata->i2c_irq = pdata->pcidev->irq + 2; - pdata->an_irq = pdata->pcidev->irq + 3; - - for (i = XGBE_MSIX_BASE_COUNT, j = 0; - (i < msi_count) && (j < XGBE_MAX_DMA_CHANNELS); - i++, j++) - pdata->channel_irq[j] = pdata->pcidev->irq + i; - pdata->channel_irq_count = j; - - pdata->per_channel_irq = 1; - pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL; - } else { - pdata->ecc_irq = pdata->pcidev->irq; - pdata->i2c_irq = pdata->pcidev->irq; - pdata->an_irq = pdata->pcidev->irq; - } - - if (netif_msg_probe(pdata)) - dev_dbg(pdata->dev, "MSI interrupts enabled\n"); - - return 0; -} - -static int xgbe_config_msix(struct xgbe_prv_data *pdata) -{ - unsigned int msix_count; - unsigned int i, j; - int ret; - - msix_count = XGBE_MSIX_BASE_COUNT; - msix_count += max(pdata->rx_ring_count, - pdata->tx_ring_count); - - pdata->msix_entries = devm_kcalloc(pdata->dev, msix_count, - sizeof(struct msix_entry), - GFP_KERNEL); - if (!pdata->msix_entries) - return -ENOMEM; - - for (i = 0; i < msix_count; i++) - pdata->msix_entries[i].entry = i; - - ret = pci_enable_msix_range(pdata->pcidev, pdata->msix_entries, - XGBE_MSIX_MIN_COUNT, msix_count); - if (ret < 0) { - dev_info(pdata->dev, "MSI-X enablement failed\n"); - devm_kfree(pdata->dev, pdata->msix_entries); - pdata->msix_entries = NULL; + dev_info(pdata->dev, "multi MSI/MSI-X enablement failed\n"); return ret; } + pdata->isr_as_tasklet = 1; pdata->irq_count = ret; - pdata->dev_irq = pdata->msix_entries[0].vector; - pdata->ecc_irq = pdata->msix_entries[1].vector; - pdata->i2c_irq = pdata->msix_entries[2].vector; - pdata->an_irq = pdata->msix_entries[3].vector; + pdata->dev_irq = pci_irq_vector(pdata->pcidev, 0); + pdata->ecc_irq = pci_irq_vector(pdata->pcidev, 1); + pdata->i2c_irq = pci_irq_vector(pdata->pcidev, 2); + pdata->an_irq = pci_irq_vector(pdata->pcidev, 3); - for (i = XGBE_MSIX_BASE_COUNT, j = 0; i < ret; i++, j++) - pdata->channel_irq[j] = pdata->msix_entries[i].vector; + for (i = XGBE_MSI_BASE_COUNT, j = 0; i < ret; i++, j++) + pdata->channel_irq[j] = pci_irq_vector(pdata->pcidev, i); pdata->channel_irq_count = j; pdata->per_channel_irq = 1; pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL; if (netif_msg_probe(pdata)) - dev_dbg(pdata->dev, "MSI-X interrupts enabled\n"); + dev_dbg(pdata->dev, "multi %s interrupts enabled\n", + pdata->pcidev->msix_enabled ? "MSI-X" : "MSI"); return 0; } @@ -228,21 +165,29 @@ static int xgbe_config_irqs(struct xgbe_prv_data *pdata) { int ret; - ret = xgbe_config_msix(pdata); + ret = xgbe_config_multi_msi(pdata); if (!ret) goto out; - ret = xgbe_config_msi(pdata); - if (!ret) - goto out; + ret = pci_alloc_irq_vectors(pdata->pcidev, 1, 1, + PCI_IRQ_LEGACY | PCI_IRQ_MSI); + if (ret < 0) { + dev_info(pdata->dev, "single IRQ enablement failed\n"); + return ret; + } + pdata->isr_as_tasklet = pdata->pcidev->msi_enabled ? 1 : 0; pdata->irq_count = 1; - pdata->irq_shared = 1; + pdata->channel_irq_count = 1; + + pdata->dev_irq = pci_irq_vector(pdata->pcidev, 0); + pdata->ecc_irq = pci_irq_vector(pdata->pcidev, 0); + pdata->i2c_irq = pci_irq_vector(pdata->pcidev, 0); + pdata->an_irq = pci_irq_vector(pdata->pcidev, 0); - pdata->dev_irq = pdata->pcidev->irq; - pdata->ecc_irq = pdata->pcidev->irq; - pdata->i2c_irq = pdata->pcidev->irq; - pdata->an_irq = pdata->pcidev->irq; + if (netif_msg_probe(pdata)) + dev_dbg(pdata->dev, "single %s interrupt enabled\n", + pdata->pcidev->msi_enabled ? "MSI" : "legacy"); out: if (netif_msg_probe(pdata)) { @@ -382,9 +327,9 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Set the DMA coherency values */ pdata->coherent = 1; - pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; - pdata->arcache = XGBE_DMA_OS_ARCACHE; - pdata->awcache = XGBE_DMA_OS_AWCACHE; + pdata->arcr = XGBE_DMA_PCI_ARCR; + pdata->awcr = XGBE_DMA_PCI_AWCR; + pdata->awarcr = XGBE_DMA_PCI_AWARCR; /* Set the maximum channels and queues */ reg = XP_IOREAD(pdata, XP_PROP_1); @@ -425,12 +370,15 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Configure the netdev resource */ ret = xgbe_config_netdev(pdata); if (ret) - goto err_pci_enable; + goto err_irq_vectors; netdev_notice(pdata->netdev, "net device enabled\n"); return 0; +err_irq_vectors: + pci_free_irq_vectors(pdata->pcidev); + err_pci_enable: xgbe_free_pdata(pdata); @@ -446,6 +394,8 @@ static void xgbe_pci_remove(struct pci_dev *pdev) xgbe_deconfig_netdev(pdata); + pci_free_irq_vectors(pdata->pcidev); + xgbe_free_pdata(pdata); } @@ -497,6 +447,9 @@ static const struct xgbe_version_data xgbe_v2a = { .tx_tstamp_workaround = 1, .ecc_support = 1, .i2c_support = 1, + .irq_reissue_support = 1, + .tx_desc_prefetch = 5, + .rx_desc_prefetch = 5, }; static const struct xgbe_version_data xgbe_v2b = { @@ -508,6 +461,9 @@ static const struct xgbe_version_data xgbe_v2b = { .tx_tstamp_workaround = 1, .ecc_support = 1, .i2c_support = 1, + .irq_reissue_support = 1, + .tx_desc_prefetch = 5, + .rx_desc_prefetch = 5, }; static const struct pci_device_id xgbe_pci_table[] = { diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 9d8c953083b4..04b5c149caca 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -711,20 +711,38 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; + if (!phy_data->sfp_mod_absent && !phy_data->sfp_changed) + return; + + pdata->phy.supported &= ~SUPPORTED_Autoneg; + pdata->phy.supported &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause); + pdata->phy.supported &= ~SUPPORTED_TP; + pdata->phy.supported &= ~SUPPORTED_FIBRE; + pdata->phy.supported &= ~SUPPORTED_100baseT_Full; + pdata->phy.supported &= ~SUPPORTED_1000baseT_Full; + pdata->phy.supported &= ~SUPPORTED_10000baseT_Full; + if (phy_data->sfp_mod_absent) { pdata->phy.speed = SPEED_UNKNOWN; pdata->phy.duplex = DUPLEX_UNKNOWN; pdata->phy.autoneg = AUTONEG_ENABLE; + pdata->phy.pause_autoneg = AUTONEG_ENABLE; + + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_TP; + pdata->phy.supported |= SUPPORTED_FIBRE; + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) + pdata->phy.supported |= SUPPORTED_100baseT_Full; + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) + pdata->phy.supported |= SUPPORTED_1000baseT_Full; + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) + pdata->phy.supported |= SUPPORTED_10000baseT_Full; + pdata->phy.advertising = pdata->phy.supported; - } - pdata->phy.advertising &= ~ADVERTISED_Autoneg; - pdata->phy.advertising &= ~ADVERTISED_TP; - pdata->phy.advertising &= ~ADVERTISED_FIBRE; - pdata->phy.advertising &= ~ADVERTISED_100baseT_Full; - pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full; - pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full; - pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC; + return; + } switch (phy_data->sfp_base) { case XGBE_SFP_BASE_1000_T: @@ -734,17 +752,25 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) pdata->phy.speed = SPEED_UNKNOWN; pdata->phy.duplex = DUPLEX_UNKNOWN; pdata->phy.autoneg = AUTONEG_ENABLE; - pdata->phy.advertising |= ADVERTISED_Autoneg; + pdata->phy.pause_autoneg = AUTONEG_ENABLE; + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; break; case XGBE_SFP_BASE_10000_SR: case XGBE_SFP_BASE_10000_LR: case XGBE_SFP_BASE_10000_LRM: case XGBE_SFP_BASE_10000_ER: case XGBE_SFP_BASE_10000_CR: - default: pdata->phy.speed = SPEED_10000; pdata->phy.duplex = DUPLEX_FULL; pdata->phy.autoneg = AUTONEG_DISABLE; + pdata->phy.pause_autoneg = AUTONEG_DISABLE; + break; + default: + pdata->phy.speed = SPEED_UNKNOWN; + pdata->phy.duplex = DUPLEX_UNKNOWN; + pdata->phy.autoneg = AUTONEG_DISABLE; + pdata->phy.pause_autoneg = AUTONEG_DISABLE; break; } @@ -752,36 +778,38 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) case XGBE_SFP_BASE_1000_T: case XGBE_SFP_BASE_1000_CX: case XGBE_SFP_BASE_10000_CR: - pdata->phy.advertising |= ADVERTISED_TP; + pdata->phy.supported |= SUPPORTED_TP; break; default: - pdata->phy.advertising |= ADVERTISED_FIBRE; + pdata->phy.supported |= SUPPORTED_FIBRE; } switch (phy_data->sfp_speed) { case XGBE_SFP_SPEED_100_1000: if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) - pdata->phy.advertising |= ADVERTISED_100baseT_Full; + pdata->phy.supported |= SUPPORTED_100baseT_Full; if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) - pdata->phy.advertising |= ADVERTISED_1000baseT_Full; + pdata->phy.supported |= SUPPORTED_1000baseT_Full; break; case XGBE_SFP_SPEED_1000: if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) - pdata->phy.advertising |= ADVERTISED_1000baseT_Full; + pdata->phy.supported |= SUPPORTED_1000baseT_Full; break; case XGBE_SFP_SPEED_10000: if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) - pdata->phy.advertising |= ADVERTISED_10000baseT_Full; + pdata->phy.supported |= SUPPORTED_10000baseT_Full; break; default: /* Choose the fastest supported speed */ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) - pdata->phy.advertising |= ADVERTISED_10000baseT_Full; + pdata->phy.supported |= SUPPORTED_10000baseT_Full; else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) - pdata->phy.advertising |= ADVERTISED_1000baseT_Full; + pdata->phy.supported |= SUPPORTED_1000baseT_Full; else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) - pdata->phy.advertising |= ADVERTISED_100baseT_Full; + pdata->phy.supported |= SUPPORTED_100baseT_Full; } + + pdata->phy.advertising = pdata->phy.supported; } static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom, @@ -875,6 +903,16 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata) !phy_data->sfp_phy_avail) return 0; + /* Set the proper MDIO mode for the PHY */ + ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr, + phy_data->phydev_mode); + if (ret) { + netdev_err(pdata->netdev, + "mdio port/clause not compatible (%u/%u)\n", + phy_data->mdio_addr, phy_data->phydev_mode); + return ret; + } + /* Create and connect to the PHY device */ phydev = get_phy_device(phy_data->mii, phy_data->mdio_addr, (phy_data->phydev_mode == XGBE_MDIO_MODE_CL45)); @@ -1083,7 +1121,8 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata) ret = xgbe_phy_sfp_get_mux(pdata); if (ret) { - netdev_err(pdata->netdev, "I2C error setting SFP MUX\n"); + dev_err_once(pdata->dev, "%s: I2C error setting SFP MUX\n", + netdev_name(pdata->netdev)); return ret; } @@ -1093,7 +1132,8 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata) &eeprom_addr, sizeof(eeprom_addr), &sfp_eeprom, sizeof(sfp_eeprom)); if (ret) { - netdev_err(pdata->netdev, "I2C error reading SFP EEPROM\n"); + dev_err_once(pdata->dev, "%s: I2C error reading SFP EEPROM\n", + netdev_name(pdata->netdev)); goto put; } @@ -1152,7 +1192,8 @@ static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata) &gpio_reg, sizeof(gpio_reg), gpio_ports, sizeof(gpio_ports)); if (ret) { - netdev_err(pdata->netdev, "I2C error reading SFP GPIOs\n"); + dev_err_once(pdata->dev, "%s: I2C error reading SFP GPIOs\n", + netdev_name(pdata->netdev)); return; } @@ -1682,19 +1723,25 @@ static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata) xgbe_phy_put_comm_ownership(pdata); } -static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata) +static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, + unsigned int cmd, unsigned int sub_cmd) { - if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) - return; + unsigned int s0 = 0; + unsigned int wait; /* Log if a previous command did not complete */ - netif_dbg(pdata, link, pdata->netdev, - "firmware mailbox not ready for command\n"); -} + if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) + netif_dbg(pdata, link, pdata->netdev, + "firmware mailbox not ready for command\n"); -static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata) -{ - unsigned int wait; + /* Construct the command */ + XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd); + XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, sub_cmd); + + /* Issue the command */ + XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); + XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); + XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); /* Wait for command to complete */ wait = XGBE_RATECHANGE_COUNT; @@ -1711,21 +1758,8 @@ static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata) static void xgbe_phy_rrc(struct xgbe_prv_data *pdata) { - unsigned int s0; - - xgbe_phy_start_ratechange(pdata); - /* Receiver Reset Cycle */ - s0 = 0; - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 5); - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0); - - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); + xgbe_phy_perform_ratechange(pdata, 5, 0); netif_dbg(pdata, link, pdata->netdev, "receiver reset complete\n"); } @@ -1734,14 +1768,8 @@ static void xgbe_phy_power_off(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - xgbe_phy_start_ratechange(pdata); - - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, 0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); + /* Power off */ + xgbe_phy_perform_ratechange(pdata, 0, 0); phy_data->cur_mode = XGBE_MODE_UNKNOWN; @@ -1751,33 +1779,21 @@ static void xgbe_phy_power_off(struct xgbe_prv_data *pdata) static void xgbe_phy_sfi_mode(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int s0; xgbe_phy_set_redrv_mode(pdata); - xgbe_phy_start_ratechange(pdata); - /* 10G/SFI */ - s0 = 0; - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 3); if (phy_data->sfp_cable != XGBE_SFP_CABLE_PASSIVE) { - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0); + xgbe_phy_perform_ratechange(pdata, 3, 0); } else { if (phy_data->sfp_cable_len <= 1) - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1); + xgbe_phy_perform_ratechange(pdata, 3, 1); else if (phy_data->sfp_cable_len <= 3) - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2); + xgbe_phy_perform_ratechange(pdata, 3, 2); else - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3); + xgbe_phy_perform_ratechange(pdata, 3, 3); } - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); - phy_data->cur_mode = XGBE_MODE_SFI; netif_dbg(pdata, link, pdata->netdev, "10GbE SFI mode set\n"); @@ -1786,23 +1802,11 @@ static void xgbe_phy_sfi_mode(struct xgbe_prv_data *pdata) static void xgbe_phy_x_mode(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int s0; xgbe_phy_set_redrv_mode(pdata); - xgbe_phy_start_ratechange(pdata); - /* 1G/X */ - s0 = 0; - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1); - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3); - - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); + xgbe_phy_perform_ratechange(pdata, 1, 3); phy_data->cur_mode = XGBE_MODE_X; @@ -1812,23 +1816,11 @@ static void xgbe_phy_x_mode(struct xgbe_prv_data *pdata) static void xgbe_phy_sgmii_1000_mode(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int s0; xgbe_phy_set_redrv_mode(pdata); - xgbe_phy_start_ratechange(pdata); - /* 1G/SGMII */ - s0 = 0; - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1); - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2); - - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); + xgbe_phy_perform_ratechange(pdata, 1, 2); phy_data->cur_mode = XGBE_MODE_SGMII_1000; @@ -1838,23 +1830,11 @@ static void xgbe_phy_sgmii_1000_mode(struct xgbe_prv_data *pdata) static void xgbe_phy_sgmii_100_mode(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int s0; xgbe_phy_set_redrv_mode(pdata); - xgbe_phy_start_ratechange(pdata); - - /* 1G/SGMII */ - s0 = 0; - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1); - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1); - - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); + /* 100M/SGMII */ + xgbe_phy_perform_ratechange(pdata, 1, 1); phy_data->cur_mode = XGBE_MODE_SGMII_100; @@ -1864,23 +1844,11 @@ static void xgbe_phy_sgmii_100_mode(struct xgbe_prv_data *pdata) static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int s0; xgbe_phy_set_redrv_mode(pdata); - xgbe_phy_start_ratechange(pdata); - /* 10G/KR */ - s0 = 0; - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 4); - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0); - - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); + xgbe_phy_perform_ratechange(pdata, 4, 0); phy_data->cur_mode = XGBE_MODE_KR; @@ -1890,23 +1858,11 @@ static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata) static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int s0; xgbe_phy_set_redrv_mode(pdata); - xgbe_phy_start_ratechange(pdata); - /* 2.5G/KX */ - s0 = 0; - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 2); - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0); - - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); + xgbe_phy_perform_ratechange(pdata, 2, 0); phy_data->cur_mode = XGBE_MODE_KX_2500; @@ -1916,23 +1872,11 @@ static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata) static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int s0; xgbe_phy_set_redrv_mode(pdata); - xgbe_phy_start_ratechange(pdata); - /* 1G/KX */ - s0 = 0; - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1); - XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3); - - /* Call FW to make the change */ - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); - XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); - XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); - - xgbe_phy_complete_ratechange(pdata); + xgbe_phy_perform_ratechange(pdata, 1, 3); phy_data->cur_mode = XGBE_MODE_KX_1000; @@ -2025,6 +1969,8 @@ static enum xgbe_mode xgbe_phy_get_baset_mode(struct xgbe_phy_data *phy_data, return XGBE_MODE_SGMII_100; case SPEED_1000: return XGBE_MODE_SGMII_1000; + case SPEED_2500: + return XGBE_MODE_KX_2500; case SPEED_10000: return XGBE_MODE_KR; default: @@ -2168,6 +2114,9 @@ static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata, case XGBE_MODE_SGMII_1000: return xgbe_phy_check_mode(pdata, mode, ADVERTISED_1000baseT_Full); + case XGBE_MODE_KX_2500: + return xgbe_phy_check_mode(pdata, mode, + ADVERTISED_2500baseX_Full); case XGBE_MODE_KR: return xgbe_phy_check_mode(pdata, mode, ADVERTISED_10000baseT_Full); @@ -2198,6 +2147,8 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata, return xgbe_phy_check_mode(pdata, mode, ADVERTISED_1000baseT_Full); case XGBE_MODE_SFI: + if (phy_data->sfp_mod_absent) + return true; return xgbe_phy_check_mode(pdata, mode, ADVERTISED_10000baseT_Full); default: @@ -2275,6 +2226,8 @@ static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_phy_data *phy_data, case SPEED_100: case SPEED_1000: return true; + case SPEED_2500: + return (phy_data->port_mode == XGBE_PORT_MODE_NBASE_T); case SPEED_10000: return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T); default: @@ -2722,6 +2675,18 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata) if (ret) return ret; + /* Set the proper MDIO mode for the re-driver */ + if (phy_data->redrv && !phy_data->redrv_if) { + ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr, + XGBE_MDIO_MODE_CL22); + if (ret) { + netdev_err(pdata->netdev, + "redriver mdio port not compatible (%u)\n", + phy_data->redrv_addr); + return ret; + } + } + /* Start in highest supported mode */ xgbe_phy_set_mode(pdata, phy_data->start_mode); @@ -2989,9 +2954,6 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) { pdata->phy.supported |= SUPPORTED_10000baseT_Full; phy_data->start_mode = XGBE_MODE_SFI; - if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) - pdata->phy.supported |= - SUPPORTED_10000baseR_FEC; } phy_data->phydev_mode = XGBE_MDIO_MODE_CL22; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c index 84d4c51cab8c..d0f3dfb88202 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c @@ -448,13 +448,11 @@ static int xgbe_platform_probe(struct platform_device *pdev) } pdata->coherent = (attr == DEV_DMA_COHERENT); if (pdata->coherent) { - pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; - pdata->arcache = XGBE_DMA_OS_ARCACHE; - pdata->awcache = XGBE_DMA_OS_AWCACHE; + pdata->arcr = XGBE_DMA_OS_ARCR; + pdata->awcr = XGBE_DMA_OS_AWCR; } else { - pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN; - pdata->arcache = XGBE_DMA_SYS_ARCACHE; - pdata->awcache = XGBE_DMA_SYS_AWCACHE; + pdata->arcr = XGBE_DMA_SYS_ARCR; + pdata->awcr = XGBE_DMA_SYS_AWCR; } /* Set the maximum fifo amounts */ diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c index a533a6cc2d53..d06d260cf1e2 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c @@ -267,7 +267,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) ktime_to_ns(ktime_get_real())); /* Disable all timestamping to start */ - XGMAC_IOWRITE(pdata, MAC_TCR, 0); + XGMAC_IOWRITE(pdata, MAC_TSCR, 0); pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF; pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 00108815b55e..0938294f640a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -128,6 +128,7 @@ #include <linux/net_tstamp.h> #include <net/dcbnl.h> #include <linux/completion.h> +#include <linux/cpumask.h> #define XGBE_DRV_NAME "amd-xgbe" #define XGBE_DRV_VERSION "1.0.3" @@ -163,14 +164,17 @@ #define XGBE_DMA_STOP_TIMEOUT 1 /* DMA cache settings - Outer sharable, write-back, write-allocate */ -#define XGBE_DMA_OS_AXDOMAIN 0x2 -#define XGBE_DMA_OS_ARCACHE 0xb -#define XGBE_DMA_OS_AWCACHE 0xf +#define XGBE_DMA_OS_ARCR 0x002b2b2b +#define XGBE_DMA_OS_AWCR 0x2f2f2f2f /* DMA cache settings - System, no caches used */ -#define XGBE_DMA_SYS_AXDOMAIN 0x3 -#define XGBE_DMA_SYS_ARCACHE 0x0 -#define XGBE_DMA_SYS_AWCACHE 0x0 +#define XGBE_DMA_SYS_ARCR 0x00303030 +#define XGBE_DMA_SYS_AWCR 0x30303030 + +/* DMA cache settings - PCI device */ +#define XGBE_DMA_PCI_ARCR 0x00000003 +#define XGBE_DMA_PCI_AWCR 0x13131313 +#define XGBE_DMA_PCI_AWARCR 0x00000313 /* DMA channel interrupt modes */ #define XGBE_IRQ_MODE_EDGE 0 @@ -211,9 +215,9 @@ #define XGBE_MAC_PROP_OFFSET 0x1d000 #define XGBE_I2C_CTRL_OFFSET 0x1e000 -/* PCI MSIx support */ -#define XGBE_MSIX_BASE_COUNT 4 -#define XGBE_MSIX_MIN_COUNT (XGBE_MSIX_BASE_COUNT + 1) +/* PCI MSI/MSIx support */ +#define XGBE_MSI_BASE_COUNT 4 +#define XGBE_MSI_MIN_COUNT (XGBE_MSI_BASE_COUNT + 1) /* PCI clock frequencies */ #define XGBE_V2_DMA_CLOCK_FREQ 500000000 /* 500 MHz */ @@ -412,6 +416,7 @@ struct xgbe_ring { /* Page allocation for RX buffers */ struct xgbe_page_alloc rx_hdr_pa; struct xgbe_page_alloc rx_buf_pa; + int node; /* Ring index values * cur - Tx: index of descriptor to be used for current transfer @@ -462,6 +467,9 @@ struct xgbe_channel { struct xgbe_ring *tx_ring; struct xgbe_ring *rx_ring; + + int node; + cpumask_t affinity_mask; } ____cacheline_aligned; enum xgbe_state { @@ -734,13 +742,6 @@ struct xgbe_hw_if { /* For TX DMA Operate on Second Frame config */ int (*config_osp_mode)(struct xgbe_prv_data *); - /* For RX and TX PBL config */ - int (*config_rx_pbl_val)(struct xgbe_prv_data *); - int (*get_rx_pbl_val)(struct xgbe_prv_data *); - int (*config_tx_pbl_val)(struct xgbe_prv_data *); - int (*get_tx_pbl_val)(struct xgbe_prv_data *); - int (*config_pblx8)(struct xgbe_prv_data *); - /* For MMC statistics */ void (*rx_mmc_int)(struct xgbe_prv_data *); void (*tx_mmc_int)(struct xgbe_prv_data *); @@ -837,7 +838,7 @@ struct xgbe_phy_if { bool (*phy_valid_speed)(struct xgbe_prv_data *, int); /* For single interrupt support */ - irqreturn_t (*an_isr)(int, struct xgbe_prv_data *); + irqreturn_t (*an_isr)(struct xgbe_prv_data *); /* PHY implementation specific services */ struct xgbe_phy_impl_if phy_impl; @@ -855,7 +856,7 @@ struct xgbe_i2c_if { int (*i2c_xfer)(struct xgbe_prv_data *, struct xgbe_i2c_op *); /* For single interrupt support */ - irqreturn_t (*i2c_isr)(int, struct xgbe_prv_data *); + irqreturn_t (*i2c_isr)(struct xgbe_prv_data *); }; struct xgbe_desc_if { @@ -924,6 +925,9 @@ struct xgbe_version_data { unsigned int tx_tstamp_workaround; unsigned int ecc_support; unsigned int i2c_support; + unsigned int irq_reissue_support; + unsigned int tx_desc_prefetch; + unsigned int rx_desc_prefetch; }; struct xgbe_prv_data { @@ -982,14 +986,12 @@ struct xgbe_prv_data { unsigned int desc_ded_count; unsigned int desc_sec_count; - struct msix_entry *msix_entries; int dev_irq; int ecc_irq; int i2c_irq; int channel_irq[XGBE_MAX_DMA_CHANNELS]; unsigned int per_channel_irq; - unsigned int irq_shared; unsigned int irq_count; unsigned int channel_irq_count; unsigned int channel_irq_mode; @@ -1003,9 +1005,9 @@ struct xgbe_prv_data { /* AXI DMA settings */ unsigned int coherent; - unsigned int axdomain; - unsigned int arcache; - unsigned int awcache; + unsigned int arcr; + unsigned int awcr; + unsigned int awarcr; /* Service routine support */ struct workqueue_struct *dev_workqueue; @@ -1013,7 +1015,7 @@ struct xgbe_prv_data { struct timer_list service_timer; /* Rings for Tx/Rx on a DMA channel */ - struct xgbe_channel *channel; + struct xgbe_channel *channel[XGBE_MAX_DMA_CHANNELS]; unsigned int tx_max_channel_count; unsigned int rx_max_channel_count; unsigned int channel_count; @@ -1028,19 +1030,21 @@ struct xgbe_prv_data { unsigned int rx_q_count; /* Tx/Rx common settings */ - unsigned int pblx8; + unsigned int blen; + unsigned int pbl; + unsigned int aal; + unsigned int rd_osr_limit; + unsigned int wr_osr_limit; /* Tx settings */ unsigned int tx_sf_mode; unsigned int tx_threshold; - unsigned int tx_pbl; unsigned int tx_osp_mode; unsigned int tx_max_fifo_size; /* Rx settings */ unsigned int rx_sf_mode; unsigned int rx_threshold; - unsigned int rx_pbl; unsigned int rx_max_fifo_size; /* Tx coalescing settings */ @@ -1161,6 +1165,12 @@ struct xgbe_prv_data { unsigned int lpm_ctrl; /* CTRL1 for resume */ + unsigned int isr_as_tasklet; + struct tasklet_struct tasklet_dev; + struct tasklet_struct tasklet_ecc; + struct tasklet_struct tasklet_i2c; + struct tasklet_struct tasklet_an; + #ifdef CONFIG_DEBUG_FS struct dentry *xgbe_debugfs; |