mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 09:31:50 +00:00
Merge branch 'upstream-fixes'
This commit is contained in:
commit
23a56e2cbe
@ -586,6 +586,7 @@ struct rtl8139_private {
|
||||
dma_addr_t tx_bufs_dma;
|
||||
signed char phys[4]; /* MII device addresses. */
|
||||
char twistie, twist_row, twist_col; /* Twister tune state. */
|
||||
unsigned int watchdog_fired : 1;
|
||||
unsigned int default_port : 4; /* Last dev->if_port value. */
|
||||
unsigned int have_thread : 1;
|
||||
spinlock_t lock;
|
||||
@ -638,6 +639,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev);
|
||||
static void __set_rx_mode (struct net_device *dev);
|
||||
static void rtl8139_hw_start (struct net_device *dev);
|
||||
static void rtl8139_thread (void *_data);
|
||||
static void rtl8139_tx_timeout_task(void *_data);
|
||||
static struct ethtool_ops rtl8139_ethtool_ops;
|
||||
|
||||
/* write MMIO register, with flush */
|
||||
@ -1598,13 +1600,14 @@ static void rtl8139_thread (void *_data)
|
||||
{
|
||||
struct net_device *dev = _data;
|
||||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
unsigned long thr_delay;
|
||||
unsigned long thr_delay = next_tick;
|
||||
|
||||
if (rtnl_shlock_nowait() == 0) {
|
||||
if (tp->watchdog_fired) {
|
||||
tp->watchdog_fired = 0;
|
||||
rtl8139_tx_timeout_task(_data);
|
||||
} else if (rtnl_shlock_nowait() == 0) {
|
||||
rtl8139_thread_iter (dev, tp, tp->mmio_addr);
|
||||
rtnl_unlock ();
|
||||
|
||||
thr_delay = next_tick;
|
||||
} else {
|
||||
/* unlikely race. mitigate with fast poll. */
|
||||
thr_delay = HZ / 2;
|
||||
@ -1631,7 +1634,8 @@ static void rtl8139_stop_thread(struct rtl8139_private *tp)
|
||||
if (tp->have_thread) {
|
||||
cancel_rearming_delayed_work(&tp->thread);
|
||||
tp->have_thread = 0;
|
||||
}
|
||||
} else
|
||||
flush_scheduled_work();
|
||||
}
|
||||
|
||||
static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
|
||||
@ -1642,14 +1646,13 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
|
||||
/* XXX account for unsent Tx packets in tp->stats.tx_dropped */
|
||||
}
|
||||
|
||||
|
||||
static void rtl8139_tx_timeout (struct net_device *dev)
|
||||
static void rtl8139_tx_timeout_task (void *_data)
|
||||
{
|
||||
struct net_device *dev = _data;
|
||||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
int i;
|
||||
u8 tmp8;
|
||||
unsigned long flags;
|
||||
|
||||
printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x "
|
||||
"media %2.2x.\n", dev->name, RTL_R8 (ChipCmd),
|
||||
@ -1670,23 +1673,34 @@ static void rtl8139_tx_timeout (struct net_device *dev)
|
||||
if (tmp8 & CmdTxEnb)
|
||||
RTL_W8 (ChipCmd, CmdRxEnb);
|
||||
|
||||
spin_lock(&tp->rx_lock);
|
||||
spin_lock_bh(&tp->rx_lock);
|
||||
/* Disable interrupts by clearing the interrupt mask. */
|
||||
RTL_W16 (IntrMask, 0x0000);
|
||||
|
||||
/* Stop a shared interrupt from scavenging while we are. */
|
||||
spin_lock_irqsave (&tp->lock, flags);
|
||||
spin_lock_irq(&tp->lock);
|
||||
rtl8139_tx_clear (tp);
|
||||
spin_unlock_irqrestore (&tp->lock, flags);
|
||||
spin_unlock_irq(&tp->lock);
|
||||
|
||||
/* ...and finally, reset everything */
|
||||
if (netif_running(dev)) {
|
||||
rtl8139_hw_start (dev);
|
||||
netif_wake_queue (dev);
|
||||
}
|
||||
spin_unlock(&tp->rx_lock);
|
||||
spin_unlock_bh(&tp->rx_lock);
|
||||
}
|
||||
|
||||
static void rtl8139_tx_timeout (struct net_device *dev)
|
||||
{
|
||||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
|
||||
if (!tp->have_thread) {
|
||||
INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev);
|
||||
schedule_delayed_work(&tp->thread, next_tick);
|
||||
} else
|
||||
tp->watchdog_fired = 1;
|
||||
|
||||
}
|
||||
|
||||
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
|
@ -1145,7 +1145,8 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
}
|
||||
|
||||
#define BOND_INTERSECT_FEATURES \
|
||||
(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
|
||||
(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
|
||||
NETIF_F_TSO|NETIF_F_UFO)
|
||||
|
||||
/*
|
||||
* Compute the common dev->feature set available to all slaves. Some
|
||||
@ -1168,6 +1169,16 @@ static int bond_compute_features(struct bonding *bond)
|
||||
NETIF_F_HW_CSUM)))
|
||||
features &= ~NETIF_F_SG;
|
||||
|
||||
/*
|
||||
* features will include NETIF_F_TSO (NETIF_F_UFO) iff all
|
||||
* slave devices support NETIF_F_TSO (NETIF_F_UFO), which
|
||||
* implies that all slaves also support scatter-gather
|
||||
* (NETIF_F_SG), which implies that features also includes
|
||||
* NETIF_F_SG. So no need to check whether we have an
|
||||
* illegal combination of NETIF_F_{TSO,UFO} and
|
||||
* !NETIF_F_SG
|
||||
*/
|
||||
|
||||
features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
|
||||
bond_dev->features = features;
|
||||
|
||||
@ -4080,6 +4091,8 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
|
||||
|
||||
static struct ethtool_ops bond_ethtool_ops = {
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.get_tso = ethtool_op_get_tso,
|
||||
.get_ufo = ethtool_op_get_ufo,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.get_drvinfo = bond_ethtool_get_drvinfo,
|
||||
};
|
||||
|
@ -260,7 +260,7 @@ static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer,
|
||||
char *ifname;
|
||||
int i, res, found, ret = count;
|
||||
struct slave *slave;
|
||||
struct net_device *dev = 0;
|
||||
struct net_device *dev = NULL;
|
||||
struct bonding *bond = to_bond(cd);
|
||||
|
||||
/* Quick sanity check -- is the bond interface up? */
|
||||
@ -995,7 +995,7 @@ static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, s
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": %s: Setting primary slave to None.\n",
|
||||
bond->dev->name);
|
||||
bond->primary_slave = 0;
|
||||
bond->primary_slave = NULL;
|
||||
bond_select_active_slave(bond);
|
||||
} else {
|
||||
printk(KERN_INFO DRV_NAME
|
||||
@ -1123,7 +1123,7 @@ static ssize_t bonding_store_active_slave(struct class_device *cd, const char *b
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": %s: Setting active slave to None.\n",
|
||||
bond->dev->name);
|
||||
bond->primary_slave = 0;
|
||||
bond->primary_slave = NULL;
|
||||
bond_select_active_slave(bond);
|
||||
} else {
|
||||
printk(KERN_INFO DRV_NAME
|
||||
|
@ -2752,8 +2752,6 @@ static int e100_resume(struct pci_dev *pdev)
|
||||
retval = pci_enable_wake(pdev, 0, 0);
|
||||
if (retval)
|
||||
DPRINTK(PROBE,ERR, "Error clearing wake events\n");
|
||||
if(e100_hw_init(nic))
|
||||
DPRINTK(HW, ERR, "e100_hw_init failed\n");
|
||||
|
||||
netif_device_attach(netdev);
|
||||
if(netif_running(netdev))
|
||||
|
@ -199,8 +199,7 @@ static int gfar_probe(struct platform_device *pdev)
|
||||
|
||||
/* get a pointer to the register memory */
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->regs = (struct gfar *)
|
||||
ioremap(r->start, sizeof (struct gfar));
|
||||
priv->regs = ioremap(r->start, sizeof (struct gfar));
|
||||
|
||||
if (NULL == priv->regs) {
|
||||
err = -ENOMEM;
|
||||
@ -369,7 +368,7 @@ static int gfar_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
register_fail:
|
||||
iounmap((void *) priv->regs);
|
||||
iounmap(priv->regs);
|
||||
regs_fail:
|
||||
free_netdev(dev);
|
||||
return err;
|
||||
@ -382,7 +381,7 @@ static int gfar_remove(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
iounmap((void *) priv->regs);
|
||||
iounmap(priv->regs);
|
||||
free_netdev(dev);
|
||||
|
||||
return 0;
|
||||
@ -454,8 +453,7 @@ static void init_registers(struct net_device *dev)
|
||||
|
||||
/* Zero out the rmon mib registers if it has them */
|
||||
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
|
||||
memset((void *) &(priv->regs->rmon), 0,
|
||||
sizeof (struct rmon_mib));
|
||||
memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib));
|
||||
|
||||
/* Mask off the CAM interrupts */
|
||||
gfar_write(&priv->regs->rmon.cam1, 0xffffffff);
|
||||
@ -477,7 +475,7 @@ static void init_registers(struct net_device *dev)
|
||||
void gfar_halt(struct net_device *dev)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regs = priv->regs;
|
||||
struct gfar __iomem *regs = priv->regs;
|
||||
u32 tempval;
|
||||
|
||||
/* Mask all interrupts */
|
||||
@ -507,7 +505,7 @@ void gfar_halt(struct net_device *dev)
|
||||
void stop_gfar(struct net_device *dev)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regs = priv->regs;
|
||||
struct gfar __iomem *regs = priv->regs;
|
||||
unsigned long flags;
|
||||
|
||||
phy_stop(priv->phydev);
|
||||
@ -590,7 +588,7 @@ static void free_skb_resources(struct gfar_private *priv)
|
||||
void gfar_start(struct net_device *dev)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regs = priv->regs;
|
||||
struct gfar __iomem *regs = priv->regs;
|
||||
u32 tempval;
|
||||
|
||||
/* Enable Rx and Tx in MACCFG1 */
|
||||
@ -624,7 +622,7 @@ int startup_gfar(struct net_device *dev)
|
||||
unsigned long vaddr;
|
||||
int i;
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regs = priv->regs;
|
||||
struct gfar __iomem *regs = priv->regs;
|
||||
int err = 0;
|
||||
u32 rctrl = 0;
|
||||
u32 attrs = 0;
|
||||
@ -1622,7 +1620,7 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
static void adjust_link(struct net_device *dev)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regs = priv->regs;
|
||||
struct gfar __iomem *regs = priv->regs;
|
||||
unsigned long flags;
|
||||
struct phy_device *phydev = priv->phydev;
|
||||
int new_state = 0;
|
||||
@ -1703,7 +1701,7 @@ static void gfar_set_multi(struct net_device *dev)
|
||||
{
|
||||
struct dev_mc_list *mc_ptr;
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regs = priv->regs;
|
||||
struct gfar __iomem *regs = priv->regs;
|
||||
u32 tempval;
|
||||
|
||||
if(dev->flags & IFF_PROMISC) {
|
||||
@ -1842,7 +1840,7 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr)
|
||||
int idx;
|
||||
char tmpbuf[MAC_ADDR_LEN];
|
||||
u32 tempval;
|
||||
u32 *macptr = &priv->regs->macstnaddr1;
|
||||
u32 __iomem *macptr = &priv->regs->macstnaddr1;
|
||||
|
||||
macptr += num*2;
|
||||
|
||||
|
@ -682,8 +682,8 @@ struct gfar_private {
|
||||
struct rxbd8 *cur_rx; /* Next free rx ring entry */
|
||||
struct txbd8 *cur_tx; /* Next free ring entry */
|
||||
struct txbd8 *dirty_tx; /* The Ring entry to be freed. */
|
||||
struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
|
||||
u32 *hash_regs[16];
|
||||
struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */
|
||||
u32 __iomem *hash_regs[16];
|
||||
int hash_width;
|
||||
struct net_device_stats stats; /* linux network statistics */
|
||||
struct gfar_extra_stats extra_stats;
|
||||
@ -718,14 +718,14 @@ struct gfar_private {
|
||||
uint32_t msg_enable;
|
||||
};
|
||||
|
||||
static inline u32 gfar_read(volatile unsigned *addr)
|
||||
static inline u32 gfar_read(volatile unsigned __iomem *addr)
|
||||
{
|
||||
u32 val;
|
||||
val = in_be32(addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void gfar_write(volatile unsigned *addr, u32 val)
|
||||
static inline void gfar_write(volatile unsigned __iomem *addr, u32 val)
|
||||
{
|
||||
out_be32(addr, val);
|
||||
}
|
||||
|
@ -144,11 +144,11 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
|
||||
u64 *extra = (u64 *) & priv->extra_stats;
|
||||
|
||||
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
|
||||
u32 *rmon = (u32 *) & priv->regs->rmon;
|
||||
u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon;
|
||||
struct gfar_stats *stats = (struct gfar_stats *) buf;
|
||||
|
||||
for (i = 0; i < GFAR_RMON_LEN; i++)
|
||||
stats->rmon[i] = (u64) (rmon[i]);
|
||||
stats->rmon[i] = (u64) gfar_read(&rmon[i]);
|
||||
|
||||
for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
|
||||
stats->extra[i] = extra[i];
|
||||
@ -221,11 +221,11 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi
|
||||
{
|
||||
int i;
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
u32 *theregs = (u32 *) priv->regs;
|
||||
u32 __iomem *theregs = (u32 __iomem *) priv->regs;
|
||||
u32 *buf = (u32 *) regbuf;
|
||||
|
||||
for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++)
|
||||
buf[i] = theregs[i];
|
||||
buf[i] = gfar_read(&theregs[i]);
|
||||
}
|
||||
|
||||
/* Convert microseconds to ethernet clock ticks, which changes
|
||||
|
@ -50,7 +50,7 @@
|
||||
* All PHY configuration is done through the TSEC1 MIIM regs */
|
||||
int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
|
||||
{
|
||||
struct gfar_mii *regs = bus->priv;
|
||||
struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
|
||||
|
||||
/* Set the PHY address and the register address we want to write */
|
||||
gfar_write(®s->miimadd, (mii_id << 8) | regnum);
|
||||
@ -70,7 +70,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
|
||||
* configuration has to be done through the TSEC1 MIIM regs */
|
||||
int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||
{
|
||||
struct gfar_mii *regs = bus->priv;
|
||||
struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
|
||||
u16 value;
|
||||
|
||||
/* Set the PHY address and the register address we want to read */
|
||||
@ -94,7 +94,7 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||
/* Reset the MIIM registers, and wait for the bus to free */
|
||||
int gfar_mdio_reset(struct mii_bus *bus)
|
||||
{
|
||||
struct gfar_mii *regs = bus->priv;
|
||||
struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
|
||||
unsigned int timeout = PHY_INIT_TIMEOUT;
|
||||
|
||||
spin_lock_bh(&bus->mdio_lock);
|
||||
@ -126,7 +126,7 @@ int gfar_mdio_probe(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct gianfar_mdio_data *pdata;
|
||||
struct gfar_mii *regs;
|
||||
struct gfar_mii __iomem *regs;
|
||||
struct mii_bus *new_bus;
|
||||
struct resource *r;
|
||||
int err = 0;
|
||||
@ -155,15 +155,14 @@ int gfar_mdio_probe(struct device *dev)
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
/* Set the PHY base address */
|
||||
regs = (struct gfar_mii *) ioremap(r->start,
|
||||
sizeof (struct gfar_mii));
|
||||
regs = ioremap(r->start, sizeof (struct gfar_mii));
|
||||
|
||||
if (NULL == regs) {
|
||||
err = -ENOMEM;
|
||||
goto reg_map_fail;
|
||||
}
|
||||
|
||||
new_bus->priv = regs;
|
||||
new_bus->priv = (void __force *)regs;
|
||||
|
||||
new_bus->irq = pdata->irq;
|
||||
|
||||
@ -181,7 +180,7 @@ int gfar_mdio_probe(struct device *dev)
|
||||
return 0;
|
||||
|
||||
bus_register_fail:
|
||||
iounmap((void *) regs);
|
||||
iounmap(regs);
|
||||
reg_map_fail:
|
||||
kfree(new_bus);
|
||||
|
||||
@ -197,7 +196,7 @@ int gfar_mdio_remove(struct device *dev)
|
||||
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
iounmap((void *) (&bus->priv));
|
||||
iounmap((void __iomem *)bus->priv);
|
||||
bus->priv = NULL;
|
||||
kfree(bus);
|
||||
|
||||
|
@ -484,13 +484,12 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
|
||||
int i;
|
||||
|
||||
RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
|
||||
udelay(1000);
|
||||
|
||||
for (i = 2000; i > 0; i--) {
|
||||
for (i = 20; i > 0; i--) {
|
||||
/* Check if the RTL8169 has completed writing to the specified MII register */
|
||||
if (!(RTL_R32(PHYAR) & 0x80000000))
|
||||
break;
|
||||
udelay(100);
|
||||
udelay(25);
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,15 +498,14 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr)
|
||||
int i, value = -1;
|
||||
|
||||
RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
|
||||
udelay(1000);
|
||||
|
||||
for (i = 2000; i > 0; i--) {
|
||||
for (i = 20; i > 0; i--) {
|
||||
/* Check if the RTL8169 has completed retrieving data from the specified MII register */
|
||||
if (RTL_R32(PHYAR) & 0x80000000) {
|
||||
value = (int) (RTL_R32(PHYAR) & 0xFFFF);
|
||||
break;
|
||||
}
|
||||
udelay(100);
|
||||
udelay(25);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@ -677,6 +675,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
|
||||
|
||||
if (duplex == DUPLEX_HALF)
|
||||
auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
|
||||
|
||||
if (duplex == DUPLEX_FULL)
|
||||
auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half);
|
||||
}
|
||||
|
||||
tp->phy_auto_nego_reg = auto_nego;
|
||||
|
@ -33,7 +33,6 @@ enum sis900_registers {
|
||||
rxcfg=0x34, //Receive Configuration Register
|
||||
flctrl=0x38, //Flow Control Register
|
||||
rxlen=0x3c, //Receive Packet Length Register
|
||||
cfgpmcsr=0x44, //Configuration Power Management Control/Status Register
|
||||
rfcr=0x48, //Receive Filter Control Register
|
||||
rfdr=0x4C, //Receive Filter Data Register
|
||||
pmctrl=0xB0, //Power Management Control Register
|
||||
|
@ -23,12 +23,6 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TOTEST
|
||||
* - speed setting
|
||||
* - suspend/resume
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -57,7 +51,7 @@
|
||||
#include "sky2.h"
|
||||
|
||||
#define DRV_NAME "sky2"
|
||||
#define DRV_VERSION "0.13"
|
||||
#define DRV_VERSION "0.15"
|
||||
#define PFX DRV_NAME " "
|
||||
|
||||
/*
|
||||
@ -102,6 +96,10 @@ static int copybreak __read_mostly = 256;
|
||||
module_param(copybreak, int, 0);
|
||||
MODULE_PARM_DESC(copybreak, "Receive copy threshold");
|
||||
|
||||
static int disable_msi = 0;
|
||||
module_param(disable_msi, int, 0);
|
||||
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
|
||||
|
||||
static const struct pci_device_id sky2_id_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
|
||||
@ -198,7 +196,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
|
||||
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
|
||||
|
||||
pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control);
|
||||
vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
|
||||
vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
|
||||
(power_control & PCI_PM_CAP_PME_D3cold);
|
||||
|
||||
pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control);
|
||||
@ -1834,6 +1832,8 @@ static int sky2_poll(struct net_device *dev0, int *budget)
|
||||
u16 hwidx;
|
||||
u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS };
|
||||
|
||||
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
|
||||
|
||||
hwidx = sky2_read16(hw, STAT_PUT_IDX);
|
||||
BUG_ON(hwidx >= STATUS_RING_SIZE);
|
||||
rmb();
|
||||
@ -1913,12 +1913,10 @@ static int sky2_poll(struct net_device *dev0, int *budget)
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
|
||||
|
||||
sky2_tx_check(hw, 0, tx_done[0]);
|
||||
sky2_tx_check(hw, 1, tx_done[1]);
|
||||
|
||||
if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) {
|
||||
if (likely(work_done < to_do)) {
|
||||
/* need to restart TX timer */
|
||||
if (is_ec_a1(hw)) {
|
||||
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
|
||||
@ -2141,14 +2139,12 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
|
||||
|
||||
static int sky2_reset(struct sky2_hw *hw)
|
||||
{
|
||||
u32 ctst;
|
||||
u16 status;
|
||||
u8 t8, pmd_type;
|
||||
int i;
|
||||
|
||||
ctst = sky2_read32(hw, B0_CTST);
|
||||
int i, err;
|
||||
|
||||
sky2_write8(hw, B0_CTST, CS_RST_CLR);
|
||||
|
||||
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
|
||||
if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
|
||||
printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n",
|
||||
@ -2156,12 +2152,6 @@ static int sky2_reset(struct sky2_hw *hw)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* ring for status responses */
|
||||
hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
|
||||
&hw->st_dma);
|
||||
if (!hw->st_le)
|
||||
return -ENOMEM;
|
||||
|
||||
/* disable ASF */
|
||||
if (hw->chip_id <= CHIP_ID_YUKON_EC) {
|
||||
sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
|
||||
@ -2173,19 +2163,24 @@ static int sky2_reset(struct sky2_hw *hw)
|
||||
sky2_write8(hw, B0_CTST, CS_RST_CLR);
|
||||
|
||||
/* clear PCI errors, if any */
|
||||
pci_read_config_word(hw->pdev, PCI_STATUS, &status);
|
||||
err = pci_read_config_word(hw->pdev, PCI_STATUS, &status);
|
||||
if (err)
|
||||
goto pci_err;
|
||||
|
||||
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
|
||||
pci_write_config_word(hw->pdev, PCI_STATUS,
|
||||
status | PCI_STATUS_ERROR_BITS);
|
||||
err = pci_write_config_word(hw->pdev, PCI_STATUS,
|
||||
status | PCI_STATUS_ERROR_BITS);
|
||||
if (err)
|
||||
goto pci_err;
|
||||
|
||||
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
|
||||
|
||||
/* clear any PEX errors */
|
||||
if (is_pciex(hw)) {
|
||||
u16 lstat;
|
||||
pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
|
||||
0xffffffffUL);
|
||||
pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat);
|
||||
if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) {
|
||||
err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
|
||||
0xffffffffUL);
|
||||
if (err)
|
||||
goto pci_err;
|
||||
}
|
||||
|
||||
pmd_type = sky2_read8(hw, B2_PMD_TYP);
|
||||
@ -2297,6 +2292,14 @@ static int sky2_reset(struct sky2_hw *hw)
|
||||
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
|
||||
|
||||
return 0;
|
||||
|
||||
pci_err:
|
||||
/* This is to catch a BIOS bug workaround where
|
||||
* mmconfig table doesn't have other buses.
|
||||
*/
|
||||
printk(KERN_ERR PFX "%s: can't access PCI config space\n",
|
||||
pci_name(hw->pdev));
|
||||
return err;
|
||||
}
|
||||
|
||||
static u32 sky2_supported_modes(const struct sky2_hw *hw)
|
||||
@ -2551,19 +2554,24 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev)
|
||||
static int sky2_set_mac_address(struct net_device *dev, void *p)
|
||||
{
|
||||
struct sky2_port *sky2 = netdev_priv(dev);
|
||||
struct sockaddr *addr = p;
|
||||
struct sky2_hw *hw = sky2->hw;
|
||||
unsigned port = sky2->port;
|
||||
const struct sockaddr *addr = p;
|
||||
|
||||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
||||
memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8,
|
||||
memcpy_toio(hw->regs + B2_MAC_1 + port * 8,
|
||||
dev->dev_addr, ETH_ALEN);
|
||||
memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8,
|
||||
memcpy_toio(hw->regs + B2_MAC_2 + port * 8,
|
||||
dev->dev_addr, ETH_ALEN);
|
||||
|
||||
if (netif_running(dev))
|
||||
sky2_phy_reinit(sky2);
|
||||
/* virtual address for data */
|
||||
gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
|
||||
|
||||
/* physical address: used for pause frames */
|
||||
gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2843,7 +2851,7 @@ static int sky2_set_coalesce(struct net_device *dev,
|
||||
if (ecmd->rx_coalesce_usecs_irq == 0)
|
||||
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP);
|
||||
else {
|
||||
sky2_write32(hw, STAT_TX_TIMER_INI,
|
||||
sky2_write32(hw, STAT_ISR_TIMER_INI,
|
||||
sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq));
|
||||
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
|
||||
}
|
||||
@ -3055,6 +3063,61 @@ static void __devinit sky2_show_addr(struct net_device *dev)
|
||||
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
|
||||
}
|
||||
|
||||
/* Handle software interrupt used during MSI test */
|
||||
static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct sky2_hw *hw = dev_id;
|
||||
u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
|
||||
|
||||
if (status == 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (status & Y2_IS_IRQ_SW) {
|
||||
sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
|
||||
hw->msi = 1;
|
||||
}
|
||||
sky2_write32(hw, B0_Y2_SP_ICR, 2);
|
||||
|
||||
sky2_read32(hw, B0_IMSK);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Test interrupt path by forcing a a software IRQ */
|
||||
static int __devinit sky2_test_msi(struct sky2_hw *hw)
|
||||
{
|
||||
struct pci_dev *pdev = hw->pdev;
|
||||
int i, err;
|
||||
|
||||
sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
|
||||
|
||||
err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
|
||||
pci_name(pdev), pdev->irq);
|
||||
return err;
|
||||
}
|
||||
|
||||
sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
|
||||
wmb();
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
barrier();
|
||||
if (hw->msi)
|
||||
goto found;
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
err = -EOPNOTSUPP;
|
||||
sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
|
||||
found:
|
||||
sky2_write32(hw, B0_IMSK, 0);
|
||||
|
||||
free_irq(pdev->irq, hw);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devinit sky2_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
@ -3135,6 +3198,12 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
|
||||
}
|
||||
hw->pm_cap = pm_cap;
|
||||
|
||||
/* ring for status responses */
|
||||
hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
|
||||
&hw->st_dma);
|
||||
if (!hw->st_le)
|
||||
goto err_out_iounmap;
|
||||
|
||||
err = sky2_reset(hw);
|
||||
if (err)
|
||||
goto err_out_iounmap;
|
||||
@ -3169,7 +3238,22 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
|
||||
}
|
||||
}
|
||||
|
||||
err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw);
|
||||
if (!disable_msi && pci_enable_msi(pdev) == 0) {
|
||||
err = sky2_test_msi(hw);
|
||||
if (err == -EOPNOTSUPP) {
|
||||
/* MSI test failed, go back to INTx mode */
|
||||
printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, "
|
||||
"switching to INTx mode. Please report this failure to "
|
||||
"the PCI maintainer and include system chipset information.\n",
|
||||
pci_name(pdev));
|
||||
pci_disable_msi(pdev);
|
||||
}
|
||||
else if (err)
|
||||
goto err_out_unregister;
|
||||
}
|
||||
|
||||
err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
|
||||
DRV_NAME, hw);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
|
||||
pci_name(pdev), pdev->irq);
|
||||
@ -3184,6 +3268,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
|
||||
return 0;
|
||||
|
||||
err_out_unregister:
|
||||
if (hw->msi)
|
||||
pci_disable_msi(pdev);
|
||||
if (dev1) {
|
||||
unregister_netdev(dev1);
|
||||
free_netdev(dev1);
|
||||
@ -3226,6 +3312,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
|
||||
sky2_read8(hw, B0_CTST);
|
||||
|
||||
free_irq(pdev->irq, hw);
|
||||
if (hw->msi)
|
||||
pci_disable_msi(pdev);
|
||||
pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
@ -3263,25 +3351,33 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
static int sky2_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct sky2_hw *hw = pci_get_drvdata(pdev);
|
||||
int i;
|
||||
int i, err;
|
||||
|
||||
pci_restore_state(pdev);
|
||||
pci_enable_wake(pdev, PCI_D0, 0);
|
||||
sky2_set_power_state(hw, PCI_D0);
|
||||
err = sky2_set_power_state(hw, PCI_D0);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
sky2_reset(hw);
|
||||
err = sky2_reset(hw);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct net_device *dev = hw->dev[i];
|
||||
if (dev) {
|
||||
if (netif_running(dev)) {
|
||||
netif_device_attach(dev);
|
||||
if (sky2_up(dev))
|
||||
dev_close(dev);
|
||||
if (dev && netif_running(dev)) {
|
||||
netif_device_attach(dev);
|
||||
err = sky2_up(dev);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "%s: could not up: %d\n",
|
||||
dev->name, err);
|
||||
dev_close(dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1841,6 +1841,7 @@ struct sky2_hw {
|
||||
struct net_device *dev[2];
|
||||
|
||||
int pm_cap;
|
||||
int msi;
|
||||
u8 chip_id;
|
||||
u8 chip_rev;
|
||||
u8 copper;
|
||||
@ -1867,14 +1868,6 @@ static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg)
|
||||
return readb(hw->regs + reg);
|
||||
}
|
||||
|
||||
/* This should probably go away, bus based tweeks suck */
|
||||
static inline int is_pciex(const struct sky2_hw *hw)
|
||||
{
|
||||
u32 status;
|
||||
pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status);
|
||||
return (status & PCI_OS_PCI_X) == 0;
|
||||
}
|
||||
|
||||
static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val)
|
||||
{
|
||||
writel(val, hw->regs + reg);
|
||||
|
@ -1943,7 +1943,7 @@ static int dscc4_init_ring(struct net_device *dev)
|
||||
(++i%TX_RING_SIZE)*sizeof(*tx_fd));
|
||||
} while (i < TX_RING_SIZE);
|
||||
|
||||
if (dscc4_init_dummy_skb(dpriv) < 0)
|
||||
if (!dscc4_init_dummy_skb(dpriv))
|
||||
goto err_free_dma_tx;
|
||||
|
||||
memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE);
|
||||
|
Loading…
Reference in New Issue
Block a user