Merge 3.17-rc3 into staging-next
[deliverable/linux.git] / drivers / staging / et131x / et131x.c
index 831b7c6fe4948074f26604083f350e33d54a5edb..52abe33f83c5cdfa12a5a51c3f058138e2f0c835 100644 (file)
@@ -179,7 +179,7 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere S
 #define NIC_DEFAULT_NUM_RFD    1024
 #define NUM_FBRS               2
 
-#define NUM_PACKETS_HANDLED    256
+#define MAX_PACKETS_HANDLED    256
 
 #define ALCATEL_MULTICAST_PKT  0x01000000
 #define ALCATEL_BROADCAST_PKT  0x02000000
@@ -470,7 +470,7 @@ struct et131x_adapter {
        struct pci_dev *pdev;
        struct mii_bus *mii_bus;
        struct phy_device *phydev;
-       struct work_struct task;
+       struct napi_struct napi;
 
        /* Flags that indicate current state of the adapter */
        u32 flags;
@@ -573,7 +573,6 @@ static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data)
        int index = 0;
        int retries;
        int err = 0;
-       int i2c_wack = 0;
        int writeok = 0;
        u32 status;
        u32 val = 0;
@@ -599,8 +598,6 @@ static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data)
                        LBCIF_CONTROL_LBCIF_ENABLE | LBCIF_CONTROL_I2C_WRITE))
                return -EIO;
 
-       i2c_wack = 1;
-
        /* Prepare EEPROM address for Step 3 */
 
        for (retries = 0; retries < MAX_NUM_WRITE_RETRIES; retries++) {
@@ -656,7 +653,7 @@ static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data)
         */
        udelay(10);
 
-       while (i2c_wack) {
+       while (1) {
                if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER,
                        LBCIF_CONTROL_LBCIF_ENABLE))
                        writeok = 0;
@@ -1138,6 +1135,7 @@ static void et1310_config_rxmac_regs(struct et131x_adapter *adapter)
        u32 sa_lo;
        u32 sa_hi = 0;
        u32 pf_ctrl = 0;
+       u32 *wolw;
 
        /* Disable the MAC while it is being configured (also disable WOL) */
        writel(0x8, &rxmac->ctrl);
@@ -1151,30 +1149,8 @@ static void et1310_config_rxmac_regs(struct et131x_adapter *adapter)
         * its default Values of 0x00000000 because there are not WOL masks
         * as of this time.
         */
-       writel(0, &rxmac->mask0_word0);
-       writel(0, &rxmac->mask0_word1);
-       writel(0, &rxmac->mask0_word2);
-       writel(0, &rxmac->mask0_word3);
-
-       writel(0, &rxmac->mask1_word0);
-       writel(0, &rxmac->mask1_word1);
-       writel(0, &rxmac->mask1_word2);
-       writel(0, &rxmac->mask1_word3);
-
-       writel(0, &rxmac->mask2_word0);
-       writel(0, &rxmac->mask2_word1);
-       writel(0, &rxmac->mask2_word2);
-       writel(0, &rxmac->mask2_word3);
-
-       writel(0, &rxmac->mask3_word0);
-       writel(0, &rxmac->mask3_word1);
-       writel(0, &rxmac->mask3_word2);
-       writel(0, &rxmac->mask3_word3);
-
-       writel(0, &rxmac->mask4_word0);
-       writel(0, &rxmac->mask4_word1);
-       writel(0, &rxmac->mask4_word2);
-       writel(0, &rxmac->mask4_word3);
+       for (wolw = &rxmac->mask0_word0; wolw <= &rxmac->mask4_word3; wolw++)
+               writel(0, wolw);
 
        /* Lets setup the WOL Source Address */
        sa_lo = (adapter->addr[2] << ET_RX_WOL_LO_SA3_SHIFT) |
