--- a/sys/dev/disk/advansys/advansys.c +++ b/sys/dev/disk/advansys/advansys.c @@ -1089,6 +1089,27 @@ #endif adv->cur_active -= sg_queue_cnt + 1; + /* + * DF-4349: ccb_index is a raw 32-bit value written by the + * RISC into LRAM. Never-allocated slots (the array is + * kmalloc'd without M_ZERO) and slots that were already + * completed (ACCB_FREE, stale cinfo->ccb) used to be + * completed a second time: double xpt_done, LIST_REMOVE of + * a detached CCB, callout_stop/dmamap_unload on recycled + * resources. Only an ACCB_ACTIVE ccb_info may complete. + */ + if (scsiq.d2.ccb_index >= adv->ccb_infos_allocated + || (adv->ccb_infos[scsiq.d2.ccb_index].state + & ACCB_ACTIVE) == 0) { + kprintf("%s: done queue ccb_index %d not active, " + "dropping completion\n", adv_name(adv), + scsiq.d2.ccb_index); + doneq_head = done_qno; + done_qno = adv_read_lram_8(adv, done_qaddr + + ADV_SCSIQ_B_FWD); + continue; + } + if ((scsiq.q_status != QS_DONE) && (scsiq.q_status & QS_ABORTED) == 0) panic("adv_qdone: completed scsiq with unknown status"); @@ -1294,7 +1315,7 @@ * upper level SCSI transaction it represents. */ adv->ccb_infos = kmalloc(sizeof(*adv->ccb_infos) * adv->max_openings, - M_DEVBUF, M_WAITOK); + M_DEVBUF, M_WAITOK | M_ZERO); adv->init_level++; /*