pch_gbe: Do not abort probe on bad MAC
[linux-flexiantxendom0.git] / drivers / net / ethernet / oki-semi / pch_gbe / pch_gbe_main.c
index 5dc61b4..43c7b25 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "pch_gbe.h"
 #include "pch_gbe_api.h"
+#include <linux/module.h>
 
 #define DRV_VERSION     "1.00"
 const char pch_driver_version[] = DRV_VERSION;
@@ -1198,6 +1199,8 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)
                        iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR),
                                  &hw->reg->INT_EN);
                        pch_gbe_stop_receive(adapter);
+                       int_st |= ioread32(&hw->reg->INT_ST);
+                       int_st = int_st & ioread32(&hw->reg->INT_EN);
                }
        if (int_st & PCH_GBE_INT_RX_DMA_ERR)
                adapter->stats.intr_rx_dma_err_count++;
@@ -1217,14 +1220,11 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)
                        /* Set Pause packet */
                        pch_gbe_mac_set_pause_packet(hw);
                }
-               if ((int_en & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT))
-                   == 0) {
-                       return IRQ_HANDLED;
-               }
        }
 
        /* When request status is Receive interruption */
-       if ((int_st & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT))) {
+       if ((int_st & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT)) ||
+           (adapter->rx_stop_flag == true)) {
                if (likely(napi_schedule_prep(&adapter->napi))) {
                        /* Enable only Rx Descriptor empty */
                        atomic_inc(&adapter->irq_sem);
@@ -1384,7 +1384,7 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter,
        struct sk_buff *skb;
        unsigned int i;
        unsigned int cleaned_count = 0;
-       bool cleaned = false;
+       bool cleaned = true;
 
        pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
 
@@ -1395,7 +1395,6 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter,
 
        while ((tx_desc->gbec_status & DSC_INIT16) == 0x0000) {
                pr_debug("gbec_status:0x%04x\n", tx_desc->gbec_status);
-               cleaned = true;
                buffer_info = &tx_ring->buffer_info[i];
                skb = buffer_info->skb;
 
@@ -1438,8 +1437,10 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter,
                tx_desc = PCH_GBE_TX_DESC(*tx_ring, i);
 
                /* weight of a sort for tx, to avoid endless transmit cleanup */
-               if (cleaned_count++ == PCH_GBE_TX_WEIGHT)
+               if (cleaned_count++ == PCH_GBE_TX_WEIGHT) {
+                       cleaned = false;
                        break;
+               }
        }
        pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n",
                 cleaned_count);
@@ -1744,6 +1745,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
        int err;
 
+       /* Ensure we have a valid MAC */
+       if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
+               pr_err("Error: Invalid MAC address\n");
+               return -EINVAL;
+       }
+
        /* hardware has been reset, we need to reload some things */
        pch_gbe_set_multi(netdev);
 
@@ -2167,7 +2174,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
 {
        struct pch_gbe_adapter *adapter =
            container_of(napi, struct pch_gbe_adapter, napi);
-       struct net_device *netdev = adapter->netdev;
        int work_done = 0;
        bool poll_end_flag = false;
        bool cleaned = false;
@@ -2175,33 +2181,32 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
 
        pr_debug("budget : %d\n", budget);
 
-       /* Keep link state information with original netdev */
-       if (!netif_carrier_ok(netdev)) {
+       pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget);
+       cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring);
+
+       if (!cleaned)
+               work_done = budget;
+       /* If no Tx and not enough Rx work done,
+        * exit the polling mode
+        */
+       if (work_done < budget)
                poll_end_flag = true;
-       } else {
-               pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget);
+
+       if (poll_end_flag) {
+               napi_complete(napi);
+               if (adapter->rx_stop_flag) {
+                       adapter->rx_stop_flag = false;
+                       pch_gbe_start_receive(&adapter->hw);
+               }
+               pch_gbe_irq_enable(adapter);
+       } else
                if (adapter->rx_stop_flag) {
                        adapter->rx_stop_flag = false;
                        pch_gbe_start_receive(&adapter->hw);
                        int_en = ioread32(&adapter->hw.reg->INT_EN);
                        iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR),
-                                       &adapter->hw.reg->INT_EN);
+                               &adapter->hw.reg->INT_EN);
                }
-               cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring);
-
-               if (cleaned)
-                       work_done = budget;
-               /* If no Tx and not enough Rx work done,
-                * exit the polling mode
-                */
-               if ((work_done < budget) || !netif_running(netdev))
-                       poll_end_flag = true;
-       }
-
-       if (poll_end_flag) {
-               napi_complete(napi);
-               pch_gbe_irq_enable(adapter);
-       }
 
        pr_debug("poll_end_flag : %d  work_done : %d  budget : %d\n",
                 poll_end_flag, work_done, budget);
@@ -2468,9 +2473,14 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 
        memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
        if (!is_valid_ether_addr(netdev->dev_addr)) {
-               dev_err(&pdev->dev, "Invalid MAC Address\n");
-               ret = -EIO;
-               goto err_free_adapter;
+               /*
+                * If the MAC is invalid (or just missing), display a warning
+                * but do not abort setting up the device. pch_gbe_up will
+                * prevent the interface from being brought up until a valid MAC
+                * is set.
+                */
+               dev_err(&pdev->dev, "Invalid MAC address, "
+                                   "interface disabled.\n");
        }
        setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog,
                    (unsigned long)adapter);