@@ -1278,60 +1254,13 @@ static void et1310_config_txmac_regs(struct et131x_adapter *adapter)
 
 static void et1310_config_macstat_regs(struct et131x_adapter *adapter)
 {
-       struct macstat_regs __iomem *macstat =
-               &adapter->regs->macstat;
+       struct macstat_regs __iomem *macstat = &adapter->regs->macstat;
+       u32 *reg;
 
-       /* Next we need to initialize all the macstat registers to zero on
-        * the device.
-        */
-       writel(0, &macstat->txrx_0_64_byte_frames);
-       writel(0, &macstat->txrx_65_127_byte_frames);
-       writel(0, &macstat->txrx_128_255_byte_frames);
-       writel(0, &macstat->txrx_256_511_byte_frames);
-       writel(0, &macstat->txrx_512_1023_byte_frames);
-       writel(0, &macstat->txrx_1024_1518_byte_frames);
-       writel(0, &macstat->txrx_1519_1522_gvln_frames);
-
-       writel(0, &macstat->rx_bytes);
-       writel(0, &macstat->rx_packets);
-       writel(0, &macstat->rx_fcs_errs);
-       writel(0, &macstat->rx_multicast_packets);
-       writel(0, &macstat->rx_broadcast_packets);
-       writel(0, &macstat->rx_control_frames);
-       writel(0, &macstat->rx_pause_frames);
-       writel(0, &macstat->rx_unknown_opcodes);
-       writel(0, &macstat->rx_align_errs);
-       writel(0, &macstat->rx_frame_len_errs);
-       writel(0, &macstat->rx_code_errs);
-       writel(0, &macstat->rx_carrier_sense_errs);
-       writel(0, &macstat->rx_undersize_packets);
-       writel(0, &macstat->rx_oversize_packets);
-       writel(0, &macstat->rx_fragment_packets);
-       writel(0, &macstat->rx_jabbers);
-       writel(0, &macstat->rx_drops);
-
-       writel(0, &macstat->tx_bytes);
-       writel(0, &macstat->tx_packets);
-       writel(0, &macstat->tx_multicast_packets);
-       writel(0, &macstat->tx_broadcast_packets);
-       writel(0, &macstat->tx_pause_frames);
-       writel(0, &macstat->tx_deferred);
-       writel(0, &macstat->tx_excessive_deferred);
-       writel(0, &macstat->tx_single_collisions);
-       writel(0, &macstat->tx_multiple_collisions);
-       writel(0, &macstat->tx_late_collisions);
-       writel(0, &macstat->tx_excessive_collisions);
-       writel(0, &macstat->tx_total_collisions);
-       writel(0, &macstat->tx_pause_honored_frames);
-       writel(0, &macstat->tx_drops);
-       writel(0, &macstat->tx_jabbers);
-       writel(0, &macstat->tx_fcs_errs);
-       writel(0, &macstat->tx_control_frames);
-       writel(0, &macstat->tx_oversize_frames);
-       writel(0, &macstat->tx_undersize_frames);
-       writel(0, &macstat->tx_fragments);
-       writel(0, &macstat->carry_reg1);
-       writel(0, &macstat->carry_reg2);
+       /* initialize all the macstat registers to zero on the device  */
+       for (reg = &macstat->txrx_0_64_byte_frames;
+            reg <= &macstat->carry_reg2; reg++)
+               writel(0, reg);
 
        /* Unmask any counters that we want to track the overflow of.
         * Initially this will be all counters.  It may become clear later
@@ -2608,26 +2537,30 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter)
 
        skb->protocol = eth_type_trans(skb, adapter->netdev);
        skb->ip_summed = CHECKSUM_NONE;
-       netif_rx_ni(skb);
+       netif_receive_skb(skb);
 
 out:
        nic_return_rfd(adapter, rfd);
        return rfd;
 }
 
-/* et131x_handle_recv_interrupt - Interrupt handler for receive processing
+/* et131x_handle_recv_pkts - Interrupt handler for receive processing
  *
  * Assumption, Rcv spinlock has been acquired.
  */
-static void et131x_handle_recv_interrupt(struct et131x_adapter *adapter)
+static int et131x_handle_recv_pkts(struct et131x_adapter *adapter, int budget)
 {
        struct rfd *rfd = NULL;
-       u32 count = 0;
+       int count = 0;
+       int limit = budget;
        bool done = true;
        struct rx_ring *rx_ring = &adapter->rx_ring;
 
+       if (budget > MAX_PACKETS_HANDLED)
+               limit = MAX_PACKETS_HANDLED;
+
        /* Process up to available RFD's */
-       while (count < NUM_PACKETS_HANDLED) {
+       while (count < limit) {
                if (list_empty(&rx_ring->recv_list)) {
                        WARN_ON(rx_ring->num_ready_recv != 0);
                        done = false;
@@ -2659,13 +2592,15 @@ static void et131x_handle_recv_interrupt(struct et131x_adapter *adapter)
                count++;
        }
 
-       if (count == NUM_PACKETS_HANDLED || !done) {
+       if (count == limit || !done) {
                rx_ring->unfinished_receives = true;
                writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO,
                       &adapter->regs->global.watchdog_timer);
        } else
                /* Watchdog timer will disable itself if appropriate. */
                rx_ring->unfinished_receives = false;
+
+       return count;
 }
 
 /* et131x_tx_dma_memory_alloc
@@ -3151,14 +3086,14 @@ static void et131x_free_busy_send_packets(struct et131x_adapter *adapter)
        tx_ring->used = 0;
 }
 
-/* et131x_handle_send_interrupt - Interrupt handler for sending processing
+/* et131x_handle_send_pkts - Interrupt handler for sending processing
  *
  * Re-claim the send resources, complete sends and get more to send from
  * the send wait queue.
  *
  * Assumption - Send spinlock has been acquired
  */
-static void et131x_handle_send_interrupt(struct et131x_adapter *adapter)
+static void et131x_handle_send_pkts(struct et131x_adapter *adapter)
 {
        unsigned long flags;
        u32 serviced;
@@ -3778,9 +3713,9 @@ static void et131x_pci_remove(struct pci_dev *pdev)
        struct et131x_adapter *adapter = netdev_priv(netdev);
 
        unregister_netdev(netdev);
+       netif_napi_del(&adapter->napi);
        phy_disconnect(adapter->phydev);
        mdiobus_unregister(adapter->mii_bus);
-       cancel_work_sync(&adapter->task);
        kfree(adapter->mii_bus->irq);
        mdiobus_free(adapter->mii_bus);
 
@@ -3860,6 +3795,7 @@ static irqreturn_t et131x_isr(int irq, void *dev_id)
        bool handled = true;
        struct net_device *netdev = (struct net_device *)dev_id;
        struct et131x_adapter *adapter = netdev_priv(netdev);
+       struct address_map __iomem *iomem = adapter->regs;
        struct rx_ring *rx_ring = &adapter->rx_ring;
        struct tx_ring *tx_ring = &adapter->tx_ring;
        u32 status;
@@ -3896,7 +3832,6 @@ static irqreturn_t et131x_isr(int irq, void *dev_id)
        }
 
        /* This is our interrupt, so process accordingly */
-
        if (status & ET_INTR_WATCHDOG) {
                struct tcb *tcb = tx_ring->send_head;
 
@@ -3912,56 +3847,10 @@ static irqreturn_t et131x_isr(int irq, void *dev_id)
                status &= ~ET_INTR_WATCHDOG;
        }
 
-       if (!status) {
-               /* This interrupt has in some way been "handled" by
-                * the ISR. Either it was a spurious Rx interrupt, or
-                * it was a Tx interrupt that has been filtered by
-                * the ISR.
-                */
-               et131x_enable_interrupts(adapter);
-               goto out;
-       }
+       if (status & (ET_INTR_RXDMA_XFR_DONE | ET_INTR_TXDMA_ISR))
+               napi_schedule(&adapter->napi);
 
-       /* We need to save the interrupt status value for use in our
-        * DPC. We will clear the software copy of that in that
-        * routine.
-        */
-       adapter->stats.interrupt_status = status;
-
-       /* Schedule the ISR handler as a bottom-half task in the
-        * kernel's tq_immediate queue, and mark the queue for
-        * execution
-        */
-       schedule_work(&adapter->task);
-out:
-       return IRQ_RETVAL(handled);
-}
-
-/* et131x_isr_handler - The ISR handler
- *
- * scheduled to run in a deferred context by the ISR. This is where the ISR's
- * work actually gets done.
- */
-static void et131x_isr_handler(struct work_struct *work)
-{
-       struct et131x_adapter *adapter =
-               container_of(work, struct et131x_adapter, task);
-       u32 status = adapter->stats.interrupt_status;
-       struct address_map __iomem *iomem = adapter->regs;
-
-       /* These first two are by far the most common.  Once handled, we clear
-        * their two bits in the status word.  If the word is now zero, we
-        * exit.
-        */
-       /* Handle all the completed Transmit interrupts */
-       if (status & ET_INTR_TXDMA_ISR)
-               et131x_handle_send_interrupt(adapter);
-
-       /* Handle all the completed Receives interrupts */
-       if (status & ET_INTR_RXDMA_XFR_DONE)
-               et131x_handle_recv_interrupt(adapter);
-
-       status &= ~(ET_INTR_TXDMA_ERR | ET_INTR_RXDMA_XFR_DONE);
+       status &= ~(ET_INTR_TXDMA_ISR | ET_INTR_RXDMA_XFR_DONE);
 
        if (!status)
                goto out;
@@ -4111,8 +4000,34 @@ static void et131x_isr_handler(struct work_struct *work)
                 * addressed module is in a power-down state and can't respond.
                 */
        }
+
+       if (!status) {
+               /* This interrupt has in some way been "handled" by
+                * the ISR. Either it was a spurious Rx interrupt, or
+                * it was a Tx interrupt that has been filtered by
+                * the ISR.
+                */
+               et131x_enable_interrupts(adapter);
+       }
+
 out:
-       et131x_enable_interrupts(adapter);
+       return IRQ_RETVAL(handled);
+}
+
+static int et131x_poll(struct napi_struct *napi, int budget)
+{
+       struct et131x_adapter *adapter =
+               container_of(napi, struct et131x_adapter, napi);
+       int work_done = et131x_handle_recv_pkts(adapter, budget);
+
+       et131x_handle_send_pkts(adapter);
+
+       if (work_done < budget) {
+               napi_complete(&adapter->napi);
+               et131x_enable_interrupts(adapter);
+       }
+
+       return work_done;
 }
 
 /* et131x_stats - Return the current device statistics  */
@@ -4181,6 +4096,8 @@ static int et131x_open(struct net_device *netdev)
 
        adapter->flags |= FMP_ADAPTER_INTERRUPT_IN_USE;
 
+       napi_enable(&adapter->napi);
+
        et131x_up(netdev);
 
        return result;
@@ -4192,6 +4109,7 @@ static int et131x_close(struct net_device *netdev)
        struct et131x_adapter *adapter = netdev_priv(netdev);
 
        et131x_down(netdev);
+       napi_disable(&adapter->napi);
 
        adapter->flags &= ~FMP_ADAPTER_INTERRUPT_IN_USE;
        free_irq(adapter->pdev->irq, netdev);
@@ -4434,8 +4352,6 @@ static int et131x_change_mtu(struct net_device *netdev, int new_mtu)
                return -EINVAL;
 
        et131x_disable_txrx(netdev);
-       et131x_handle_send_interrupt(adapter);
-       et131x_handle_recv_interrupt(adapter);
 
        /* Set the new MTU */
        netdev->mtu = new_mtu;
@@ -4468,57 +4384,6 @@ static int et131x_change_mtu(struct net_device *netdev, int new_mtu)
        return result;
 }
 
