]> Pileus Git - ~andy/linux/blobdiff - drivers/net/sis190.c
ath5k: Use high bitrates for ACK/CTS
[~andy/linux] / drivers / net / sis190.c
index 4487b065ef727b6e85350c3b516f6780c86cb082..760d9e83a46514fb603d97e7d1abdf667968a86f 100644 (file)
@@ -285,6 +285,11 @@ struct sis190_private {
        struct list_head first_phy;
        u32 features;
        u32 negotiated_lpa;
+       enum {
+               LNK_OFF,
+               LNK_ON,
+               LNK_AUTONEG,
+       } link_status;
 };
 
 struct sis190_phy {
@@ -484,18 +489,24 @@ static struct sk_buff *sis190_alloc_rx_skb(struct sis190_private *tp,
 {
        u32 rx_buf_sz = tp->rx_buf_sz;
        struct sk_buff *skb;
+       dma_addr_t mapping;
 
        skb = netdev_alloc_skb(tp->dev, rx_buf_sz);
-       if (likely(skb)) {
-               dma_addr_t mapping;
-
-               mapping = pci_map_single(tp->pci_dev, skb->data, tp->rx_buf_sz,
-                                        PCI_DMA_FROMDEVICE);
-               sis190_map_to_asic(desc, mapping, rx_buf_sz);
-       } else
-               sis190_make_unusable_by_asic(desc);
+       if (unlikely(!skb))
+               goto skb_alloc_failed;
+       mapping = pci_map_single(tp->pci_dev, skb->data, tp->rx_buf_sz,
+                       PCI_DMA_FROMDEVICE);
+       if (pci_dma_mapping_error(tp->pci_dev, mapping))
+               goto out;
+       sis190_map_to_asic(desc, mapping, rx_buf_sz);
 
        return skb;
+
+out:
+       dev_kfree_skb_any(skb);
+skb_alloc_failed:
+       sis190_make_unusable_by_asic(desc);
+       return NULL;
 }
 
 static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
@@ -744,6 +755,7 @@ static irqreturn_t sis190_interrupt(int irq, void *__dev)
 
        if (status & LinkChange) {
                netif_info(tp, intr, dev, "link change\n");
+               del_timer(&tp->timer);
                schedule_work(&tp->phy_task);
        }
 
@@ -916,12 +928,15 @@ static void sis190_phy_task(struct work_struct *work)
        if (val & BMCR_RESET) {
                // FIXME: needlessly high ?  -- FR 02/07/2005
                mod_timer(&tp->timer, jiffies + HZ/10);
-       } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) &
-                    BMSR_ANEGCOMPLETE)) {
+               goto out_unlock;
+       }
+
+       val = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
+       if (!(val & BMSR_ANEGCOMPLETE) && tp->link_status != LNK_AUTONEG) {
                netif_carrier_off(dev);
                netif_warn(tp, link, dev, "auto-negotiating...\n");
-               mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
-       } else {
+               tp->link_status = LNK_AUTONEG;
+       } else if ((val & BMSR_LSTATUS) && tp->link_status != LNK_ON) {
                /* Rejoice ! */
                struct {
                        int val;
@@ -994,7 +1009,10 @@ static void sis190_phy_task(struct work_struct *work)
 
                netif_info(tp, link, dev, "link on %s mode\n", p->msg);
                netif_carrier_on(dev);
-       }
+               tp->link_status = LNK_ON;
+       } else if (!(val & BMSR_LSTATUS) && tp->link_status != LNK_AUTONEG)
+               tp->link_status = LNK_OFF;
+       mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
 
 out_unlock:
        rtnl_unlock();
@@ -1184,6 +1202,11 @@ static netdev_tx_t sis190_start_xmit(struct sk_buff *skb,
        }
 
        mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(tp->pci_dev, mapping)) {
+               netif_err(tp, tx_err, dev,
+                               "PCI mapping failed, dropping packet");
+               return NETDEV_TX_BUSY;
+       }
 
        tp->Tx_skbuff[entry] = skb;
 
@@ -1502,6 +1525,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
 
        tp->pci_dev = pdev;
        tp->mmio_addr = ioaddr;
+       tp->link_status = LNK_OFF;
 
        sis190_irq_mask_and_ack(ioaddr);