return received;
 }
 
+static bool macb_rx_pending(struct macb_queue *queue)
+{
+       struct macb *bp = queue->bp;
+       unsigned int            entry;
+       struct macb_dma_desc    *desc;
+
+       entry = macb_rx_ring_wrap(bp, queue->rx_tail);
+       desc = macb_rx_desc(queue, entry);
+
+       /* Make hw descriptor updates visible to CPU */
+       rmb();
+
+       return (desc->addr & MACB_BIT(RX_USED)) != 0;
+}
+
 static int macb_poll(struct napi_struct *napi, int budget)
 {
        struct macb_queue *queue = container_of(napi, struct macb_queue, napi);
        struct macb *bp = queue->bp;
        int work_done;
-       u32 status;
 
-       status = macb_readl(bp, RSR);
-       macb_writel(bp, RSR, status);
+       work_done = bp->macbgem_ops.mog_rx(queue, napi, budget);
 
-       netdev_vdbg(bp->dev, "poll: status = %08lx, budget = %d\n",
-                   (unsigned long)status, budget);
+       netdev_vdbg(bp->dev, "poll: queue = %u, work_done = %d, budget = %d\n",
+                   (unsigned int)(queue - bp->queues), work_done, budget);
 
-       work_done = bp->macbgem_ops.mog_rx(queue, napi, budget);
-       if (work_done < budget) {
-               napi_complete_done(napi, work_done);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
+               queue_writel(queue, IER, bp->rx_intr_mask);
 
-               /* RSR bits only seem to propagate to raise interrupts when
-                * interrupts are enabled at the time, so if bits are already
-                * set due to packets received while interrupts were disabled,
+               /* Packet completions only seem to propagate to raise
+                * interrupts when interrupts are enabled at the time, so if
+                * packets were received while interrupts were disabled,
                 * they will not cause another interrupt to be generated when
                 * interrupts are re-enabled.
-                * Check for this case here. This has been seen to happen
-                * around 30% of the time under heavy network load.
+                * Check for this case here to avoid losing a wakeup. This can
+                * potentially race with the interrupt handler doing the same
+                * actions if an interrupt is raised just after enabling them,
+                * but this should be harmless.
                 */
-               status = macb_readl(bp, RSR);
-               if (status) {
+               if (macb_rx_pending(queue)) {
+                       queue_writel(queue, IDR, bp->rx_intr_mask);
                        if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
                                queue_writel(queue, ISR, MACB_BIT(RCOMP));
-                       napi_reschedule(napi);
-               } else {
-                       queue_writel(queue, IER, bp->rx_intr_mask);
-
-                       /* In rare cases, packets could have been received in
-                        * the window between the check above and re-enabling
-                        * interrupts. Therefore, a double-check is required
-                        * to avoid losing a wakeup. This can potentially race
-                        * with the interrupt handler doing the same actions
-                        * if an interrupt is raised just after enabling them,
-                        * but this should be harmless.
-                        */
-                       status = macb_readl(bp, RSR);
-                       if (unlikely(status)) {
-                               queue_writel(queue, IDR, bp->rx_intr_mask);
-                               if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
-                                       queue_writel(queue, ISR, MACB_BIT(RCOMP));
-                               napi_schedule(napi);
-                       }
+                       netdev_vdbg(bp->dev, "poll: packets pending, reschedule\n");
+                       napi_schedule(napi);
                }
        }