mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
scsi: esp: Defer command completion until previous interrupts have been handled
The guest OS reads RSTAT, RSEQ, and RINTR, and expects those registers to reflect a consistent state. However, it is possible that the registers can change after RSTAT was read, but before RINTR is read, when esp_command_complete() is called. Guest OS qemu -------- ---- [handle interrupt] Read RSTAT esp_command_complete() RSTAT = STAT_ST esp_dma_done() RSTAT |= STAT_TC RSEQ = 0 RINTR = INTR_BS Read RSEQ Read RINTR RINTR = 0 RSTAT &= ~STAT_TC RSEQ = SEQ_CD The guest OS would then try to handle INTR_BS combined with an old value of RSTAT. This sometimes resulted in lost events, spurious interrupts, guest OS confusion, and stalled SCSI operations. A typical guest error log (observed with various versions of Linux) looks as follows. scsi host1: Spurious irq, sreg=13. ... scsi host1: Aborting command [84531f10:2a] scsi host1: Current command [f882eea8:35] scsi host1: Queued command [84531f10:2a] scsi host1: Active command [f882eea8:35] scsi host1: Dumping command log scsi host1: ent[15] CMD val[44] sreg[90] seqreg[00] sreg2[00] ireg[20] ss[00] event[0c] scsi host1: ent[16] CMD val[01] sreg[90] seqreg[00] sreg2[00] ireg[20] ss[02] event[0c] scsi host1: ent[17] CMD val[43] sreg[90] seqreg[00] sreg2[00] ireg[20] ss[02] event[0c] scsi host1: ent[18] EVENT val[0d] sreg[92] seqreg[04] sreg2[00] ireg[18] ss[00] event[0c] ... Defer handling command completion until previous interrupts have been handled to fix the problem. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
c2d6eeda01
commit
ea84a44250
4 changed files with 31 additions and 9 deletions
|
@ -167,6 +167,7 @@ esp_handle_satn_stop(uint32_t cmdlen) "cmdlen %d"
|
|||
esp_write_response(uint32_t status) "Transfer status (status=%d)"
|
||||
esp_do_dma(uint32_t cmdlen, uint32_t len) "command len %d + %d"
|
||||
esp_command_complete(void) "SCSI Command complete"
|
||||
esp_command_complete_deferred(void) "SCSI Command complete deferred"
|
||||
esp_command_complete_unexpected(void) "SCSI command completed unexpectedly"
|
||||
esp_command_complete_fail(void) "Command failed"
|
||||
esp_transfer_data(uint32_t dma_left, int32_t ti_size) "transfer %d/%d"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue