Author: cem
Date: Mon Aug 22 14:51:07 2016
New Revision: 304602
URL: https://svnweb.freebsd.org/changeset/base/304602

Log:
  ioat(4): Don't process events past queue head
  
  Fix a race where the completion routine could overrun the active ring
  area in some situations.

Modified:
  head/sys/dev/ioat/ioat.c

Modified: head/sys/dev/ioat/ioat.c
==============================================================================
--- head/sys/dev/ioat/ioat.c    Mon Aug 22 13:43:25 2016        (r304601)
+++ head/sys/dev/ioat/ioat.c    Mon Aug 22 14:51:07 2016        (r304602)
@@ -678,19 +678,12 @@ ioat_process_events(struct ioat_softc *i
        }
 
        completed = 0;
-       comp_update = *ioat->comp_update;
+       comp_update = ioat_get_chansts(ioat);
+       CTR4(KTR_IOAT, "%s channel=%u hw_status=0x%lx last_seen=0x%lx",
+           __func__, ioat->chan_idx, comp_update, ioat->last_seen);
        status = comp_update & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK;
 
-       if (status == ioat->last_seen) {
-               /*
-                * If we landed in process_events and nothing has been
-                * completed, check for a timeout due to channel halt.
-                */
-               comp_update = ioat_get_chansts(ioat);
-               goto out;
-       }
-
-       while (1) {
+       while (ioat_get_active(ioat) > 0) {
                desc = ioat_get_ring_entry(ioat, ioat->tail);
                dmadesc = &desc->bus_dmadesc;
                CTR4(KTR_IOAT, "channel=%u completing desc %u ok  cb %p(%p)",
@@ -704,17 +697,13 @@ ioat_process_events(struct ioat_softc *i
                ioat->tail++;
                if (desc->hw_desc_bus_addr == status)
                        break;
-
-               KASSERT(ioat_get_active(ioat) > 0, ("overrunning ring t:%u "
-                   "h:%u st:0x%016lx last_seen:%016lx completed:%u\n",
-                   ioat->tail, ioat->head, comp_update, ioat->last_seen,
-                   completed));
        }
 
-       ioat->last_seen = desc->hw_desc_bus_addr;
-       ioat->stats.descriptors_processed += completed;
+       if (completed != 0) {
+               ioat->last_seen = desc->hw_desc_bus_addr;
+               ioat->stats.descriptors_processed += completed;
+       }
 
-out:
        ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN);
 
        /* Perform a racy check first; only take the locks if it passes. */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to