#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
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;
int index = 0;
int retries;
int err = 0;
- int i2c_wack = 0;
int writeok = 0;
u32 status;
u32 val = 0;
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++) {
*/
udelay(10);
- while (i2c_wack) {
+ while (1) {
if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER,
LBCIF_CONTROL_LBCIF_ENABLE))
writeok = 0;
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);
* 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) |
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
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;
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
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;
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);
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;
}
/* This is our interrupt, so process accordingly */
-
if (status & ET_INTR_WATCHDOG) {
struct tcb *tcb = tx_ring->send_head;
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;
* 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 */
adapter->flags |= FMP_ADAPTER_INTERRUPT_IN_USE;
+ napi_enable(&adapter->napi);
+
et131x_up(netdev);
return result;
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);
return -EINVAL;
et131x_disable_txrx(netdev);
- et131x_handle_send_interrupt(adapter);
- et131x_handle_recv_interrupt(adapter);
/* Set the new MTU */
netdev->mtu = 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,
.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,
/* 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);