This fixes several bugs in the diagnostic buffer code in the mpr(4) and mps(4) drivers.
There are times when the driver reinitializes the firmware, and that could cause panics. We also fail to check the status of bus_dmamap_load() and we return incorrect status if we fail to create a busdma tag.
The commit messages for the mpr(4) driver in Spectra's repository are below. The mps(4) driver is pretty much the same.
Change 1341263 on 2017/11/21 by kenm@ken.redline14
Fix several bugs in the diagnostic path in mpr_user.c. o In mpr_post_fw_diag_buffer() and mpr_release_fw_diag_buffer(), check the reply to see whether it is NULL. It can be NULL (and the command non-NULL) if the controller gets reinitialized while we're waiting for the command to complete but the driver structures aren't reallocated. The driver structures generally won't be reallocated unless there is a firmware upgrade that changes one of the IOCFacts. o When freeing diagnostic buffers in mpr_diag_register() and mpr_diag_unregister(), zero/NULL out the buffer after freeing it. This will prevent a duplicate free in some situations.
Change 1343313 on 2017/12/06 by kenm@ken.redline14
Fix a couple of busdma issues in the mpr(4) driver. In mpr_diag_register(), which is used to register diagnostic buffers with the mpr(4) firmware, we allocate DMAable memory. There were several issues here: o No checking of the bus_dmamap_load() return value. If the load failed or got deferred, mpr_diag_register() continued on as if nothing had happened. We now check the return value and bail out if it fails. o No waiting for a deferred load callback. bus_dmamap_load() calls a supplied callback when the mapping is done. This is generally done immediately, but it can be deferred. mpr_diag_register() did not check to see whether the callback was already done before proceeding on. We now sleep until the callback is done if it is deferred. o No call to bus_dmamap_sync(... BUS_DMASYNC_PREREAD) after the memory is allocated and loaded. This is necessary on some platforms to synchronize host memory that is going to be updated by a device. mprvar.h: Add a new structure, struct mpr_busdma_context, that is used for deferred busdma load callbacks. Add a prototype for mpr_memaddr_wait_cb(). mpr.c: Add a new busdma callback function, mpr_memaddr_wait_cb(). This provides synchronization for callers that want to wait on a deferred bus_dmamap_load() callback. mpr_user.c: In bus_dmamap_register(), add a call to bus_dmamap_sync() with the BUS_DMASYNC_PREREAD flag set after an allocation is loaded. Also, check the return value of bus_dmamap_load(). If it fails, bail out. If it is EINPROGRESS, wait for the callback to happen. We use an interruptible sleep (msleep with PCATCH) and let the callback clean things up if we get interrupted.
Change 1343965 on 2017/12/11 by kenm@ken.redline14
Fix a return value in mpr_diag_register(). In the case of a failure to create a busdma tag, we were returning ENOMEM instead of MPR_DIAG_FAILURE. The caller expects an MPR_ status returned, not an errno.