-/* et131x_set_mac_addr - handler to change the MAC address for the device */
-static int et131x_set_mac_addr(struct net_device *netdev, void *new_mac)
-{
-       int result = 0;
-       struct et131x_adapter *adapter = netdev_priv(netdev);
-       struct sockaddr *address = new_mac;
-
-       if (adapter == NULL)
-               return -ENODEV;
-
-       /* Make sure the requested MAC is valid */
-       if (!is_valid_ether_addr(address->sa_data))
-               return -EADDRNOTAVAIL;
-
-       et131x_disable_txrx(netdev);
-       et131x_handle_send_interrupt(adapter);
-       et131x_handle_recv_interrupt(adapter);
-
-       /* Set the new MAC */
-       /* netdev->set_mac_address  = &new_mac; */
-
-       memcpy(netdev->dev_addr, address->sa_data, netdev->addr_len);
-
-       netdev_info(netdev, "Setting MAC address to %pM\n",
-                   netdev->dev_addr);
-
-       /* Free Rx DMA memory */
-       et131x_adapter_memory_free(adapter);
-
-       et131x_soft_reset(adapter);
-
-       /* Alloc and init Rx DMA memory */
-       result = et131x_adapter_memory_alloc(adapter);
-       if (result != 0) {
-               dev_err(&adapter->pdev->dev,
-                       "Change MAC failed; couldn't re-alloc DMA memory\n");
-               return result;
-       }
-
-       et131x_init_send(adapter);
-
-       et131x_hwaddr_init(adapter);
-
-       /* Init the device with the new settings */
-       et131x_adapter_setup(adapter);
-
-       et131x_enable_txrx(netdev);
-
-       return result;
-}
-
 static const struct net_device_ops et131x_netdev_ops = {
        .ndo_open               = et131x_open,
        .ndo_stop               = et131x_close,
@@ -4526,7 +4391,7 @@ static const struct net_device_ops et131x_netdev_ops = {
        .ndo_set_rx_mode        = et131x_multicast,
        .ndo_tx_timeout         = et131x_tx_timeout,
        .ndo_change_mtu         = et131x_change_mtu,
-       .ndo_set_mac_address    = et131x_set_mac_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_get_stats          = et131x_stats,
        .ndo_do_ioctl           = et131x_ioctl,
@@ -4625,8 +4490,7 @@ static int et131x_pci_setup(struct pci_dev *pdev,
        /* Init send data structures */
        et131x_init_send(adapter);
 
-       /* Set up the task structure for the ISR's deferred handler */
-       INIT_WORK(&adapter->task, et131x_isr_handler);
+       netif_napi_add(netdev, &adapter->napi, et131x_poll, 64);
 
        /* Copy address into the net_device struct */
        memcpy(netdev->dev_addr, adapter->addr, ETH_ALEN);
This page took 0.030609 seconds and 5 git commands to generate.