aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/sis/sis900.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/sis/sis900.c')
-rw-r--r--drivers/net/ethernet/sis/sis900.c79
1 files changed, 43 insertions, 36 deletions
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index efca14eaefa..6072f093e6b 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -576,7 +576,6 @@ err_unmap_tx:
err_out_unmap:
pci_iounmap(pci_dev, ioaddr);
err_out_cleardev:
- pci_set_drvdata(pci_dev, NULL);
pci_release_regions(pci_dev);
err_out:
free_netdev(net_dev);
@@ -1187,8 +1186,14 @@ sis900_init_rx_ring(struct net_device *net_dev)
}
sis_priv->rx_skbuff[i] = skb;
sis_priv->rx_ring[i].cmdsts = RX_BUF_SIZE;
- sis_priv->rx_ring[i].bufptr = pci_map_single(sis_priv->pci_dev,
- skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ sis_priv->rx_ring[i].bufptr = pci_map_single(sis_priv->pci_dev,
+ skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(sis_priv->pci_dev,
+ sis_priv->rx_ring[i].bufptr))) {
+ dev_kfree_skb(skb);
+ sis_priv->rx_skbuff[i] = NULL;
+ break;
+ }
}
sis_priv->dirty_rx = (unsigned int) (i - NUM_RX_DESC);
@@ -1303,23 +1308,9 @@ static void sis900_timer(unsigned long data)
struct sis900_private *sis_priv = netdev_priv(net_dev);
struct mii_phy *mii_phy = sis_priv->mii;
static const int next_tick = 5*HZ;
+ int speed = 0, duplex = 0;
u16 status;
- if (!sis_priv->autong_complete){
- int uninitialized_var(speed), duplex = 0;
-
- sis900_read_mode(net_dev, &speed, &duplex);
- if (duplex){
- sis900_set_mode(sis_priv, speed, duplex);
- sis630_set_eq(net_dev, sis_priv->chipset_rev);
- netif_start_queue(net_dev);
- }
-
- sis_priv->timer.expires = jiffies + HZ;
- add_timer(&sis_priv->timer);
- return;
- }
-
status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);
status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);
@@ -1330,9 +1321,15 @@ static void sis900_timer(unsigned long data)
status = sis900_default_phy(net_dev);
mii_phy = sis_priv->mii;
- if (status & MII_STAT_LINK){
- sis900_check_mode(net_dev, mii_phy);
- netif_carrier_on(net_dev);
+ if (status & MII_STAT_LINK) {
+ WARN_ON(!(status & MII_STAT_AUTO_DONE));
+
+ sis900_read_mode(net_dev, &speed, &duplex);
+ if (duplex) {
+ sis900_set_mode(sis_priv, speed, duplex);
+ sis630_set_eq(net_dev, sis_priv->chipset_rev);
+ netif_carrier_on(net_dev);
+ }
}
} else {
/* Link ON -> OFF */
@@ -1606,12 +1603,6 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
unsigned int index_cur_tx, index_dirty_tx;
unsigned int count_dirty_tx;
- /* Don't transmit data before the complete of auto-negotiation */
- if(!sis_priv->autong_complete){
- netif_stop_queue(net_dev);
- return NETDEV_TX_BUSY;
- }
-
spin_lock_irqsave(&sis_priv->lock, flags);
/* Calculate the next Tx descriptor entry. */
@@ -1621,6 +1612,14 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
/* set the transmit buffer descriptor and enable Transmit State Machine */
sis_priv->tx_ring[entry].bufptr = pci_map_single(sis_priv->pci_dev,
skb->data, skb->len, PCI_DMA_TODEVICE);
+ if (unlikely(pci_dma_mapping_error(sis_priv->pci_dev,
+ sis_priv->tx_ring[entry].bufptr))) {
+ dev_kfree_skb_any(skb);
+ sis_priv->tx_skbuff[entry] = NULL;
+ net_dev->stats.tx_dropped++;
+ spin_unlock_irqrestore(&sis_priv->lock, flags);
+ return NETDEV_TX_OK;
+ }
sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len);
sw32(cr, TxENA | sr32(cr));
@@ -1709,7 +1708,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
if(netif_msg_intr(sis_priv))
printk(KERN_DEBUG "%s: exiting interrupt, "
- "interrupt status = 0x%#8.8x.\n",
+ "interrupt status = %#8.8x\n",
net_dev->name, sr32(isr));
spin_unlock (&sis_priv->lock);
@@ -1824,9 +1823,15 @@ static int sis900_rx(struct net_device *net_dev)
refill_rx_ring:
sis_priv->rx_skbuff[entry] = skb;
sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
- sis_priv->rx_ring[entry].bufptr =
+ sis_priv->rx_ring[entry].bufptr =
pci_map_single(sis_priv->pci_dev, skb->data,
RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(sis_priv->pci_dev,
+ sis_priv->rx_ring[entry].bufptr))) {
+ dev_kfree_skb_irq(skb);
+ sis_priv->rx_skbuff[entry] = NULL;
+ break;
+ }
}
sis_priv->cur_rx++;
entry = sis_priv->cur_rx % NUM_RX_DESC;
@@ -1841,23 +1846,26 @@ refill_rx_ring:
entry = sis_priv->dirty_rx % NUM_RX_DESC;
if (sis_priv->rx_skbuff[entry] == NULL) {
- if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) {
+ skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE);
+ if (skb == NULL) {
/* not enough memory for skbuff, this makes a
* "hole" on the buffer ring, it is not clear
* how the hardware will react to this kind
* of degenerated buffer */
- if (netif_msg_rx_err(sis_priv))
- printk(KERN_INFO "%s: Memory squeeze, "
- "deferring packet.\n",
- net_dev->name);
net_dev->stats.rx_dropped++;
break;
}
sis_priv->rx_skbuff[entry] = skb;
sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
- sis_priv->rx_ring[entry].bufptr =
+ sis_priv->rx_ring[entry].bufptr =
pci_map_single(sis_priv->pci_dev, skb->data,
RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(sis_priv->pci_dev,
+ sis_priv->rx_ring[entry].bufptr))) {
+ dev_kfree_skb_irq(skb);
+ sis_priv->rx_skbuff[entry] = NULL;
+ break;
+ }
}
}
/* re-enable the potentially idle receive state matchine */
@@ -2418,7 +2426,6 @@ static void sis900_remove(struct pci_dev *pci_dev)
pci_iounmap(pci_dev, sis_priv->ioaddr);
free_netdev(net_dev);
pci_release_regions(pci_dev);
- pci_set_drvdata(pci_dev, NULL);
}
#ifdef CONFIG_PM