ioat(4): Use memory completion rather than device register
The CHANSTS register is a split 64-bit register on CBDMA units before hardware v3.3. If a torn read happens during ioat_process_events(), software cannot know when to stop completing descriptors correctly. So, just use the device-pushed main memory channel status instead. Remove the ioat_get_active() seatbelt as well. It does nothing if the completion address is valid. Sponsored by: Dell EMC Isilon
This commit is contained in:
parent
452397fbf4
commit
7ea1be6e5b
@ -677,7 +677,7 @@ ioat_process_events(struct ioat_softc *ioat)
|
|||||||
}
|
}
|
||||||
|
|
||||||
completed = 0;
|
completed = 0;
|
||||||
comp_update = ioat_get_chansts(ioat);
|
comp_update = *ioat->comp_update;
|
||||||
status = comp_update & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK;
|
status = comp_update & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK;
|
||||||
|
|
||||||
if (status == ioat->last_seen) {
|
if (status == ioat->last_seen) {
|
||||||
@ -691,7 +691,7 @@ ioat_process_events(struct ioat_softc *ioat)
|
|||||||
__func__, ioat->chan_idx, comp_update, ioat->last_seen);
|
__func__, ioat->chan_idx, comp_update, ioat->last_seen);
|
||||||
|
|
||||||
desc = ioat_get_ring_entry(ioat, ioat->tail - 1);
|
desc = ioat_get_ring_entry(ioat, ioat->tail - 1);
|
||||||
while (desc->hw_desc_bus_addr != status && ioat_get_active(ioat) > 0) {
|
while (desc->hw_desc_bus_addr != status) {
|
||||||
desc = ioat_get_ring_entry(ioat, ioat->tail);
|
desc = ioat_get_ring_entry(ioat, ioat->tail);
|
||||||
dmadesc = &desc->bus_dmadesc;
|
dmadesc = &desc->bus_dmadesc;
|
||||||
CTR5(KTR_IOAT, "channel=%u completing desc idx %u (%p) ok cb %p(%p)",
|
CTR5(KTR_IOAT, "channel=%u completing desc idx %u (%p) ok cb %p(%p)",
|
||||||
|
@ -523,6 +523,15 @@ struct ioat_softc {
|
|||||||
void ioat_test_attach(void);
|
void ioat_test_attach(void);
|
||||||
void ioat_test_detach(void);
|
void ioat_test_detach(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX DO NOT USE this routine for obtaining the current completed descriptor.
|
||||||
|
*
|
||||||
|
* The double_4 read on ioat<3.3 appears to result in torn reads. And v3.2
|
||||||
|
* hardware is still commonplace (Broadwell Xeon has it). Instead, use the
|
||||||
|
* device-pushed *comp_update.
|
||||||
|
*
|
||||||
|
* It is safe to use ioat_get_chansts() for the low status bits.
|
||||||
|
*/
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
ioat_get_chansts(struct ioat_softc *ioat)
|
ioat_get_chansts(struct ioat_softc *ioat)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user